mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-14 11:47:38 +00:00
feat(login): additionally use email/phone for authentication (#4563)
* feat: add ability to disable login by email and phone * feat: check login by email and phone * fix: set verified email / phone correctly on notify users * update projection version * fix merge * fix email/phone verified reduce tests * fix user tests * loginname check * cleanup * fix: update user projection version to handle fixed statement
This commit is contained in:
@@ -442,7 +442,7 @@ func (s *Server) importData(ctx context.Context, orgs []*admin_pb.DataOrg) (*adm
|
||||
}
|
||||
}
|
||||
if org.LoginPolicy != nil {
|
||||
_, err = s.command.AddLoginPolicy(ctx, org.GetOrgId(), management.AddLoginPolicyToDomain(org.GetLoginPolicy()))
|
||||
_, err = s.command.AddLoginPolicy(ctx, org.GetOrgId(), management.AddLoginPolicyToCommand(org.GetLoginPolicy()))
|
||||
if err != nil {
|
||||
errors = append(errors, &admin_pb.ImportDataError{Type: "login_policy", Id: org.GetOrgId(), Message: err.Error()})
|
||||
}
|
||||
|
@@ -22,14 +22,14 @@ func (s *Server) GetLoginPolicy(ctx context.Context, _ *admin_pb.GetLoginPolicyR
|
||||
}
|
||||
|
||||
func (s *Server) UpdateLoginPolicy(ctx context.Context, p *admin_pb.UpdateLoginPolicyRequest) (*admin_pb.UpdateLoginPolicyResponse, error) {
|
||||
policy, err := s.command.ChangeDefaultLoginPolicy(ctx, updateLoginPolicyToDomain(p))
|
||||
policy, err := s.command.ChangeDefaultLoginPolicy(ctx, updateLoginPolicyToCommand(p))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &admin_pb.UpdateLoginPolicyResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
policy.Sequence,
|
||||
policy.ChangeDate,
|
||||
policy.EventDate,
|
||||
policy.ResourceOwner,
|
||||
),
|
||||
}, nil
|
||||
|
@@ -3,13 +3,13 @@ package admin
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
policy_grpc "github.com/zitadel/zitadel/internal/api/grpc/policy"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
admin_pb "github.com/zitadel/zitadel/pkg/grpc/admin"
|
||||
)
|
||||
|
||||
func updateLoginPolicyToDomain(p *admin_pb.UpdateLoginPolicyRequest) *domain.LoginPolicy {
|
||||
return &domain.LoginPolicy{
|
||||
func updateLoginPolicyToCommand(p *admin_pb.UpdateLoginPolicyRequest) *command.ChangeLoginPolicy {
|
||||
return &command.ChangeLoginPolicy{
|
||||
AllowUsernamePassword: p.AllowUsernamePassword,
|
||||
AllowRegister: p.AllowRegister,
|
||||
AllowExternalIDP: p.AllowExternalIdp,
|
||||
@@ -18,6 +18,8 @@ func updateLoginPolicyToDomain(p *admin_pb.UpdateLoginPolicyRequest) *domain.Log
|
||||
HidePasswordReset: p.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: p.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: p.AllowDomainDiscovery,
|
||||
DisableLoginWithEmail: p.DisableLoginWithEmail,
|
||||
DisableLoginWithPhone: p.DisableLoginWithPhone,
|
||||
DefaultRedirectURI: p.DefaultRedirectUri,
|
||||
PasswordCheckLifetime: p.PasswordCheckLifetime.AsDuration(),
|
||||
ExternalLoginCheckLifetime: p.ExternalLoginCheckLifetime.AsDuration(),
|
||||
|
@@ -30,28 +30,28 @@ func (s *Server) GetDefaultLoginPolicy(ctx context.Context, req *mgmt_pb.GetDefa
|
||||
}
|
||||
|
||||
func (s *Server) AddCustomLoginPolicy(ctx context.Context, req *mgmt_pb.AddCustomLoginPolicyRequest) (*mgmt_pb.AddCustomLoginPolicyResponse, error) {
|
||||
policy, err := s.command.AddLoginPolicy(ctx, authz.GetCtxData(ctx).OrgID, AddLoginPolicyToDomain(req))
|
||||
policy, err := s.command.AddLoginPolicy(ctx, authz.GetCtxData(ctx).OrgID, AddLoginPolicyToCommand(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.AddCustomLoginPolicyResponse{
|
||||
Details: object.AddToDetailsPb(
|
||||
policy.Sequence,
|
||||
policy.ChangeDate,
|
||||
policy.EventDate,
|
||||
policy.ResourceOwner,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) UpdateCustomLoginPolicy(ctx context.Context, req *mgmt_pb.UpdateCustomLoginPolicyRequest) (*mgmt_pb.UpdateCustomLoginPolicyResponse, error) {
|
||||
policy, err := s.command.ChangeLoginPolicy(ctx, authz.GetCtxData(ctx).OrgID, updateLoginPolicyToDomain(req))
|
||||
policy, err := s.command.ChangeLoginPolicy(ctx, authz.GetCtxData(ctx).OrgID, updateLoginPolicyToCommand(req))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &mgmt_pb.UpdateCustomLoginPolicyResponse{
|
||||
Details: object.ChangeToDetailsPb(
|
||||
policy.Sequence,
|
||||
policy.ChangeDate,
|
||||
policy.EventDate,
|
||||
policy.ResourceOwner,
|
||||
),
|
||||
}, nil
|
||||
|
@@ -4,13 +4,13 @@ import (
|
||||
idp_grpc "github.com/zitadel/zitadel/internal/api/grpc/idp"
|
||||
"github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||
policy_grpc "github.com/zitadel/zitadel/internal/api/grpc/policy"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/command"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
mgmt_pb "github.com/zitadel/zitadel/pkg/grpc/management"
|
||||
)
|
||||
|
||||
func AddLoginPolicyToDomain(p *mgmt_pb.AddCustomLoginPolicyRequest) *domain.LoginPolicy {
|
||||
return &domain.LoginPolicy{
|
||||
func AddLoginPolicyToCommand(p *mgmt_pb.AddCustomLoginPolicyRequest) *command.AddLoginPolicy {
|
||||
return &command.AddLoginPolicy{
|
||||
AllowUsernamePassword: p.AllowUsernamePassword,
|
||||
AllowRegister: p.AllowRegister,
|
||||
AllowExternalIDP: p.AllowExternalIdp,
|
||||
@@ -27,22 +27,24 @@ func AddLoginPolicyToDomain(p *mgmt_pb.AddCustomLoginPolicyRequest) *domain.Logi
|
||||
MultiFactorCheckLifetime: p.MultiFactorCheckLifetime.AsDuration(),
|
||||
SecondFactors: policy_grpc.SecondFactorsTypesToDomain(p.SecondFactors),
|
||||
MultiFactors: policy_grpc.MultiFactorsTypesToDomain(p.MultiFactors),
|
||||
IDPProviders: addLoginPolicyIDPsToDomain(p.Idps),
|
||||
IDPProviders: addLoginPolicyIDPsToCommand(p.Idps),
|
||||
DisableLoginWithEmail: p.DisableLoginWithEmail,
|
||||
DisableLoginWithPhone: p.DisableLoginWithPhone,
|
||||
}
|
||||
}
|
||||
func addLoginPolicyIDPsToDomain(idps []*mgmt_pb.AddCustomLoginPolicyRequest_IDP) []*domain.IDPProvider {
|
||||
providers := make([]*domain.IDPProvider, len(idps))
|
||||
func addLoginPolicyIDPsToCommand(idps []*mgmt_pb.AddCustomLoginPolicyRequest_IDP) []*command.AddLoginPolicyIDP {
|
||||
providers := make([]*command.AddLoginPolicyIDP, len(idps))
|
||||
for i, idp := range idps {
|
||||
providers[i] = &domain.IDPProvider{
|
||||
Type: idp_grpc.IDPProviderTypeFromPb(idp.OwnerType),
|
||||
IDPConfigID: idp.IdpId,
|
||||
providers[i] = &command.AddLoginPolicyIDP{
|
||||
Type: idp_grpc.IDPProviderTypeFromPb(idp.OwnerType),
|
||||
ConfigID: idp.IdpId,
|
||||
}
|
||||
}
|
||||
return providers
|
||||
}
|
||||
|
||||
func updateLoginPolicyToDomain(p *mgmt_pb.UpdateCustomLoginPolicyRequest) *domain.LoginPolicy {
|
||||
return &domain.LoginPolicy{
|
||||
func updateLoginPolicyToCommand(p *mgmt_pb.UpdateCustomLoginPolicyRequest) *command.ChangeLoginPolicy {
|
||||
return &command.ChangeLoginPolicy{
|
||||
AllowUsernamePassword: p.AllowUsernamePassword,
|
||||
AllowRegister: p.AllowRegister,
|
||||
AllowExternalIDP: p.AllowExternalIdp,
|
||||
@@ -51,6 +53,8 @@ func updateLoginPolicyToDomain(p *mgmt_pb.UpdateCustomLoginPolicyRequest) *domai
|
||||
HidePasswordReset: p.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: p.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: p.AllowDomainDiscovery,
|
||||
DisableLoginWithEmail: p.DisableLoginWithEmail,
|
||||
DisableLoginWithPhone: p.DisableLoginWithPhone,
|
||||
DefaultRedirectURI: p.DefaultRedirectUri,
|
||||
PasswordCheckLifetime: p.PasswordCheckLifetime.AsDuration(),
|
||||
ExternalLoginCheckLifetime: p.ExternalLoginCheckLifetime.AsDuration(),
|
||||
|
@@ -22,6 +22,8 @@ func ModelLoginPolicyToPb(policy *query.LoginPolicy) *policy_pb.LoginPolicy {
|
||||
HidePasswordReset: policy.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: policy.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: policy.AllowDomainDiscovery,
|
||||
DisableLoginWithEmail: policy.DisableLoginWithEmail,
|
||||
DisableLoginWithPhone: policy.DisableLoginWithPhone,
|
||||
DefaultRedirectUri: policy.DefaultRedirectURI,
|
||||
PasswordCheckLifetime: durationpb.New(policy.PasswordCheckLifetime),
|
||||
ExternalLoginCheckLifetime: durationpb.New(policy.ExternalLoginCheckLifetime),
|
||||
|
@@ -641,15 +641,9 @@ func (repo *AuthRequestRepo) checkLoginName(ctx context.Context, request *domain
|
||||
preferredLoginName += "@" + request.RequestedPrimaryDomain
|
||||
}
|
||||
}
|
||||
user, err = repo.View.UserByLoginNameAndResourceOwner(preferredLoginName, request.RequestedOrgID, request.InstanceID)
|
||||
user, err = repo.checkLoginNameInputForResourceOwner(request, preferredLoginName)
|
||||
} else {
|
||||
user, err = repo.View.UserByLoginName(loginName, request.InstanceID)
|
||||
if err == nil {
|
||||
err = repo.checkLoginPolicyWithResourceOwner(ctx, request, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
user, err = repo.checkLoginNameInput(ctx, request, preferredLoginName)
|
||||
}
|
||||
// return any error apart from not found ones directly
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
@@ -720,8 +714,74 @@ func (repo *AuthRequestRepo) checkDomainDiscovery(ctx context.Context, request *
|
||||
return true
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) checkLoginPolicyWithResourceOwner(ctx context.Context, request *domain.AuthRequest, user *user_view_model.UserView) error {
|
||||
loginPolicy, idpProviders, err := repo.getLoginPolicyAndIDPProviders(ctx, user.ResourceOwner)
|
||||
func (repo *AuthRequestRepo) checkLoginNameInput(ctx context.Context, request *domain.AuthRequest, loginNameInput string) (*user_view_model.UserView, error) {
|
||||
// always check the loginname first
|
||||
user, err := repo.View.UserByLoginName(loginNameInput, request.InstanceID)
|
||||
if err == nil {
|
||||
// and take the user regardless if there would be a user with that email or phone
|
||||
return user, repo.checkLoginPolicyWithResourceOwner(ctx, request, user.ResourceOwner)
|
||||
}
|
||||
user, emailErr := repo.View.UserByEmail(loginNameInput, request.InstanceID)
|
||||
if emailErr == nil {
|
||||
// if there was a single user with the specified email
|
||||
// load and check the login policy
|
||||
if emailErr = repo.checkLoginPolicyWithResourceOwner(ctx, request, user.ResourceOwner); emailErr != nil {
|
||||
return nil, emailErr
|
||||
}
|
||||
// and in particular if the login with email is possible
|
||||
// if so take the user (and ignore possible phone matches)
|
||||
if !request.LoginPolicy.DisableLoginWithEmail {
|
||||
return user, nil
|
||||
}
|
||||
}
|
||||
user, phoneErr := repo.View.UserByPhone(loginNameInput, request.InstanceID)
|
||||
if phoneErr == nil {
|
||||
// if there was a single user with the specified phone
|
||||
// load and check the login policy
|
||||
if phoneErr = repo.checkLoginPolicyWithResourceOwner(ctx, request, user.ResourceOwner); phoneErr != nil {
|
||||
return nil, phoneErr
|
||||
}
|
||||
// and in particular if the login with phone is possible
|
||||
// if so take the user
|
||||
if !request.LoginPolicy.DisableLoginWithPhone {
|
||||
return user, nil
|
||||
}
|
||||
}
|
||||
// if we get here the user was not found by loginname
|
||||
// and either there was no match for email or phone as well, or they have been both disabled
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) checkLoginNameInputForResourceOwner(request *domain.AuthRequest, loginNameInput string) (*user_view_model.UserView, error) {
|
||||
// always check the loginname first
|
||||
user, err := repo.View.UserByLoginNameAndResourceOwner(loginNameInput, request.RequestedOrgID, request.InstanceID)
|
||||
if err == nil {
|
||||
// and take the user regardless if there would be a user with that email or phone
|
||||
return user, nil
|
||||
}
|
||||
if request.LoginPolicy != nil && !request.LoginPolicy.DisableLoginWithEmail {
|
||||
// if login by email is allowed and there was a single user with the specified email
|
||||
// take that user (and ignore possible phone number matches)
|
||||
user, emailErr := repo.View.UserByEmailAndResourceOwner(loginNameInput, request.RequestedOrgID, request.InstanceID)
|
||||
if emailErr == nil {
|
||||
return user, nil
|
||||
}
|
||||
}
|
||||
if request.LoginPolicy != nil && !request.LoginPolicy.DisableLoginWithPhone {
|
||||
// if login by phone is allowed and there was a single user with the specified phone
|
||||
// take that user
|
||||
user, phoneErr := repo.View.UserByPhoneAndResourceOwner(loginNameInput, request.RequestedOrgID, request.InstanceID)
|
||||
if phoneErr == nil {
|
||||
return user, nil
|
||||
}
|
||||
}
|
||||
// if we get here the user was not found by loginname
|
||||
// and either there was no match for email or phone as well or they have been both disabled
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) checkLoginPolicyWithResourceOwner(ctx context.Context, request *domain.AuthRequest, resourceOwner string) error {
|
||||
loginPolicy, idpProviders, err := repo.getLoginPolicyAndIDPProviders(ctx, resourceOwner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -758,11 +818,15 @@ func queryLoginPolicyToDomain(policy *query.LoginPolicy) *domain.LoginPolicy {
|
||||
PasswordlessType: policy.PasswordlessType,
|
||||
HidePasswordReset: policy.HidePasswordReset,
|
||||
IgnoreUnknownUsernames: policy.IgnoreUnknownUsernames,
|
||||
AllowDomainDiscovery: policy.AllowDomainDiscovery,
|
||||
DefaultRedirectURI: policy.DefaultRedirectURI,
|
||||
PasswordCheckLifetime: policy.PasswordCheckLifetime,
|
||||
ExternalLoginCheckLifetime: policy.ExternalLoginCheckLifetime,
|
||||
MFAInitSkipLifetime: policy.MFAInitSkipLifetime,
|
||||
SecondFactorCheckLifetime: policy.SecondFactorCheckLifetime,
|
||||
MultiFactorCheckLifetime: policy.MultiFactorCheckLifetime,
|
||||
DisableLoginWithEmail: policy.DisableLoginWithEmail,
|
||||
DisableLoginWithPhone: policy.DisableLoginWithPhone,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -52,10 +52,52 @@ func (v *View) UserByLoginNameAndResourceOwner(loginName, resourceOwner, instanc
|
||||
return v.userByID(instanceID, loginNameQuery, resourceOwnerQuery)
|
||||
}
|
||||
|
||||
func (v *View) UserByEmail(email, instanceID string) (*model.UserView, error) {
|
||||
emailQuery, err := query.NewUserVerifiedEmailSearchQuery(email, query.TextEquals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v.userByID(instanceID, emailQuery)
|
||||
}
|
||||
|
||||
func (v *View) UserByEmailAndResourceOwner(email, resourceOwner, instanceID string) (*model.UserView, error) {
|
||||
emailQuery, err := query.NewUserVerifiedEmailSearchQuery(email, query.TextEquals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resourceOwnerQuery, err := query.NewUserResourceOwnerSearchQuery(resourceOwner, query.TextEquals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return v.userByID(instanceID, emailQuery, resourceOwnerQuery)
|
||||
}
|
||||
|
||||
func (v *View) UserByPhone(phone, instanceID string) (*model.UserView, error) {
|
||||
phoneQuery, err := query.NewUserVerifiedPhoneSearchQuery(phone, query.TextEquals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v.userByID(instanceID, phoneQuery)
|
||||
}
|
||||
|
||||
func (v *View) UserByPhoneAndResourceOwner(phone, resourceOwner, instanceID string) (*model.UserView, error) {
|
||||
phoneQuery, err := query.NewUserVerifiedPhoneSearchQuery(phone, query.TextEquals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resourceOwnerQuery, err := query.NewUserResourceOwnerSearchQuery(resourceOwner, query.TextEquals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return v.userByID(instanceID, phoneQuery, resourceOwnerQuery)
|
||||
}
|
||||
|
||||
func (v *View) userByID(instanceID string, queries ...query.SearchQuery) (*model.UserView, error) {
|
||||
ctx := authz.WithInstanceID(context.Background(), instanceID)
|
||||
|
||||
queriedUser, err := v.query.GetUser(ctx, true, queries...)
|
||||
queriedUser, err := v.query.GetNotifyUser(ctx, true, queries...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -1,11 +1,13 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
api_http "github.com/zitadel/zitadel/internal/api/http"
|
||||
"github.com/zitadel/zitadel/internal/command/preparation"
|
||||
sd "github.com/zitadel/zitadel/internal/config/systemdefaults"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
@@ -132,3 +134,28 @@ func AppendAndReduce(object interface {
|
||||
object.AppendEvents(events...)
|
||||
return object.Reduce()
|
||||
}
|
||||
|
||||
func queryAndReduce(ctx context.Context, filter preparation.FilterToQueryReducer, wm eventstore.QueryReducer) error {
|
||||
events, err := filter(ctx, wm.Query())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(events) == 0 {
|
||||
return nil
|
||||
}
|
||||
wm.AppendEvents(events...)
|
||||
return wm.Reduce()
|
||||
}
|
||||
|
||||
type existsWriteModel interface {
|
||||
Exists() bool
|
||||
eventstore.QueryReducer
|
||||
}
|
||||
|
||||
func exists(ctx context.Context, filter preparation.FilterToQueryReducer, wm existsWriteModel) (bool, error) {
|
||||
err := queryAndReduce(ctx, filter, wm)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return wm.Exists(), nil
|
||||
}
|
||||
|
@@ -62,3 +62,7 @@ func (rm *IDPConfigWriteModel) reduceConfigChangedEvent(e *idpconfig.IDPConfigCh
|
||||
func (rm *IDPConfigWriteModel) reduceConfigStateChanged(configID string, state domain.IDPConfigState) {
|
||||
rm.State = state
|
||||
}
|
||||
|
||||
func (rm *IDPConfigWriteModel) Exists() bool {
|
||||
return rm.State.Exists()
|
||||
}
|
||||
|
@@ -72,6 +72,8 @@ type InstanceSetup struct {
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsername bool
|
||||
AllowDomainDiscovery bool
|
||||
DisableLoginWithEmail bool
|
||||
DisableLoginWithPhone bool
|
||||
PasswordlessType domain.PasswordlessType
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
@@ -219,6 +221,8 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
|
||||
setup.LoginPolicy.HidePasswordReset,
|
||||
setup.LoginPolicy.IgnoreUnknownUsername,
|
||||
setup.LoginPolicy.AllowDomainDiscovery,
|
||||
setup.LoginPolicy.DisableLoginWithEmail,
|
||||
setup.LoginPolicy.DisableLoginWithPhone,
|
||||
setup.LoginPolicy.PasswordlessType,
|
||||
setup.LoginPolicy.DefaultRedirectURI,
|
||||
setup.LoginPolicy.PasswordCheckLifetime,
|
||||
|
@@ -15,56 +15,17 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
)
|
||||
|
||||
func (c *Commands) ChangeDefaultLoginPolicy(ctx context.Context, policy *domain.LoginPolicy) (*domain.LoginPolicy, error) {
|
||||
existingPolicy := NewInstanceLoginPolicyWriteModel(ctx)
|
||||
instanceAgg := InstanceAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel)
|
||||
event, err := c.changeDefaultLoginPolicy(ctx, instanceAgg, existingPolicy, policy)
|
||||
func (c *Commands) ChangeDefaultLoginPolicy(ctx context.Context, policy *ChangeLoginPolicy) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, prepareChangeDefaultLoginPolicy(instanceAgg, policy))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, event)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToLoginPolicy(&existingPolicy.LoginPolicyWriteModel), nil
|
||||
}
|
||||
|
||||
func (c *Commands) changeDefaultLoginPolicy(ctx context.Context, instanceAgg *eventstore.Aggregate, existingPolicy *InstanceLoginPolicyWriteModel, policy *domain.LoginPolicy) (eventstore.Command, error) {
|
||||
if ok := domain.ValidateDefaultRedirectURI(policy.DefaultRedirectURI); !ok {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-SFdqd", "Errors.IAM.LoginPolicy.RedirectURIInvalid")
|
||||
}
|
||||
err := c.defaultLoginPolicyWriteModelByID(ctx, existingPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "INSTANCE-M0sif", "Errors.IAM.LoginPolicy.NotFound")
|
||||
}
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(ctx,
|
||||
instanceAgg,
|
||||
policy.AllowUsernamePassword,
|
||||
policy.AllowRegister,
|
||||
policy.AllowExternalIDP,
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
policy.ExternalLoginCheckLifetime,
|
||||
policy.MFAInitSkipLifetime,
|
||||
policy.SecondFactorCheckLifetime,
|
||||
policy.MultiFactorCheckLifetime,
|
||||
)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "INSTANCE-5M9vdd", "Errors.IAM.LoginPolicy.NotChanged")
|
||||
}
|
||||
return changedEvent, nil
|
||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) AddIDPProviderToDefaultLoginPolicy(ctx context.Context, idpProvider *domain.IDPProvider) (*domain.IDPProvider, error) {
|
||||
@@ -255,6 +216,44 @@ func (c *Commands) getDefaultLoginPolicy(ctx context.Context) (*domain.LoginPoli
|
||||
return policy, nil
|
||||
}
|
||||
|
||||
func prepareChangeDefaultLoginPolicy(a *instance.Aggregate, policy *ChangeLoginPolicy) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if ok := domain.ValidateDefaultRedirectURI(policy.DefaultRedirectURI); !ok {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "IAM-SFdqd", "Errors.IAM.LoginPolicy.RedirectURIInvalid")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
wm := NewInstanceLoginPolicyWriteModel(ctx)
|
||||
if err := queryAndReduce(ctx, filter, wm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !wm.State.Exists() {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "INSTANCE-M0sif", "Errors.IAM.LoginPolicy.NotFound")
|
||||
}
|
||||
changedEvent, hasChanged := wm.NewChangedEvent(ctx, &a.Aggregate,
|
||||
policy.AllowUsernamePassword,
|
||||
policy.AllowRegister,
|
||||
policy.AllowExternalIDP,
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.DisableLoginWithEmail,
|
||||
policy.DisableLoginWithPhone,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
policy.ExternalLoginCheckLifetime,
|
||||
policy.MFAInitSkipLifetime,
|
||||
policy.SecondFactorCheckLifetime,
|
||||
policy.MultiFactorCheckLifetime)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "INSTANCE-5M9vdd", "Errors.IAM.LoginPolicy.NotChanged")
|
||||
}
|
||||
return []eventstore.Command{changedEvent}, nil
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func prepareAddDefaultLoginPolicy(
|
||||
a *instance.Aggregate,
|
||||
allowUsernamePassword bool,
|
||||
@@ -264,6 +263,8 @@ func prepareAddDefaultLoginPolicy(
|
||||
hidePasswordReset bool,
|
||||
ignoreUnknownUsernames bool,
|
||||
allowDomainDiscovery bool,
|
||||
disableLoginWithEmail bool,
|
||||
disableLoginWithPhone bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime time.Duration,
|
||||
@@ -295,6 +296,8 @@ func prepareAddDefaultLoginPolicy(
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery,
|
||||
disableLoginWithEmail,
|
||||
disableLoginWithPhone,
|
||||
passwordlessType,
|
||||
defaultRedirectURI,
|
||||
passwordCheckLifetime,
|
||||
|
@@ -67,7 +67,9 @@ func (wm *InstanceLoginPolicyWriteModel) NewChangedEvent(
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
allowDomainDiscovery,
|
||||
disableLoginWithEmail,
|
||||
disableLoginWithPhone bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@@ -120,6 +122,12 @@ func (wm *InstanceLoginPolicyWriteModel) NewChangedEvent(
|
||||
if wm.MultiFactorCheckLifetime != multiFactorCheckLifetime {
|
||||
changes = append(changes, policy.ChangeMultiFactorCheckLifetime(multiFactorCheckLifetime))
|
||||
}
|
||||
if wm.DisableLoginWithEmail != disableLoginWithEmail {
|
||||
changes = append(changes, policy.ChangeDisableLoginWithEmail(disableLoginWithEmail))
|
||||
}
|
||||
if wm.DisableLoginWithPhone != disableLoginWithPhone {
|
||||
changes = append(changes, policy.ChangeDisableLoginWithPhone(disableLoginWithPhone))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
@@ -24,10 +24,10 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
policy *domain.LoginPolicy
|
||||
policy *ChangeLoginPolicy
|
||||
}
|
||||
type res struct {
|
||||
want *domain.LoginPolicy
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -46,7 +46,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &ChangeLoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowExternalIDP: true,
|
||||
},
|
||||
@@ -71,6 +71,8 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -85,7 +87,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &ChangeLoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
@@ -93,6 +95,8 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
DisableLoginWithEmail: true,
|
||||
DisableLoginWithPhone: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -123,6 +127,8 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -145,6 +151,8 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*10,
|
||||
@@ -159,7 +167,7 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
},
|
||||
args: args{
|
||||
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &ChangeLoginPolicy{
|
||||
AllowRegister: false,
|
||||
AllowUsernamePassword: false,
|
||||
AllowExternalIDP: false,
|
||||
@@ -167,6 +175,8 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
HidePasswordReset: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
DisableLoginWithEmail: false,
|
||||
DisableLoginWithPhone: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
@@ -177,26 +187,8 @@ func TestCommandSide_ChangeDefaultLoginPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.LoginPolicy{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
InstanceID: "INSTANCE",
|
||||
AggregateID: "INSTANCE",
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
AllowRegister: false,
|
||||
AllowUsernamePassword: false,
|
||||
AllowExternalIDP: false,
|
||||
ForceMFA: false,
|
||||
HidePasswordReset: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
ExternalLoginCheckLifetime: time.Hour * 20,
|
||||
MFAInitSkipLifetime: time.Hour * 30,
|
||||
SecondFactorCheckLifetime: time.Hour * 40,
|
||||
MultiFactorCheckLifetime: time.Hour * 50,
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "INSTANCE",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -287,6 +279,8 @@ func TestCommandSide_AddIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -326,6 +320,8 @@ func TestCommandSide_AddIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -385,6 +381,8 @@ func TestCommandSide_AddIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -526,6 +524,8 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -565,6 +565,8 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -617,6 +619,8 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -674,6 +678,8 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -739,6 +745,8 @@ func TestCommandSide_RemoveIDPProviderDefaultLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1293,7 +1301,8 @@ func TestCommandSide_RemoveMultiFactorDefaultLoginPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newDefaultLoginPolicyChangedEvent(ctx context.Context, allowRegister, allowUsernamePassword, allowExternalIDP, forceMFA, hidePasswordReset, ignoreUnknownUsernames, allowDomainDiscovery bool,
|
||||
func newDefaultLoginPolicyChangedEvent(ctx context.Context, allowRegister, allowUsernamePassword, allowExternalIDP, forceMFA,
|
||||
hidePasswordReset, ignoreUnknownUsernames, allowDomainDiscovery, disableLoginWithEmail, disableLoginWithPhone bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
redirectURI string,
|
||||
passwordLifetime, externalLoginLifetime, mfaInitSkipLifetime, secondFactorLifetime, multiFactorLifetime time.Duration) *instance.LoginPolicyChangedEvent {
|
||||
@@ -1307,6 +1316,8 @@ func newDefaultLoginPolicyChangedEvent(ctx context.Context, allowRegister, allow
|
||||
policy.ChangeHidePasswordReset(hidePasswordReset),
|
||||
policy.ChangeIgnoreUnknownUsernames(ignoreUnknownUsernames),
|
||||
policy.ChangeAllowDomainDiscovery(allowDomainDiscovery),
|
||||
policy.ChangeDisableLoginWithEmail(disableLoginWithEmail),
|
||||
policy.ChangeDisableLoginWithPhone(disableLoginWithPhone),
|
||||
policy.ChangePasswordlessType(passwordlessType),
|
||||
policy.ChangeDefaultRedirectURI(redirectURI),
|
||||
policy.ChangePasswordCheckLifetime(passwordLifetime),
|
||||
|
@@ -2,9 +2,12 @@ package command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/command/preparation"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
caos_errs "github.com/zitadel/zitadel/internal/errors"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
@@ -12,74 +15,63 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
)
|
||||
|
||||
func (c *Commands) AddLoginPolicy(ctx context.Context, resourceOwner string, policy *domain.LoginPolicy) (*domain.LoginPolicy, error) {
|
||||
if resourceOwner == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-Fn8ds", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if ok := domain.ValidateDefaultRedirectURI(policy.DefaultRedirectURI); !ok {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-WSfdq", "Errors.Org.LoginPolicy.RedirectURIInvalid")
|
||||
}
|
||||
addedPolicy := NewOrgLoginPolicyWriteModel(resourceOwner)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, addedPolicy)
|
||||
type AddLoginPolicy struct {
|
||||
AllowUsernamePassword bool
|
||||
AllowRegister bool
|
||||
AllowExternalIDP bool
|
||||
IDPProviders []*AddLoginPolicyIDP
|
||||
ForceMFA bool
|
||||
SecondFactors []domain.SecondFactorType
|
||||
MultiFactors []domain.MultiFactorType
|
||||
PasswordlessType domain.PasswordlessType
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsernames bool
|
||||
AllowDomainDiscovery bool
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
ExternalLoginCheckLifetime time.Duration
|
||||
MFAInitSkipLifetime time.Duration
|
||||
SecondFactorCheckLifetime time.Duration
|
||||
MultiFactorCheckLifetime time.Duration
|
||||
DisableLoginWithEmail bool
|
||||
DisableLoginWithPhone bool
|
||||
}
|
||||
|
||||
type AddLoginPolicyIDP struct {
|
||||
ConfigID string
|
||||
Type domain.IdentityProviderType
|
||||
}
|
||||
|
||||
type ChangeLoginPolicy struct {
|
||||
AllowUsernamePassword bool
|
||||
AllowRegister bool
|
||||
AllowExternalIDP bool
|
||||
ForceMFA bool
|
||||
PasswordlessType domain.PasswordlessType
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsernames bool
|
||||
AllowDomainDiscovery bool
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
ExternalLoginCheckLifetime time.Duration
|
||||
MFAInitSkipLifetime time.Duration
|
||||
SecondFactorCheckLifetime time.Duration
|
||||
MultiFactorCheckLifetime time.Duration
|
||||
DisableLoginWithEmail bool
|
||||
DisableLoginWithPhone bool
|
||||
}
|
||||
|
||||
func (c *Commands) AddLoginPolicy(ctx context.Context, resourceOwner string, policy *AddLoginPolicy) (*domain.ObjectDetails, error) {
|
||||
orgAgg := org.NewAggregate(resourceOwner)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, prepareAddLoginPolicy(orgAgg, policy))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addedPolicy.State == domain.PolicyStateActive {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-Dgfb2", "Errors.Org.LoginPolicy.AlreadyExists")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&addedPolicy.WriteModel)
|
||||
cmds := []eventstore.Command{
|
||||
org.NewLoginPolicyAddedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
policy.AllowUsernamePassword,
|
||||
policy.AllowRegister,
|
||||
policy.AllowExternalIDP,
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
policy.ExternalLoginCheckLifetime,
|
||||
policy.MFAInitSkipLifetime,
|
||||
policy.SecondFactorCheckLifetime,
|
||||
policy.MultiFactorCheckLifetime),
|
||||
}
|
||||
for _, factor := range policy.SecondFactors {
|
||||
if !factor.Valid() {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-SFeea", "Errors.Org.LoginPolicy.MFA.Unspecified")
|
||||
}
|
||||
cmds = append(cmds, org.NewLoginPolicySecondFactorAddedEvent(ctx, orgAgg, factor))
|
||||
}
|
||||
for _, factor := range policy.MultiFactors {
|
||||
if !factor.Valid() {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-WSfrg", "Errors.Org.LoginPolicy.MFA.Unspecified")
|
||||
}
|
||||
cmds = append(cmds, org.NewLoginPolicyMultiFactorAddedEvent(ctx, orgAgg, factor))
|
||||
}
|
||||
for _, provider := range policy.IDPProviders {
|
||||
if provider.Type == domain.IdentityProviderTypeOrg {
|
||||
_, err = c.getOrgIDPConfigByID(ctx, provider.IDPConfigID, resourceOwner)
|
||||
} else {
|
||||
_, err = c.getInstanceIDPConfigByID(ctx, provider.IDPConfigID)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(err, "Org-FEd32", "Errors.IDPConfig.NotExisting")
|
||||
}
|
||||
cmds = append(cmds, org.NewIdentityProviderAddedEvent(ctx, orgAgg, provider.IDPConfigID, provider.Type))
|
||||
}
|
||||
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(addedPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToLoginPolicy(&addedPolicy.LoginPolicyWriteModel), nil
|
||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) orgLoginPolicyWriteModelByID(ctx context.Context, orgID string) (*OrgLoginPolicyWriteModel, error) {
|
||||
@@ -102,54 +94,17 @@ func (c *Commands) getOrgLoginPolicy(ctx context.Context, orgID string) (*domain
|
||||
return c.getDefaultLoginPolicy(ctx)
|
||||
}
|
||||
|
||||
func (c *Commands) ChangeLoginPolicy(ctx context.Context, resourceOwner string, policy *domain.LoginPolicy) (*domain.LoginPolicy, error) {
|
||||
if resourceOwner == "" {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-Mf9sf", "Errors.ResourceOwnerMissing")
|
||||
}
|
||||
if ok := domain.ValidateDefaultRedirectURI(policy.DefaultRedirectURI); !ok {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-Sfd21", "Errors.Org.LoginPolicy.RedirectURIInvalid")
|
||||
}
|
||||
existingPolicy := NewOrgLoginPolicyWriteModel(resourceOwner)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, existingPolicy)
|
||||
func (c *Commands) ChangeLoginPolicy(ctx context.Context, resourceOwner string, policy *ChangeLoginPolicy) (*domain.ObjectDetails, error) {
|
||||
orgAgg := org.NewAggregate(resourceOwner)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, prepareChangeLoginPolicy(orgAgg, policy))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if existingPolicy.State == domain.PolicyStateUnspecified || existingPolicy.State == domain.PolicyStateRemoved {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "Org-M0sif", "Errors.Org.LoginPolicy.NotFound")
|
||||
}
|
||||
|
||||
orgAgg := OrgAggregateFromWriteModel(&existingPolicy.LoginPolicyWriteModel.WriteModel)
|
||||
changedEvent, hasChanged := existingPolicy.NewChangedEvent(
|
||||
ctx,
|
||||
orgAgg,
|
||||
policy.AllowUsernamePassword,
|
||||
policy.AllowRegister,
|
||||
policy.AllowExternalIDP,
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
policy.ExternalLoginCheckLifetime,
|
||||
policy.MFAInitSkipLifetime,
|
||||
policy.SecondFactorCheckLifetime,
|
||||
policy.MultiFactorCheckLifetime)
|
||||
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-5M9vdd", "Errors.Org.LoginPolicy.NotChanged")
|
||||
}
|
||||
|
||||
pushedEvents, err := c.eventstore.Push(ctx, changedEvent)
|
||||
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = AppendAndReduce(existingPolicy, pushedEvents...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return writeModelToLoginPolicy(&existingPolicy.LoginPolicyWriteModel), nil
|
||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||
}
|
||||
|
||||
func (c *Commands) RemoveLoginPolicy(ctx context.Context, orgID string) (*domain.ObjectDetails, error) {
|
||||
@@ -437,3 +392,106 @@ func (c *Commands) orgLoginPolicyAuthFactorsWriteModel(ctx context.Context, orgI
|
||||
}
|
||||
return writeModel, nil
|
||||
}
|
||||
|
||||
func prepareAddLoginPolicy(a *org.Aggregate, policy *AddLoginPolicy) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if ok := domain.ValidateDefaultRedirectURI(policy.DefaultRedirectURI); !ok {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-WSfdq", "Errors.Org.LoginPolicy.RedirectURIInvalid")
|
||||
}
|
||||
for _, factor := range policy.SecondFactors {
|
||||
if !factor.Valid() {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-SFeea", "Errors.Org.LoginPolicy.MFA.Unspecified")
|
||||
}
|
||||
}
|
||||
for _, factor := range policy.MultiFactors {
|
||||
if !factor.Valid() {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-WSfrg", "Errors.Org.LoginPolicy.MFA.Unspecified")
|
||||
}
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
if exists, err := exists(ctx, filter, NewOrgLoginPolicyWriteModel(a.ID)); exists || err != nil {
|
||||
return nil, caos_errs.ThrowAlreadyExists(nil, "Org-Dgfb2", "Errors.Org.LoginPolicy.AlreadyExists")
|
||||
}
|
||||
for _, idp := range policy.IDPProviders {
|
||||
exists, err := idpExists(ctx, filter, idp)
|
||||
if !exists || err != nil {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(err, "Org-FEd32", "Errors.IDPConfig.NotExisting")
|
||||
}
|
||||
}
|
||||
cmds := make([]eventstore.Command, 0, len(policy.SecondFactors)+len(policy.MultiFactors)+len(policy.IDPProviders)+1)
|
||||
cmds = append(cmds, org.NewLoginPolicyAddedEvent(ctx, &a.Aggregate,
|
||||
policy.AllowUsernamePassword,
|
||||
policy.AllowRegister,
|
||||
policy.AllowExternalIDP,
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.DisableLoginWithEmail,
|
||||
policy.DisableLoginWithPhone,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
policy.ExternalLoginCheckLifetime,
|
||||
policy.MFAInitSkipLifetime,
|
||||
policy.SecondFactorCheckLifetime,
|
||||
policy.MultiFactorCheckLifetime,
|
||||
))
|
||||
for _, factor := range policy.SecondFactors {
|
||||
cmds = append(cmds, org.NewLoginPolicySecondFactorAddedEvent(ctx, &a.Aggregate, factor))
|
||||
}
|
||||
for _, factor := range policy.MultiFactors {
|
||||
cmds = append(cmds, org.NewLoginPolicyMultiFactorAddedEvent(ctx, &a.Aggregate, factor))
|
||||
}
|
||||
for _, idp := range policy.IDPProviders {
|
||||
cmds = append(cmds, org.NewIdentityProviderAddedEvent(ctx, &a.Aggregate, idp.ConfigID, idp.Type))
|
||||
}
|
||||
return cmds, nil
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func prepareChangeLoginPolicy(a *org.Aggregate, policy *ChangeLoginPolicy) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if ok := domain.ValidateDefaultRedirectURI(policy.DefaultRedirectURI); !ok {
|
||||
return nil, caos_errs.ThrowInvalidArgument(nil, "Org-Sfd21", "Errors.Org.LoginPolicy.RedirectURIInvalid")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
wm := NewOrgLoginPolicyWriteModel(a.ID)
|
||||
if err := queryAndReduce(ctx, filter, wm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !wm.State.Exists() {
|
||||
return nil, caos_errs.ThrowNotFound(nil, "Org-M0sif", "Errors.Org.LoginPolicy.NotFound")
|
||||
}
|
||||
changedEvent, hasChanged := wm.NewChangedEvent(ctx, &a.Aggregate,
|
||||
policy.AllowUsernamePassword,
|
||||
policy.AllowRegister,
|
||||
policy.AllowExternalIDP,
|
||||
policy.ForceMFA,
|
||||
policy.HidePasswordReset,
|
||||
policy.IgnoreUnknownUsernames,
|
||||
policy.AllowDomainDiscovery,
|
||||
policy.DisableLoginWithEmail,
|
||||
policy.DisableLoginWithPhone,
|
||||
policy.PasswordlessType,
|
||||
policy.DefaultRedirectURI,
|
||||
policy.PasswordCheckLifetime,
|
||||
policy.ExternalLoginCheckLifetime,
|
||||
policy.MFAInitSkipLifetime,
|
||||
policy.SecondFactorCheckLifetime,
|
||||
policy.MultiFactorCheckLifetime)
|
||||
if !hasChanged {
|
||||
return nil, caos_errs.ThrowPreconditionFailed(nil, "Org-5M9vdd", "Errors.Org.LoginPolicy.NotChanged")
|
||||
}
|
||||
return []eventstore.Command{changedEvent}, nil
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func idpExists(ctx context.Context, filter preparation.FilterToQueryReducer, idp *AddLoginPolicyIDP) (bool, error) {
|
||||
if idp.Type == domain.IdentityProviderTypeSystem {
|
||||
return exists(ctx, filter, NewInstanceIDPConfigWriteModel(ctx, idp.ConfigID))
|
||||
}
|
||||
return exists(ctx, filter, NewOrgIDPConfigWriteModel(idp.ConfigID, authz.GetCtxData(ctx).ResourceOwner))
|
||||
}
|
||||
|
@@ -69,7 +69,9 @@ func (wm *OrgLoginPolicyWriteModel) NewChangedEvent(
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
allowDomainDiscovery,
|
||||
disableLoginWithEmail,
|
||||
disableLoginWithPhone bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@@ -122,6 +124,12 @@ func (wm *OrgLoginPolicyWriteModel) NewChangedEvent(
|
||||
if wm.DefaultRedirectURI != defaultRedirectURI {
|
||||
changes = append(changes, policy.ChangeDefaultRedirectURI(defaultRedirectURI))
|
||||
}
|
||||
if wm.DisableLoginWithEmail != disableLoginWithEmail {
|
||||
changes = append(changes, policy.ChangeDisableLoginWithEmail(disableLoginWithEmail))
|
||||
}
|
||||
if wm.DisableLoginWithPhone != disableLoginWithPhone {
|
||||
changes = append(changes, policy.ChangeDisableLoginWithPhone(disableLoginWithPhone))
|
||||
}
|
||||
if len(changes) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
@@ -33,10 +33,10 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
orgID string
|
||||
policy *domain.LoginPolicy
|
||||
policy *AddLoginPolicy
|
||||
}
|
||||
type res struct {
|
||||
want *domain.LoginPolicy
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -45,25 +45,6 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "org id missing, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
policy: &domain.LoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "loginpolicy already existing, already exists error",
|
||||
fields: fields{
|
||||
@@ -80,6 +61,8 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -95,7 +78,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &AddLoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
@@ -133,6 +116,8 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -149,7 +134,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &AddLoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
@@ -157,6 +142,8 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
DisableLoginWithEmail: true,
|
||||
DisableLoginWithPhone: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -167,25 +154,8 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.LoginPolicy{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "org1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
ExternalLoginCheckLifetime: time.Hour * 2,
|
||||
MFAInitSkipLifetime: time.Hour * 3,
|
||||
SecondFactorCheckLifetime: time.Hour * 4,
|
||||
MultiFactorCheckLifetime: time.Hour * 5,
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -194,13 +164,12 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
expectFilter(),
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &AddLoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
@@ -208,6 +177,8 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
DisableLoginWithEmail: true,
|
||||
DisableLoginWithPhone: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -240,6 +211,8 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -268,7 +241,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &AddLoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
@@ -276,6 +249,8 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
DisableLoginWithEmail: true,
|
||||
DisableLoginWithPhone: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -288,25 +263,8 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.LoginPolicy{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "org1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
ExternalLoginCheckLifetime: time.Hour * 2,
|
||||
MFAInitSkipLifetime: time.Hour * 3,
|
||||
SecondFactorCheckLifetime: time.Hour * 4,
|
||||
MultiFactorCheckLifetime: time.Hour * 5,
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -322,7 +280,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &AddLoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
@@ -330,6 +288,8 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
DisableLoginWithEmail: true,
|
||||
DisableLoginWithPhone: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -337,10 +297,10 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
MFAInitSkipLifetime: time.Hour * 3,
|
||||
SecondFactorCheckLifetime: time.Hour * 4,
|
||||
MultiFactorCheckLifetime: time.Hour * 5,
|
||||
IDPProviders: []*domain.IDPProvider{
|
||||
IDPProviders: []*AddLoginPolicyIDP{
|
||||
{
|
||||
Type: domain.IdentityProviderTypeSystem,
|
||||
IDPConfigID: "invalid",
|
||||
Type: domain.IdentityProviderTypeSystem,
|
||||
ConfigID: "invalid",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -379,6 +339,8 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -402,7 +364,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &AddLoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
@@ -410,6 +372,8 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
DisableLoginWithEmail: true,
|
||||
DisableLoginWithPhone: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -417,34 +381,17 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
|
||||
MFAInitSkipLifetime: time.Hour * 3,
|
||||
SecondFactorCheckLifetime: time.Hour * 4,
|
||||
MultiFactorCheckLifetime: time.Hour * 5,
|
||||
IDPProviders: []*domain.IDPProvider{
|
||||
IDPProviders: []*AddLoginPolicyIDP{
|
||||
{
|
||||
Type: domain.IdentityProviderTypeSystem,
|
||||
IDPConfigID: "config1",
|
||||
Type: domain.IdentityProviderTypeSystem,
|
||||
ConfigID: "config1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.LoginPolicy{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "org1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
ExternalLoginCheckLifetime: time.Hour * 2,
|
||||
MFAInitSkipLifetime: time.Hour * 3,
|
||||
SecondFactorCheckLifetime: time.Hour * 4,
|
||||
MultiFactorCheckLifetime: time.Hour * 5,
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -475,10 +422,10 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
orgID string
|
||||
policy *domain.LoginPolicy
|
||||
policy *ChangeLoginPolicy
|
||||
}
|
||||
type res struct {
|
||||
want *domain.LoginPolicy
|
||||
want *domain.ObjectDetails
|
||||
err func(error) bool
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -487,30 +434,6 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
args args
|
||||
res res
|
||||
}{
|
||||
{
|
||||
name: "org id missing, invalid argument error",
|
||||
fields: fields{
|
||||
eventstore: eventstoreExpect(
|
||||
t,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
policy: &domain.LoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
err: caos_errs.IsErrorInvalidArgument,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "loginpolicy not existing, not found error",
|
||||
fields: fields{
|
||||
@@ -522,13 +445,15 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &ChangeLoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
ForceMFA: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
DisableLoginWithEmail: true,
|
||||
DisableLoginWithPhone: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
},
|
||||
@@ -553,6 +478,8 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -568,7 +495,7 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &ChangeLoginPolicy{
|
||||
AllowRegister: true,
|
||||
AllowUsernamePassword: true,
|
||||
AllowExternalIDP: true,
|
||||
@@ -576,6 +503,8 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
DisableLoginWithEmail: true,
|
||||
DisableLoginWithPhone: true,
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 1,
|
||||
@@ -605,6 +534,8 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"https://example.com/redirect",
|
||||
time.Hour*1,
|
||||
@@ -627,6 +558,8 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
&duration10,
|
||||
@@ -643,13 +576,15 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
orgID: "org1",
|
||||
policy: &domain.LoginPolicy{
|
||||
policy: &ChangeLoginPolicy{
|
||||
AllowRegister: false,
|
||||
AllowUsernamePassword: false,
|
||||
AllowExternalIDP: false,
|
||||
ForceMFA: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
DisableLoginWithEmail: false,
|
||||
DisableLoginWithPhone: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
@@ -660,25 +595,8 @@ func TestCommandSide_ChangeLoginPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
res: res{
|
||||
want: &domain.LoginPolicy{
|
||||
ObjectRoot: models.ObjectRoot{
|
||||
AggregateID: "org1",
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
AllowRegister: false,
|
||||
AllowUsernamePassword: false,
|
||||
AllowExternalIDP: false,
|
||||
ForceMFA: false,
|
||||
HidePasswordReset: false,
|
||||
IgnoreUnknownUsernames: false,
|
||||
AllowDomainDiscovery: false,
|
||||
PasswordlessType: domain.PasswordlessTypeNotAllowed,
|
||||
DefaultRedirectURI: "",
|
||||
PasswordCheckLifetime: time.Hour * 10,
|
||||
ExternalLoginCheckLifetime: time.Hour * 20,
|
||||
MFAInitSkipLifetime: time.Hour * 30,
|
||||
SecondFactorCheckLifetime: time.Hour * 40,
|
||||
MultiFactorCheckLifetime: time.Hour * 50,
|
||||
want: &domain.ObjectDetails{
|
||||
ResourceOwner: "org1",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -766,6 +684,8 @@ func TestCommandSide_RemoveLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -907,6 +827,8 @@ func TestCommandSide_AddIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -949,6 +871,8 @@ func TestCommandSide_AddIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1011,6 +935,8 @@ func TestCommandSide_AddIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1176,6 +1102,8 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1218,6 +1146,8 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1272,6 +1202,8 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1333,6 +1265,8 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1402,6 +1336,8 @@ func TestCommandSide_RemoveIDPProviderLoginPolicy(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
domain.PasswordlessTypeAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -2020,7 +1956,8 @@ func TestCommandSide_RemoveMultiFactorLoginPolicy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func newLoginPolicyChangedEvent(ctx context.Context, orgID string, usernamePassword, register, externalIDP, mfa, passwordReset, ignoreUnknownUsernames, allowDomainDiscovery bool,
|
||||
func newLoginPolicyChangedEvent(ctx context.Context, orgID string,
|
||||
usernamePassword, register, externalIDP, mfa, passwordReset, ignoreUnknownUsernames, allowDomainDiscovery, disableLoginWithEmail, disableLoginWithPhone bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
redirectURI string,
|
||||
passwordLifetime, externalLoginLifetime, mfaInitSkipLifetime, secondFactorLifetime, multiFactorLifetime *time.Duration) *org.LoginPolicyChangedEvent {
|
||||
@@ -2034,6 +1971,8 @@ func newLoginPolicyChangedEvent(ctx context.Context, orgID string, usernamePassw
|
||||
policy.ChangeAllowDomainDiscovery(allowDomainDiscovery),
|
||||
policy.ChangePasswordlessType(passwordlessType),
|
||||
policy.ChangeDefaultRedirectURI(redirectURI),
|
||||
policy.ChangeDisableLoginWithEmail(disableLoginWithEmail),
|
||||
policy.ChangeDisableLoginWithPhone(disableLoginWithPhone),
|
||||
}
|
||||
if passwordLifetime != nil {
|
||||
changes = append(changes, policy.ChangePasswordCheckLifetime(*passwordLifetime))
|
||||
|
@@ -18,6 +18,8 @@ type LoginPolicyWriteModel struct {
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsernames bool
|
||||
AllowDomainDiscovery bool
|
||||
DisableLoginWithEmail bool
|
||||
DisableLoginWithPhone bool
|
||||
PasswordlessType domain.PasswordlessType
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
@@ -40,6 +42,8 @@ func (wm *LoginPolicyWriteModel) Reduce() error {
|
||||
wm.HidePasswordReset = e.HidePasswordReset
|
||||
wm.IgnoreUnknownUsernames = e.IgnoreUnknownUsernames
|
||||
wm.AllowDomainDiscovery = e.AllowDomainDiscovery
|
||||
wm.DisableLoginWithEmail = e.DisableLoginWithEmail
|
||||
wm.DisableLoginWithPhone = e.DisableLoginWithPhone
|
||||
wm.DefaultRedirectURI = e.DefaultRedirectURI
|
||||
wm.PasswordCheckLifetime = e.PasswordCheckLifetime
|
||||
wm.ExternalLoginCheckLifetime = e.ExternalLoginCheckLifetime
|
||||
@@ -90,9 +94,19 @@ func (wm *LoginPolicyWriteModel) Reduce() error {
|
||||
if e.MultiFactorCheckLifetime != nil {
|
||||
wm.MultiFactorCheckLifetime = *e.MultiFactorCheckLifetime
|
||||
}
|
||||
if e.DisableLoginWithEmail != nil {
|
||||
wm.DisableLoginWithEmail = *e.DisableLoginWithEmail
|
||||
}
|
||||
if e.DisableLoginWithPhone != nil {
|
||||
wm.DisableLoginWithPhone = *e.DisableLoginWithPhone
|
||||
}
|
||||
case *policy.LoginPolicyRemovedEvent:
|
||||
wm.State = domain.PolicyStateRemoved
|
||||
}
|
||||
}
|
||||
return wm.WriteModel.Reduce()
|
||||
}
|
||||
|
||||
func (wm *LoginPolicyWriteModel) Exists() bool {
|
||||
return wm.State.Exists()
|
||||
}
|
||||
|
@@ -1158,6 +1158,8 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1196,6 +1198,8 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1235,6 +1239,8 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1290,6 +1296,8 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1379,6 +1387,8 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1475,6 +1485,8 @@ func TestCommandSide_CheckPassword(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
|
@@ -1680,6 +1680,8 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1747,6 +1749,8 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1814,6 +1818,8 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -1898,6 +1904,8 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -2040,6 +2048,8 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -2150,6 +2160,8 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -2254,6 +2266,8 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
@@ -2380,6 +2394,8 @@ func TestCommandSide_RegisterHuman(t *testing.T) {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
domain.PasswordlessTypeNotAllowed,
|
||||
"",
|
||||
time.Hour*1,
|
||||
|
@@ -101,7 +101,7 @@ func (s IDPConfigState) Valid() bool {
|
||||
}
|
||||
|
||||
func (s IDPConfigState) Exists() bool {
|
||||
return s != IDPConfigStateUnspecified || s == IDPConfigStateRemoved
|
||||
return s != IDPConfigStateUnspecified && s != IDPConfigStateRemoved
|
||||
}
|
||||
|
||||
type IDPConfigStylingType int32
|
||||
|
@@ -28,6 +28,8 @@ type LoginPolicy struct {
|
||||
MFAInitSkipLifetime time.Duration
|
||||
SecondFactorCheckLifetime time.Duration
|
||||
MultiFactorCheckLifetime time.Duration
|
||||
DisableLoginWithEmail bool
|
||||
DisableLoginWithPhone bool
|
||||
}
|
||||
|
||||
func ValidateDefaultRedirectURI(rawURL string) bool {
|
||||
|
@@ -123,7 +123,7 @@ func getUpdateCols(cols, conflictTarget []string) (updateCols, updateVals []stri
|
||||
|
||||
func NewUpdateStatement(event eventstore.Event, values []handler.Column, conditions []handler.Condition, opts ...execOption) *handler.Statement {
|
||||
cols, params, args := columnsToQuery(values)
|
||||
wheres, whereArgs := conditionsToWhere(conditions, len(params))
|
||||
wheres, whereArgs := conditionsToWhere(conditions, len(args))
|
||||
args = append(args, whereArgs...)
|
||||
|
||||
config := execConfig{
|
||||
@@ -278,6 +278,13 @@ func NewArrayIntersectCol(column string, value interface{}) handler.Column {
|
||||
}
|
||||
}
|
||||
|
||||
func NewCopyCol(column, from string) handler.Column {
|
||||
return handler.Column{
|
||||
Name: column,
|
||||
Value: handler.NewCol(from, nil),
|
||||
}
|
||||
}
|
||||
|
||||
// NewCopyStatement creates a new upsert statement which updates a column from an existing row
|
||||
// cols represent the columns which are objective to change.
|
||||
// if the value of a col is empty the data will be copied from the selected row
|
||||
@@ -359,15 +366,22 @@ func columnsToQuery(cols []handler.Column) (names []string, parameters []string,
|
||||
names = make([]string, len(cols))
|
||||
values = make([]interface{}, len(cols))
|
||||
parameters = make([]string, len(cols))
|
||||
var parameterIndex int
|
||||
for i, col := range cols {
|
||||
names[i] = col.Name
|
||||
values[i] = col.Value
|
||||
parameters[i] = "$" + strconv.Itoa(i+1)
|
||||
if c, ok := col.Value.(handler.Column); ok {
|
||||
parameters[i] = c.Name
|
||||
continue
|
||||
} else {
|
||||
values[parameterIndex] = col.Value
|
||||
}
|
||||
parameters[i] = "$" + strconv.Itoa(parameterIndex+1)
|
||||
if col.ParameterOpt != nil {
|
||||
parameters[i] = col.ParameterOpt(parameters[i])
|
||||
}
|
||||
parameterIndex++
|
||||
}
|
||||
return names, parameters, values
|
||||
return names, parameters, values[:parameterIndex]
|
||||
}
|
||||
|
||||
func conditionsToWhere(cols []handler.Condition, paramOffset int) (wheres []string, values []interface{}) {
|
||||
|
@@ -1352,6 +1352,32 @@ func Test_columnsToQuery(t *testing.T) {
|
||||
values: []interface{}{1, 3.14},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with copy column",
|
||||
args: args{
|
||||
cols: []handler.Column{
|
||||
{
|
||||
Name: "col1",
|
||||
Value: 1,
|
||||
},
|
||||
{
|
||||
Name: "col2",
|
||||
Value: handler.Column{
|
||||
Name: "col1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "col3",
|
||||
Value: "something",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
names: []string{"col1", "col2", "col3"},
|
||||
params: []string{"$1", "col1", "$2"},
|
||||
values: []interface{}{1, "something"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@@ -169,7 +169,7 @@ func (p *notificationsProjection) reduceInitCodeAdded(event eventstore.Event) (*
|
||||
return nil, err
|
||||
}
|
||||
|
||||
notifyUser, err := p.queries.GeNotifyUser(ctx, true, e.Aggregate().ID)
|
||||
notifyUser, err := p.queries.GetNotifyUserByID(ctx, true, e.Aggregate().ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -232,7 +232,7 @@ func (p *notificationsProjection) reduceEmailCodeAdded(event eventstore.Event) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
notifyUser, err := p.queries.GeNotifyUser(ctx, true, e.Aggregate().ID)
|
||||
notifyUser, err := p.queries.GetNotifyUserByID(ctx, true, e.Aggregate().ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -295,7 +295,7 @@ func (p *notificationsProjection) reducePasswordCodeAdded(event eventstore.Event
|
||||
return nil, err
|
||||
}
|
||||
|
||||
notifyUser, err := p.queries.GeNotifyUser(ctx, true, e.Aggregate().ID)
|
||||
notifyUser, err := p.queries.GetNotifyUserByID(ctx, true, e.Aggregate().ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -366,7 +366,7 @@ func (p *notificationsProjection) reduceDomainClaimed(event eventstore.Event) (*
|
||||
return nil, err
|
||||
}
|
||||
|
||||
notifyUser, err := p.queries.GeNotifyUser(ctx, true, e.Aggregate().ID)
|
||||
notifyUser, err := p.queries.GetNotifyUserByID(ctx, true, e.Aggregate().ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -427,7 +427,7 @@ func (p *notificationsProjection) reducePasswordlessCodeRequested(event eventsto
|
||||
return nil, err
|
||||
}
|
||||
|
||||
notifyUser, err := p.queries.GeNotifyUser(ctx, true, e.Aggregate().ID)
|
||||
notifyUser, err := p.queries.GetNotifyUserByID(ctx, true, e.Aggregate().ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -485,7 +485,7 @@ func (p *notificationsProjection) reducePhoneCodeAdded(event eventstore.Event) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
notifyUser, err := p.queries.GeNotifyUser(ctx, true, e.Aggregate().ID)
|
||||
notifyUser, err := p.queries.GetNotifyUserByID(ctx, true, e.Aggregate().ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -20,18 +20,18 @@ var (
|
||||
", members.user_id" +
|
||||
", members.roles" +
|
||||
", projections.login_names.login_name" +
|
||||
", projections.users3_humans.email" +
|
||||
", projections.users3_humans.first_name" +
|
||||
", projections.users3_humans.last_name" +
|
||||
", projections.users3_humans.display_name" +
|
||||
", projections.users3_machines.name" +
|
||||
", projections.users3_humans.avatar_key" +
|
||||
", projections.users4_humans.email" +
|
||||
", projections.users4_humans.first_name" +
|
||||
", projections.users4_humans.last_name" +
|
||||
", projections.users4_humans.display_name" +
|
||||
", projections.users4_machines.name" +
|
||||
", projections.users4_humans.avatar_key" +
|
||||
", COUNT(*) OVER () " +
|
||||
"FROM projections.instance_members2 AS members " +
|
||||
"LEFT JOIN projections.users3_humans " +
|
||||
"ON members.user_id = projections.users3_humans.user_id " +
|
||||
"LEFT JOIN projections.users3_machines " +
|
||||
"ON members.user_id = projections.users3_machines.user_id " +
|
||||
"LEFT JOIN projections.users4_humans " +
|
||||
"ON members.user_id = projections.users4_humans.user_id " +
|
||||
"LEFT JOIN projections.users4_machines " +
|
||||
"ON members.user_id = projections.users4_machines.user_id " +
|
||||
"LEFT JOIN projections.login_names " +
|
||||
"ON members.user_id = projections.login_names.user_id " +
|
||||
"WHERE projections.login_names.is_primary = $1")
|
||||
|
@@ -31,6 +31,8 @@ type LoginPolicy struct {
|
||||
HidePasswordReset bool
|
||||
IgnoreUnknownUsernames bool
|
||||
AllowDomainDiscovery bool
|
||||
DisableLoginWithEmail bool
|
||||
DisableLoginWithPhone bool
|
||||
DefaultRedirectURI string
|
||||
PasswordCheckLifetime time.Duration
|
||||
ExternalLoginCheckLifetime time.Duration
|
||||
@@ -118,6 +120,14 @@ var (
|
||||
name: projection.AllowDomainDiscovery,
|
||||
table: loginPolicyTable,
|
||||
}
|
||||
LoginPolicyColumnDisableLoginWithEmail = Column{
|
||||
name: projection.DisableLoginWithEmail,
|
||||
table: loginPolicyTable,
|
||||
}
|
||||
LoginPolicyColumnDisableLoginWithPhone = Column{
|
||||
name: projection.DisableLoginWithPhone,
|
||||
table: loginPolicyTable,
|
||||
}
|
||||
LoginPolicyColumnDefaultRedirectURI = Column{
|
||||
name: projection.DefaultRedirectURI,
|
||||
table: loginPolicyTable,
|
||||
@@ -311,6 +321,8 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy,
|
||||
LoginPolicyColumnHidePasswordReset.identifier(),
|
||||
LoginPolicyColumnIgnoreUnknownUsernames.identifier(),
|
||||
LoginPolicyColumnAllowDomainDiscovery.identifier(),
|
||||
LoginPolicyColumnDisableLoginWithEmail.identifier(),
|
||||
LoginPolicyColumnDisableLoginWithPhone.identifier(),
|
||||
LoginPolicyColumnDefaultRedirectURI.identifier(),
|
||||
LoginPolicyColumnPasswordCheckLifetime.identifier(),
|
||||
LoginPolicyColumnExternalLoginCheckLifetime.identifier(),
|
||||
@@ -350,6 +362,8 @@ func prepareLoginPolicyQuery() (sq.SelectBuilder, func(*sql.Rows) (*LoginPolicy,
|
||||
&p.HidePasswordReset,
|
||||
&p.IgnoreUnknownUsernames,
|
||||
&p.AllowDomainDiscovery,
|
||||
&p.DisableLoginWithEmail,
|
||||
&p.DisableLoginWithPhone,
|
||||
&defaultRedirectURI,
|
||||
&p.PasswordCheckLifetime,
|
||||
&p.ExternalLoginCheckLifetime,
|
||||
|
@@ -30,33 +30,35 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueries(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.aggregate_id,`+
|
||||
` projections.login_policies2.creation_date,`+
|
||||
` projections.login_policies2.change_date,`+
|
||||
` projections.login_policies2.sequence,`+
|
||||
` projections.login_policies2.allow_register,`+
|
||||
` projections.login_policies2.allow_username_password,`+
|
||||
` projections.login_policies2.allow_external_idps,`+
|
||||
` projections.login_policies2.force_mfa,`+
|
||||
` projections.login_policies2.second_factors,`+
|
||||
` projections.login_policies2.multi_factors,`+
|
||||
` projections.login_policies2.passwordless_type,`+
|
||||
` projections.login_policies2.is_default,`+
|
||||
` projections.login_policies2.hide_password_reset,`+
|
||||
` projections.login_policies2.ignore_unknown_usernames,`+
|
||||
` projections.login_policies2.allow_domain_discovery,`+
|
||||
` projections.login_policies2.default_redirect_uri,`+
|
||||
` projections.login_policies2.password_check_lifetime,`+
|
||||
` projections.login_policies2.external_login_check_lifetime,`+
|
||||
` projections.login_policies2.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies2.second_factor_check_lifetime,`+
|
||||
` projections.login_policies2.multi_factor_check_lifetime,`+
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies3.aggregate_id,`+
|
||||
` projections.login_policies3.creation_date,`+
|
||||
` projections.login_policies3.change_date,`+
|
||||
` projections.login_policies3.sequence,`+
|
||||
` projections.login_policies3.allow_register,`+
|
||||
` projections.login_policies3.allow_username_password,`+
|
||||
` projections.login_policies3.allow_external_idps,`+
|
||||
` projections.login_policies3.force_mfa,`+
|
||||
` projections.login_policies3.second_factors,`+
|
||||
` projections.login_policies3.multi_factors,`+
|
||||
` projections.login_policies3.passwordless_type,`+
|
||||
` projections.login_policies3.is_default,`+
|
||||
` projections.login_policies3.hide_password_reset,`+
|
||||
` projections.login_policies3.ignore_unknown_usernames,`+
|
||||
` projections.login_policies3.allow_domain_discovery,`+
|
||||
` projections.login_policies3.disable_login_with_email,`+
|
||||
` projections.login_policies3.disable_login_with_phone,`+
|
||||
` projections.login_policies3.default_redirect_uri,`+
|
||||
` projections.login_policies3.password_check_lifetime,`+
|
||||
` projections.login_policies3.external_login_check_lifetime,`+
|
||||
` projections.login_policies3.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies3.second_factor_check_lifetime,`+
|
||||
` projections.login_policies3.multi_factor_check_lifetime,`+
|
||||
` projections.idp_login_policy_links3.idp_id,`+
|
||||
` projections.idps2.name,`+
|
||||
` projections.idps2.type`+
|
||||
` FROM projections.login_policies2`+
|
||||
` FROM projections.login_policies3`+
|
||||
` LEFT JOIN projections.idp_login_policy_links3 ON `+
|
||||
` projections.login_policies2.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` projections.login_policies3.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` LEFT JOIN projections.idps2 ON`+
|
||||
` projections.idp_login_policy_links3.idp_id = projections.idps2.id`),
|
||||
nil,
|
||||
@@ -76,33 +78,35 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.aggregate_id,`+
|
||||
` projections.login_policies2.creation_date,`+
|
||||
` projections.login_policies2.change_date,`+
|
||||
` projections.login_policies2.sequence,`+
|
||||
` projections.login_policies2.allow_register,`+
|
||||
` projections.login_policies2.allow_username_password,`+
|
||||
` projections.login_policies2.allow_external_idps,`+
|
||||
` projections.login_policies2.force_mfa,`+
|
||||
` projections.login_policies2.second_factors,`+
|
||||
` projections.login_policies2.multi_factors,`+
|
||||
` projections.login_policies2.passwordless_type,`+
|
||||
` projections.login_policies2.is_default,`+
|
||||
` projections.login_policies2.hide_password_reset,`+
|
||||
` projections.login_policies2.ignore_unknown_usernames,`+
|
||||
` projections.login_policies2.allow_domain_discovery,`+
|
||||
` projections.login_policies2.default_redirect_uri,`+
|
||||
` projections.login_policies2.password_check_lifetime,`+
|
||||
` projections.login_policies2.external_login_check_lifetime,`+
|
||||
` projections.login_policies2.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies2.second_factor_check_lifetime,`+
|
||||
` projections.login_policies2.multi_factor_check_lifetime,`+
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies3.aggregate_id,`+
|
||||
` projections.login_policies3.creation_date,`+
|
||||
` projections.login_policies3.change_date,`+
|
||||
` projections.login_policies3.sequence,`+
|
||||
` projections.login_policies3.allow_register,`+
|
||||
` projections.login_policies3.allow_username_password,`+
|
||||
` projections.login_policies3.allow_external_idps,`+
|
||||
` projections.login_policies3.force_mfa,`+
|
||||
` projections.login_policies3.second_factors,`+
|
||||
` projections.login_policies3.multi_factors,`+
|
||||
` projections.login_policies3.passwordless_type,`+
|
||||
` projections.login_policies3.is_default,`+
|
||||
` projections.login_policies3.hide_password_reset,`+
|
||||
` projections.login_policies3.ignore_unknown_usernames,`+
|
||||
` projections.login_policies3.allow_domain_discovery,`+
|
||||
` projections.login_policies3.disable_login_with_email,`+
|
||||
` projections.login_policies3.disable_login_with_phone,`+
|
||||
` projections.login_policies3.default_redirect_uri,`+
|
||||
` projections.login_policies3.password_check_lifetime,`+
|
||||
` projections.login_policies3.external_login_check_lifetime,`+
|
||||
` projections.login_policies3.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies3.second_factor_check_lifetime,`+
|
||||
` projections.login_policies3.multi_factor_check_lifetime,`+
|
||||
` projections.idp_login_policy_links3.idp_id,`+
|
||||
` projections.idps2.name,`+
|
||||
` projections.idps2.type`+
|
||||
` FROM projections.login_policies2`+
|
||||
` FROM projections.login_policies3`+
|
||||
` LEFT JOIN projections.idp_login_policy_links3 ON `+
|
||||
` projections.login_policies2.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` projections.login_policies3.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` LEFT JOIN projections.idps2 ON`+
|
||||
` projections.idp_login_policy_links3.idp_id = projections.idps2.id`),
|
||||
[]string{
|
||||
@@ -121,6 +125,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
"hide_password_reset",
|
||||
"ignore_unknown_usernames",
|
||||
"allow_domain_discovery",
|
||||
"disable_login_with_email",
|
||||
"disable_login_with_phone",
|
||||
"default_redirect_uri",
|
||||
"password_check_lifetime",
|
||||
"external_login_check_lifetime",
|
||||
@@ -147,6 +153,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Hour * 2,
|
||||
time.Hour * 2,
|
||||
@@ -175,6 +183,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
HidePasswordReset: true,
|
||||
IgnoreUnknownUsernames: true,
|
||||
AllowDomainDiscovery: true,
|
||||
DisableLoginWithEmail: true,
|
||||
DisableLoginWithPhone: true,
|
||||
DefaultRedirectURI: "https://example.com/redirect",
|
||||
PasswordCheckLifetime: time.Hour * 2,
|
||||
ExternalLoginCheckLifetime: time.Hour * 2,
|
||||
@@ -195,33 +205,35 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.aggregate_id,`+
|
||||
` projections.login_policies2.creation_date,`+
|
||||
` projections.login_policies2.change_date,`+
|
||||
` projections.login_policies2.sequence,`+
|
||||
` projections.login_policies2.allow_register,`+
|
||||
` projections.login_policies2.allow_username_password,`+
|
||||
` projections.login_policies2.allow_external_idps,`+
|
||||
` projections.login_policies2.force_mfa,`+
|
||||
` projections.login_policies2.second_factors,`+
|
||||
` projections.login_policies2.multi_factors,`+
|
||||
` projections.login_policies2.passwordless_type,`+
|
||||
` projections.login_policies2.is_default,`+
|
||||
` projections.login_policies2.hide_password_reset,`+
|
||||
` projections.login_policies2.ignore_unknown_usernames,`+
|
||||
` projections.login_policies2.allow_domain_discovery,`+
|
||||
` projections.login_policies2.default_redirect_uri,`+
|
||||
` projections.login_policies2.password_check_lifetime,`+
|
||||
` projections.login_policies2.external_login_check_lifetime,`+
|
||||
` projections.login_policies2.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies2.second_factor_check_lifetime,`+
|
||||
` projections.login_policies2.multi_factor_check_lifetime,`+
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies3.aggregate_id,`+
|
||||
` projections.login_policies3.creation_date,`+
|
||||
` projections.login_policies3.change_date,`+
|
||||
` projections.login_policies3.sequence,`+
|
||||
` projections.login_policies3.allow_register,`+
|
||||
` projections.login_policies3.allow_username_password,`+
|
||||
` projections.login_policies3.allow_external_idps,`+
|
||||
` projections.login_policies3.force_mfa,`+
|
||||
` projections.login_policies3.second_factors,`+
|
||||
` projections.login_policies3.multi_factors,`+
|
||||
` projections.login_policies3.passwordless_type,`+
|
||||
` projections.login_policies3.is_default,`+
|
||||
` projections.login_policies3.hide_password_reset,`+
|
||||
` projections.login_policies3.ignore_unknown_usernames,`+
|
||||
` projections.login_policies3.allow_domain_discovery,`+
|
||||
` projections.login_policies3.disable_login_with_email,`+
|
||||
` projections.login_policies3.disable_login_with_phone,`+
|
||||
` projections.login_policies3.default_redirect_uri,`+
|
||||
` projections.login_policies3.password_check_lifetime,`+
|
||||
` projections.login_policies3.external_login_check_lifetime,`+
|
||||
` projections.login_policies3.mfa_init_skip_lifetime,`+
|
||||
` projections.login_policies3.second_factor_check_lifetime,`+
|
||||
` projections.login_policies3.multi_factor_check_lifetime,`+
|
||||
` projections.idp_login_policy_links3.idp_id,`+
|
||||
` projections.idps2.name,`+
|
||||
` projections.idps2.type`+
|
||||
` FROM projections.login_policies2`+
|
||||
` FROM projections.login_policies3`+
|
||||
` LEFT JOIN projections.idp_login_policy_links3 ON `+
|
||||
` projections.login_policies2.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` projections.login_policies3.aggregate_id = projections.idp_login_policy_links3.aggregate_id`+
|
||||
` LEFT JOIN projections.idps2 ON`+
|
||||
` projections.idp_login_policy_links3.idp_id = projections.idps2.id`),
|
||||
sql.ErrConnDone,
|
||||
@@ -240,8 +252,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies3.second_factors`+
|
||||
` FROM projections.login_policies3`),
|
||||
[]string{
|
||||
"second_factors",
|
||||
},
|
||||
@@ -261,8 +273,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies3.second_factors`+
|
||||
` FROM projections.login_policies3`),
|
||||
[]string{
|
||||
"second_factors",
|
||||
},
|
||||
@@ -283,8 +295,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies3.second_factors`+
|
||||
` FROM projections.login_policies3`),
|
||||
[]string{
|
||||
"second_factors",
|
||||
},
|
||||
@@ -300,8 +312,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicy2FAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.second_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies3.second_factors`+
|
||||
` FROM projections.login_policies3`),
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
@@ -318,8 +330,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies3.multi_factors`+
|
||||
` FROM projections.login_policies3`),
|
||||
[]string{
|
||||
"multi_factors",
|
||||
},
|
||||
@@ -339,8 +351,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies3.multi_factors`+
|
||||
` FROM projections.login_policies3`),
|
||||
[]string{
|
||||
"multi_factors",
|
||||
},
|
||||
@@ -361,8 +373,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQuery(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies3.multi_factors`+
|
||||
` FROM projections.login_policies3`),
|
||||
[]string{
|
||||
"multi_factors",
|
||||
},
|
||||
@@ -378,8 +390,8 @@ func Test_LoginPolicyPrepares(t *testing.T) {
|
||||
prepare: prepareLoginPolicyMFAsQuery,
|
||||
want: want{
|
||||
sqlExpectations: mockQueryErr(
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies2.multi_factors`+
|
||||
` FROM projections.login_policies2`),
|
||||
regexp.QuoteMeta(`SELECT projections.login_policies3.multi_factors`+
|
||||
` FROM projections.login_policies3`),
|
||||
sql.ErrConnDone,
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
|
@@ -20,18 +20,18 @@ var (
|
||||
", members.user_id" +
|
||||
", members.roles" +
|
||||
", projections.login_names.login_name" +
|
||||
", projections.users3_humans.email" +
|
||||
", projections.users3_humans.first_name" +
|
||||
", projections.users3_humans.last_name" +
|
||||
", projections.users3_humans.display_name" +
|
||||
", projections.users3_machines.name" +
|
||||
", projections.users3_humans.avatar_key" +
|
||||
", projections.users4_humans.email" +
|
||||
", projections.users4_humans.first_name" +
|
||||
", projections.users4_humans.last_name" +
|
||||
", projections.users4_humans.display_name" +
|
||||
", projections.users4_machines.name" +
|
||||
", projections.users4_humans.avatar_key" +
|
||||
", COUNT(*) OVER () " +
|
||||
"FROM projections.org_members2 AS members " +
|
||||
"LEFT JOIN projections.users3_humans " +
|
||||
"ON members.user_id = projections.users3_humans.user_id " +
|
||||
"LEFT JOIN projections.users3_machines " +
|
||||
"ON members.user_id = projections.users3_machines.user_id " +
|
||||
"LEFT JOIN projections.users4_humans " +
|
||||
"ON members.user_id = projections.users4_humans.user_id " +
|
||||
"LEFT JOIN projections.users4_machines " +
|
||||
"ON members.user_id = projections.users4_machines.user_id " +
|
||||
"LEFT JOIN projections.login_names " +
|
||||
"ON members.user_id = projections.login_names.user_id " +
|
||||
"WHERE projections.login_names.is_primary = $1")
|
||||
|
@@ -20,18 +20,18 @@ var (
|
||||
", members.user_id" +
|
||||
", members.roles" +
|
||||
", projections.login_names.login_name" +
|
||||
", projections.users3_humans.email" +
|
||||
", projections.users3_humans.first_name" +
|
||||
", projections.users3_humans.last_name" +
|
||||
", projections.users3_humans.display_name" +
|
||||
", projections.users3_machines.name" +
|
||||
", projections.users3_humans.avatar_key" +
|
||||
", projections.users4_humans.email" +
|
||||
", projections.users4_humans.first_name" +
|
||||
", projections.users4_humans.last_name" +
|
||||
", projections.users4_humans.display_name" +
|
||||
", projections.users4_machines.name" +
|
||||
", projections.users4_humans.avatar_key" +
|
||||
", COUNT(*) OVER () " +
|
||||
"FROM projections.project_grant_members2 AS members " +
|
||||
"LEFT JOIN projections.users3_humans " +
|
||||
"ON members.user_id = projections.users3_humans.user_id " +
|
||||
"LEFT JOIN projections.users3_machines " +
|
||||
"ON members.user_id = projections.users3_machines.user_id " +
|
||||
"LEFT JOIN projections.users4_humans " +
|
||||
"ON members.user_id = projections.users4_humans.user_id " +
|
||||
"LEFT JOIN projections.users4_machines " +
|
||||
"ON members.user_id = projections.users4_machines.user_id " +
|
||||
"LEFT JOIN projections.login_names " +
|
||||
"ON members.user_id = projections.login_names.user_id " +
|
||||
"LEFT JOIN projections.project_grants2 " +
|
||||
|
@@ -20,18 +20,18 @@ var (
|
||||
", members.user_id" +
|
||||
", members.roles" +
|
||||
", projections.login_names.login_name" +
|
||||
", projections.users3_humans.email" +
|
||||
", projections.users3_humans.first_name" +
|
||||
", projections.users3_humans.last_name" +
|
||||
", projections.users3_humans.display_name" +
|
||||
", projections.users3_machines.name" +
|
||||
", projections.users3_humans.avatar_key" +
|
||||
", projections.users4_humans.email" +
|
||||
", projections.users4_humans.first_name" +
|
||||
", projections.users4_humans.last_name" +
|
||||
", projections.users4_humans.display_name" +
|
||||
", projections.users4_machines.name" +
|
||||
", projections.users4_humans.avatar_key" +
|
||||
", COUNT(*) OVER () " +
|
||||
"FROM projections.project_members2 AS members " +
|
||||
"LEFT JOIN projections.users3_humans " +
|
||||
"ON members.user_id = projections.users3_humans.user_id " +
|
||||
"LEFT JOIN projections.users3_machines " +
|
||||
"ON members.user_id = projections.users3_machines.user_id " +
|
||||
"LEFT JOIN projections.users4_humans " +
|
||||
"ON members.user_id = projections.users4_humans.user_id " +
|
||||
"LEFT JOIN projections.users4_machines " +
|
||||
"ON members.user_id = projections.users4_machines.user_id " +
|
||||
"LEFT JOIN projections.login_names " +
|
||||
"ON members.user_id = projections.login_names.user_id " +
|
||||
"WHERE projections.login_names.is_primary = $1")
|
||||
|
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
LoginPolicyTable = "projections.login_policies2"
|
||||
LoginPolicyTable = "projections.login_policies3"
|
||||
|
||||
LoginPolicyIDCol = "aggregate_id"
|
||||
LoginPolicyInstanceIDCol = "instance_id"
|
||||
@@ -31,6 +31,8 @@ const (
|
||||
LoginPolicyHidePWResetCol = "hide_password_reset"
|
||||
IgnoreUnknownUsernames = "ignore_unknown_usernames"
|
||||
AllowDomainDiscovery = "allow_domain_discovery"
|
||||
DisableLoginWithEmail = "disable_login_with_email"
|
||||
DisableLoginWithPhone = "disable_login_with_phone"
|
||||
DefaultRedirectURI = "default_redirect_uri"
|
||||
PasswordCheckLifetimeCol = "password_check_lifetime"
|
||||
ExternalLoginCheckLifetimeCol = "external_login_check_lifetime"
|
||||
@@ -65,6 +67,8 @@ func newLoginPolicyProjection(ctx context.Context, config crdb.StatementHandlerC
|
||||
crdb.NewColumn(LoginPolicyHidePWResetCol, crdb.ColumnTypeBool),
|
||||
crdb.NewColumn(IgnoreUnknownUsernames, crdb.ColumnTypeBool),
|
||||
crdb.NewColumn(AllowDomainDiscovery, crdb.ColumnTypeBool),
|
||||
crdb.NewColumn(DisableLoginWithEmail, crdb.ColumnTypeBool),
|
||||
crdb.NewColumn(DisableLoginWithPhone, crdb.ColumnTypeBool),
|
||||
crdb.NewColumn(DefaultRedirectURI, crdb.ColumnTypeText, crdb.Nullable()),
|
||||
crdb.NewColumn(PasswordCheckLifetimeCol, crdb.ColumnTypeInt64),
|
||||
crdb.NewColumn(ExternalLoginCheckLifetimeCol, crdb.ColumnTypeInt64),
|
||||
@@ -175,6 +179,8 @@ func (p *loginPolicyProjection) reduceLoginPolicyAdded(event eventstore.Event) (
|
||||
handler.NewCol(LoginPolicyHidePWResetCol, policyEvent.HidePasswordReset),
|
||||
handler.NewCol(IgnoreUnknownUsernames, policyEvent.IgnoreUnknownUsernames),
|
||||
handler.NewCol(AllowDomainDiscovery, policyEvent.AllowDomainDiscovery),
|
||||
handler.NewCol(DisableLoginWithEmail, policyEvent.DisableLoginWithEmail),
|
||||
handler.NewCol(DisableLoginWithPhone, policyEvent.DisableLoginWithPhone),
|
||||
handler.NewCol(DefaultRedirectURI, policyEvent.DefaultRedirectURI),
|
||||
handler.NewCol(PasswordCheckLifetimeCol, policyEvent.PasswordCheckLifetime),
|
||||
handler.NewCol(ExternalLoginCheckLifetimeCol, policyEvent.ExternalLoginCheckLifetime),
|
||||
@@ -223,6 +229,12 @@ func (p *loginPolicyProjection) reduceLoginPolicyChanged(event eventstore.Event)
|
||||
if policyEvent.AllowDomainDiscovery != nil {
|
||||
cols = append(cols, handler.NewCol(AllowDomainDiscovery, *policyEvent.AllowDomainDiscovery))
|
||||
}
|
||||
if policyEvent.DisableLoginWithEmail != nil {
|
||||
cols = append(cols, handler.NewCol(DisableLoginWithEmail, *policyEvent.DisableLoginWithEmail))
|
||||
}
|
||||
if policyEvent.DisableLoginWithPhone != nil {
|
||||
cols = append(cols, handler.NewCol(DisableLoginWithPhone, *policyEvent.DisableLoginWithPhone))
|
||||
}
|
||||
if policyEvent.DefaultRedirectURI != nil {
|
||||
cols = append(cols, handler.NewCol(DefaultRedirectURI, *policyEvent.DefaultRedirectURI))
|
||||
}
|
||||
|
@@ -37,6 +37,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"disableLoginWithEmail": true,
|
||||
"disableLoginWithPhone": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect",
|
||||
"passwordCheckLifetime": 10000000,
|
||||
@@ -56,7 +58,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.login_policies2 (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)",
|
||||
expectedStmt: "INSERT INTO projections.login_policies3 (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, disable_login_with_email, disable_login_with_phone, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -72,6 +74,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
@@ -99,6 +103,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"disableLoginWithEmail": true,
|
||||
"disableLoginWithPhone": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect",
|
||||
"passwordCheckLifetime": 10000000,
|
||||
@@ -117,7 +123,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) WHERE (aggregate_id = $17)",
|
||||
expectedStmt: "UPDATE projections.login_policies3 SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, disable_login_with_email, disable_login_with_phone, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18) WHERE (aggregate_id = $19)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -129,6 +135,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
@@ -162,7 +170,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies3 SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -194,7 +202,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies3 SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -224,7 +232,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.login_policies2 WHERE (aggregate_id = $1)",
|
||||
expectedStmt: "DELETE FROM projections.login_policies3 WHERE (aggregate_id = $1)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
},
|
||||
@@ -253,7 +261,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies3 SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -285,7 +293,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies3 SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -312,6 +320,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"disableLoginWithEmail": true,
|
||||
"disableLoginWithPhone": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect",
|
||||
"passwordCheckLifetime": 10000000,
|
||||
@@ -330,7 +340,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.login_policies2 (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)",
|
||||
expectedStmt: "INSERT INTO projections.login_policies3 (aggregate_id, instance_id, creation_date, change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, is_default, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, disable_login_with_email, disable_login_with_phone, default_redirect_uri, password_check_lifetime, external_login_check_lifetime, mfa_init_skip_lifetime, second_factor_check_lifetime, multi_factor_check_lifetime) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -346,6 +356,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
time.Millisecond * 10,
|
||||
time.Millisecond * 10,
|
||||
@@ -373,6 +385,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
"hidePasswordReset": true,
|
||||
"ignoreUnknownUsernames": true,
|
||||
"allowDomainDiscovery": true,
|
||||
"disableLoginWithEmail": true,
|
||||
"disableLoginWithPhone": true,
|
||||
"passwordlessType": 1,
|
||||
"defaultRedirectURI": "https://example.com/redirect"
|
||||
}`),
|
||||
@@ -386,7 +400,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, default_redirect_uri) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) WHERE (aggregate_id = $12)",
|
||||
expectedStmt: "UPDATE projections.login_policies3 SET (change_date, sequence, allow_register, allow_username_password, allow_external_idps, force_mfa, passwordless_type, hide_password_reset, ignore_unknown_usernames, allow_domain_discovery, disable_login_with_email, disable_login_with_phone, default_redirect_uri) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) WHERE (aggregate_id = $14)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -398,6 +412,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"https://example.com/redirect",
|
||||
"agg-id",
|
||||
},
|
||||
@@ -426,7 +442,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies3 SET (change_date, sequence, multi_factors) = ($1, $2, array_append(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -458,7 +474,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies3 SET (change_date, sequence, multi_factors) = ($1, $2, array_remove(multi_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -490,7 +506,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies3 SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -522,7 +538,7 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.login_policies2 SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedStmt: "UPDATE projections.login_policies3 SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
|
@@ -17,7 +17,7 @@ type userProjection struct {
|
||||
}
|
||||
|
||||
const (
|
||||
UserTable = "projections.users3"
|
||||
UserTable = "projections.users4"
|
||||
UserHumanTable = UserTable + "_" + UserHumanSuffix
|
||||
UserMachineTable = UserTable + "_" + UserMachineSuffix
|
||||
UserNotifyTable = UserTable + "_" + UserNotifySuffix
|
||||
@@ -88,9 +88,9 @@ func newUserProjection(ctx context.Context, config crdb.StatementHandlerConfig)
|
||||
crdb.NewColumn(UserTypeCol, crdb.ColumnTypeEnum),
|
||||
},
|
||||
crdb.NewPrimaryKey(UserIDCol, UserInstanceIDCol),
|
||||
crdb.WithIndex(crdb.NewIndex("username_idx", []string{UserUsernameCol})),
|
||||
crdb.WithIndex(crdb.NewIndex("user_ro_idx", []string{UserResourceOwnerCol})),
|
||||
crdb.WithConstraint(crdb.NewConstraint("user_id_unique", []string{UserIDCol})),
|
||||
crdb.WithIndex(crdb.NewIndex("username_idx4", []string{UserUsernameCol})),
|
||||
crdb.WithIndex(crdb.NewIndex("user_ro_idx4", []string{UserResourceOwnerCol})),
|
||||
crdb.WithConstraint(crdb.NewConstraint("user_id_unique4", []string{UserIDCol})),
|
||||
),
|
||||
crdb.NewSuffixedTable([]*crdb.Column{
|
||||
crdb.NewColumn(HumanUserIDCol, crdb.ColumnTypeText),
|
||||
@@ -109,7 +109,7 @@ func newUserProjection(ctx context.Context, config crdb.StatementHandlerConfig)
|
||||
},
|
||||
crdb.NewPrimaryKey(HumanUserIDCol, HumanUserInstanceIDCol),
|
||||
UserHumanSuffix,
|
||||
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_human_ref_user")),
|
||||
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_human_ref_user4")),
|
||||
),
|
||||
crdb.NewSuffixedTable([]*crdb.Column{
|
||||
crdb.NewColumn(MachineUserIDCol, crdb.ColumnTypeText),
|
||||
@@ -119,7 +119,7 @@ func newUserProjection(ctx context.Context, config crdb.StatementHandlerConfig)
|
||||
},
|
||||
crdb.NewPrimaryKey(MachineUserIDCol, MachineUserInstanceIDCol),
|
||||
UserMachineSuffix,
|
||||
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_machine_ref_user")),
|
||||
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_machine_ref_user4")),
|
||||
),
|
||||
crdb.NewSuffixedTable([]*crdb.Column{
|
||||
crdb.NewColumn(NotifyUserIDCol, crdb.ColumnTypeText),
|
||||
@@ -132,7 +132,7 @@ func newUserProjection(ctx context.Context, config crdb.StatementHandlerConfig)
|
||||
},
|
||||
crdb.NewPrimaryKey(NotifyUserIDCol, NotifyInstanceIDCol),
|
||||
UserNotifySuffix,
|
||||
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_notify_ref_user")),
|
||||
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_notify_ref_user4")),
|
||||
),
|
||||
)
|
||||
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
|
||||
@@ -708,20 +708,9 @@ func (p *userProjection) reduceHumanPhoneVerified(event eventstore.Event) (*hand
|
||||
},
|
||||
crdb.WithTableSuffix(UserHumanSuffix),
|
||||
),
|
||||
crdb.AddCopyStatement(
|
||||
crdb.AddUpdateStatement(
|
||||
[]handler.Column{
|
||||
handler.NewCol(NotifyUserIDCol, nil),
|
||||
handler.NewCol(NotifyInstanceIDCol, nil),
|
||||
},
|
||||
[]handler.Column{
|
||||
handler.NewCol(NotifyUserIDCol, nil),
|
||||
handler.NewCol(NotifyInstanceIDCol, nil),
|
||||
handler.NewCol(NotifyLastPhoneCol, nil),
|
||||
},
|
||||
[]handler.Column{
|
||||
handler.NewCol(NotifyUserIDCol, nil),
|
||||
handler.NewCol(NotifyInstanceIDCol, nil),
|
||||
handler.NewCol(NotifyVerifiedPhoneCol, nil),
|
||||
crdb.NewCopyCol(NotifyVerifiedPhoneCol, NotifyLastPhoneCol),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(NotifyUserIDCol, e.Aggregate().ID),
|
||||
@@ -802,20 +791,9 @@ func (p *userProjection) reduceHumanEmailVerified(event eventstore.Event) (*hand
|
||||
},
|
||||
crdb.WithTableSuffix(UserHumanSuffix),
|
||||
),
|
||||
crdb.AddCopyStatement(
|
||||
crdb.AddUpdateStatement(
|
||||
[]handler.Column{
|
||||
handler.NewCol(NotifyUserIDCol, nil),
|
||||
handler.NewCol(NotifyInstanceIDCol, nil),
|
||||
},
|
||||
[]handler.Column{
|
||||
handler.NewCol(NotifyUserIDCol, nil),
|
||||
handler.NewCol(NotifyInstanceIDCol, nil),
|
||||
handler.NewCol(NotifyLastEmailCol, nil),
|
||||
},
|
||||
[]handler.Column{
|
||||
handler.NewCol(NotifyUserIDCol, nil),
|
||||
handler.NewCol(NotifyInstanceIDCol, nil),
|
||||
handler.NewCol(NotifyVerifiedEmailCol, nil),
|
||||
crdb.NewCopyCol(NotifyVerifiedEmailCol, NotifyLastEmailCol),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(NotifyUserIDCol, e.Aggregate().ID),
|
||||
|
@@ -50,7 +50,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.users4 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
@@ -64,7 +64,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedStmt: "INSERT INTO projections.users4_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -79,7 +79,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedStmt: "INSERT INTO projections.users4_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -120,7 +120,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.users4 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
@@ -134,7 +134,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedStmt: "INSERT INTO projections.users4_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -149,7 +149,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedStmt: "INSERT INTO projections.users4_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -185,7 +185,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.users4 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
@@ -199,7 +199,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedStmt: "INSERT INTO projections.users4_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -214,7 +214,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedStmt: "INSERT INTO projections.users4_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -255,7 +255,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.users4 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
@@ -269,7 +269,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedStmt: "INSERT INTO projections.users4_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -284,7 +284,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedStmt: "INSERT INTO projections.users4_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -325,7 +325,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.users4 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
@@ -339,7 +339,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedStmt: "INSERT INTO projections.users4_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -354,7 +354,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedStmt: "INSERT INTO projections.users4_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -390,7 +390,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.users4 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
@@ -404,7 +404,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedStmt: "INSERT INTO projections.users4_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -419,7 +419,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedStmt: "INSERT INTO projections.users4_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -450,7 +450,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
domain.UserStateInitial,
|
||||
"agg-id",
|
||||
@@ -479,7 +479,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
domain.UserStateInitial,
|
||||
"agg-id",
|
||||
@@ -508,7 +508,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
domain.UserStateActive,
|
||||
"agg-id",
|
||||
@@ -537,7 +537,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
domain.UserStateActive,
|
||||
"agg-id",
|
||||
@@ -566,7 +566,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
domain.UserStateLocked,
|
||||
@@ -597,7 +597,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
domain.UserStateActive,
|
||||
@@ -628,7 +628,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
domain.UserStateInactive,
|
||||
@@ -659,7 +659,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
domain.UserStateActive,
|
||||
@@ -690,7 +690,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "DELETE FROM projections.users3 WHERE (id = $1) AND (instance_id = $2)",
|
||||
expectedStmt: "DELETE FROM projections.users4 WHERE (id = $1) AND (instance_id = $2)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -720,7 +720,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
"username",
|
||||
@@ -753,7 +753,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
"id@temporary.domain",
|
||||
@@ -791,7 +791,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -800,7 +800,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)",
|
||||
expectedArgs: []interface{}{
|
||||
"first-name",
|
||||
"last-name",
|
||||
@@ -841,7 +841,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -850,7 +850,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET (first_name, last_name, nick_name, display_name, preferred_language, gender) = ($1, $2, $3, $4, $5, $6) WHERE (user_id = $7) AND (instance_id = $8)",
|
||||
expectedArgs: []interface{}{
|
||||
"first-name",
|
||||
"last-name",
|
||||
@@ -886,7 +886,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -895,7 +895,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
"+41 00 000 00 00",
|
||||
false,
|
||||
@@ -904,7 +904,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_notifications SET last_phone = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_notifications SET last_phone = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
|
||||
"agg-id",
|
||||
@@ -935,7 +935,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -944,7 +944,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
"+41 00 000 00 00",
|
||||
false,
|
||||
@@ -953,7 +953,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_notifications SET last_phone = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_notifications SET last_phone = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
|
||||
"agg-id",
|
||||
@@ -982,7 +982,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -991,7 +991,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
nil,
|
||||
nil,
|
||||
@@ -1000,7 +1000,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
nil,
|
||||
nil,
|
||||
@@ -1030,7 +1030,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1039,7 +1039,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
nil,
|
||||
nil,
|
||||
@@ -1048,7 +1048,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
nil,
|
||||
nil,
|
||||
@@ -1078,7 +1078,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1087,7 +1087,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
true,
|
||||
"agg-id",
|
||||
@@ -1095,7 +1095,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, verified_phone) SELECT user_id, instance_id, last_phone FROM projections.users3_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2 ON CONFLICT (user_id, instance_id) DO UPDATE SET (user_id, instance_id, verified_phone) = (EXCLUDED.user_id, EXCLUDED.instance_id, EXCLUDED.last_phone)",
|
||||
expectedStmt: "UPDATE projections.users4_notifications SET verified_phone = last_phone WHERE (user_id = $1) AND (instance_id = $2)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -1123,7 +1123,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1132,7 +1132,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
true,
|
||||
"agg-id",
|
||||
@@ -1140,7 +1140,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, verified_phone) SELECT user_id, instance_id, last_phone FROM projections.users3_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2 ON CONFLICT (user_id, instance_id) DO UPDATE SET (user_id, instance_id, verified_phone) = (EXCLUDED.user_id, EXCLUDED.instance_id, EXCLUDED.last_phone)",
|
||||
expectedStmt: "UPDATE projections.users4_notifications SET verified_phone = last_phone WHERE (user_id = $1) AND (instance_id = $2)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -1170,7 +1170,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1179,7 +1179,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
"email@zitadel.com",
|
||||
false,
|
||||
@@ -1188,7 +1188,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_notifications SET last_email = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_notifications SET last_email = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
&sql.NullString{String: "email@zitadel.com", Valid: true},
|
||||
"agg-id",
|
||||
@@ -1219,7 +1219,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1228,7 +1228,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
"email@zitadel.com",
|
||||
false,
|
||||
@@ -1237,7 +1237,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_notifications SET last_email = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_notifications SET last_email = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
&sql.NullString{String: "email@zitadel.com", Valid: true},
|
||||
"agg-id",
|
||||
@@ -1266,7 +1266,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1275,7 +1275,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
true,
|
||||
"agg-id",
|
||||
@@ -1283,7 +1283,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, verified_email) SELECT user_id, instance_id, last_email FROM projections.users3_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2 ON CONFLICT (user_id, instance_id) DO UPDATE SET (user_id, instance_id, verified_email) = (EXCLUDED.user_id, EXCLUDED.instance_id, EXCLUDED.last_email)",
|
||||
expectedStmt: "UPDATE projections.users4_notifications SET verified_email = last_email WHERE (user_id = $1) AND (instance_id = $2)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -1311,7 +1311,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1320,7 +1320,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
true,
|
||||
"agg-id",
|
||||
@@ -1328,7 +1328,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_notifications (user_id, instance_id, verified_email) SELECT user_id, instance_id, last_email FROM projections.users3_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2 ON CONFLICT (user_id, instance_id) DO UPDATE SET (user_id, instance_id, verified_email) = (EXCLUDED.user_id, EXCLUDED.instance_id, EXCLUDED.last_email)",
|
||||
expectedStmt: "UPDATE projections.users4_notifications SET verified_email = last_email WHERE (user_id = $1) AND (instance_id = $2)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -1358,7 +1358,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1367,7 +1367,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
"users/agg-id/avatar",
|
||||
"agg-id",
|
||||
@@ -1396,7 +1396,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1405,7 +1405,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
nil,
|
||||
"agg-id",
|
||||
@@ -1437,7 +1437,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.users4 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
@@ -1451,7 +1451,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
|
||||
expectedStmt: "INSERT INTO projections.users4_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -1485,7 +1485,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedStmt: "INSERT INTO projections.users4 (id, creation_date, change_date, resource_owner, instance_id, state, sequence, username, type) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
anyArg{},
|
||||
@@ -1499,7 +1499,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "INSERT INTO projections.users3_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
|
||||
expectedStmt: "INSERT INTO projections.users4_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
|
||||
expectedArgs: []interface{}{
|
||||
"agg-id",
|
||||
"instance-id",
|
||||
@@ -1532,7 +1532,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1541,7 +1541,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_machines SET (name, description) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4_machines SET (name, description) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
"machine-name",
|
||||
"description",
|
||||
@@ -1573,7 +1573,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1582,7 +1582,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_machines SET name = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_machines SET name = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
"machine-name",
|
||||
"agg-id",
|
||||
@@ -1613,7 +1613,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
executer: &testExecuter{
|
||||
executions: []execution{
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedStmt: "UPDATE projections.users4 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
|
||||
expectedArgs: []interface{}{
|
||||
anyArg{},
|
||||
uint64(15),
|
||||
@@ -1622,7 +1622,7 @@ func TestUserProjection_reduces(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedStmt: "UPDATE projections.users3_machines SET description = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedStmt: "UPDATE projections.users4_machines SET description = $1 WHERE (user_id = $2) AND (instance_id = $3)",
|
||||
expectedArgs: []interface{}{
|
||||
"description",
|
||||
"agg-id",
|
||||
|
@@ -388,7 +388,7 @@ func (q *Queries) GetHumanPhone(ctx context.Context, userID string, queries ...S
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
func (q *Queries) GeNotifyUser(ctx context.Context, shouldTriggered bool, userID string, queries ...SearchQuery) (*NotifyUser, error) {
|
||||
func (q *Queries) GetNotifyUserByID(ctx context.Context, shouldTriggered bool, userID string, queries ...SearchQuery) (*NotifyUser, error) {
|
||||
if shouldTriggered {
|
||||
projection.UserProjection.Trigger(ctx)
|
||||
projection.LoginNameProjection.Trigger(ctx)
|
||||
@@ -411,6 +411,28 @@ func (q *Queries) GeNotifyUser(ctx context.Context, shouldTriggered bool, userID
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
func (q *Queries) GetNotifyUser(ctx context.Context, shouldTriggered bool, queries ...SearchQuery) (*NotifyUser, error) {
|
||||
if shouldTriggered {
|
||||
projection.UserProjection.Trigger(ctx)
|
||||
projection.LoginNameProjection.Trigger(ctx)
|
||||
}
|
||||
|
||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||
query, scan := prepareNotifyUserQuery(instanceID)
|
||||
for _, q := range queries {
|
||||
query = q.toQuery(query)
|
||||
}
|
||||
stmt, args, err := query.Where(sq.Eq{
|
||||
UserInstanceIDCol.identifier(): instanceID,
|
||||
}).ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.ThrowInternal(err, "QUERY-Err3g", "Errors.Query.SQLStatment")
|
||||
}
|
||||
|
||||
row := q.client.QueryRowContext(ctx, stmt, args...)
|
||||
return scan(row)
|
||||
}
|
||||
|
||||
func (q *Queries) SearchUsers(ctx context.Context, queries *UserSearchQueries) (*Users, error) {
|
||||
query, scan := prepareUsersQuery()
|
||||
stmt, args, err := queries.toQuery(query).
|
||||
@@ -492,27 +514,39 @@ func NewUserResourceOwnerSearchQuery(value string, comparison TextComparison) (S
|
||||
}
|
||||
|
||||
func NewUserUsernameSearchQuery(value string, comparison TextComparison) (SearchQuery, error) {
|
||||
return NewTextQuery(Column(UserUsernameCol), value, comparison)
|
||||
return NewTextQuery(UserUsernameCol, value, comparison)
|
||||
}
|
||||
|
||||
func NewUserFirstNameSearchQuery(value string, comparison TextComparison) (SearchQuery, error) {
|
||||
return NewTextQuery(Column(HumanFirstNameCol), value, comparison)
|
||||
return NewTextQuery(HumanFirstNameCol, value, comparison)
|
||||
}
|
||||
|
||||
func NewUserLastNameSearchQuery(value string, comparison TextComparison) (SearchQuery, error) {
|
||||
return NewTextQuery(Column(HumanLastNameCol), value, comparison)
|
||||
return NewTextQuery(HumanLastNameCol, value, comparison)
|
||||
}
|
||||
|
||||
func NewUserNickNameSearchQuery(value string, comparison TextComparison) (SearchQuery, error) {
|
||||
return NewTextQuery(Column(HumanNickNameCol), value, comparison)
|
||||
return NewTextQuery(HumanNickNameCol, value, comparison)
|
||||
}
|
||||
|
||||
func NewUserDisplayNameSearchQuery(value string, comparison TextComparison) (SearchQuery, error) {
|
||||
return NewTextQuery(Column(HumanDisplayNameCol), value, comparison)
|
||||
return NewTextQuery(HumanDisplayNameCol, value, comparison)
|
||||
}
|
||||
|
||||
func NewUserEmailSearchQuery(value string, comparison TextComparison) (SearchQuery, error) {
|
||||
return NewTextQuery(Column(HumanEmailCol), value, comparison)
|
||||
return NewTextQuery(HumanEmailCol, value, comparison)
|
||||
}
|
||||
|
||||
func NewUserPhoneSearchQuery(value string, comparison TextComparison) (SearchQuery, error) {
|
||||
return NewTextQuery(HumanPhoneCol, value, comparison)
|
||||
}
|
||||
|
||||
func NewUserVerifiedEmailSearchQuery(value string, comparison TextComparison) (SearchQuery, error) {
|
||||
return NewTextQuery(NotifyVerifiedEmailCol, value, comparison)
|
||||
}
|
||||
|
||||
func NewUserVerifiedPhoneSearchQuery(value string, comparison TextComparison) (SearchQuery, error) {
|
||||
return NewTextQuery(NotifyVerifiedPhoneCol, value, comparison)
|
||||
}
|
||||
|
||||
func NewUserStateSearchQuery(value int32) (SearchQuery, error) {
|
||||
@@ -580,6 +614,7 @@ func prepareUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row) (*Use
|
||||
MachineUserIDCol.identifier(),
|
||||
MachineNameCol.identifier(),
|
||||
MachineDescriptionCol.identifier(),
|
||||
countColumn.identifier(),
|
||||
).
|
||||
From(userTable.identifier()).
|
||||
LeftJoin(join(HumanUserIDCol, UserIDCol)).
|
||||
@@ -589,6 +624,7 @@ func prepareUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row) (*Use
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(row *sql.Row) (*User, error) {
|
||||
u := new(User)
|
||||
var count int
|
||||
preferredLoginName := sql.NullString{}
|
||||
|
||||
humanID := sql.NullString{}
|
||||
@@ -634,10 +670,11 @@ func prepareUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row) (*Use
|
||||
&machineID,
|
||||
&name,
|
||||
&description,
|
||||
&count,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
if errs.Is(err, sql.ErrNoRows) {
|
||||
if err != nil || count != 1 {
|
||||
if errs.Is(err, sql.ErrNoRows) || count != 1 {
|
||||
return nil, errors.ThrowNotFound(err, "QUERY-Dfbg2", "Errors.User.NotFound")
|
||||
}
|
||||
return nil, errors.ThrowInternal(err, "QUERY-Bgah2", "Errors.Internal")
|
||||
@@ -877,6 +914,7 @@ func prepareNotifyUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row)
|
||||
NotifyPhoneCol.identifier(),
|
||||
NotifyVerifiedPhoneCol.identifier(),
|
||||
NotifyPasswordSetCol.identifier(),
|
||||
countColumn.identifier(),
|
||||
).
|
||||
From(userTable.identifier()).
|
||||
LeftJoin(join(HumanUserIDCol, UserIDCol)).
|
||||
@@ -886,6 +924,7 @@ func prepareNotifyUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row)
|
||||
PlaceholderFormat(sq.Dollar),
|
||||
func(row *sql.Row) (*NotifyUser, error) {
|
||||
u := new(NotifyUser)
|
||||
var count int
|
||||
loginNames := database.StringArray{}
|
||||
preferredLoginName := sql.NullString{}
|
||||
|
||||
@@ -930,10 +969,11 @@ func prepareNotifyUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row)
|
||||
¬ifyPhone,
|
||||
¬ifyVerifiedPhone,
|
||||
¬ifyPasswordSet,
|
||||
&count,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
if errs.Is(err, sql.ErrNoRows) {
|
||||
if err != nil || count != 1 {
|
||||
if errs.Is(err, sql.ErrNoRows) || count != 1 {
|
||||
return nil, errors.ThrowNotFound(err, "QUERY-Dgqd2", "Errors.User.NotFound")
|
||||
}
|
||||
return nil, errors.ThrowInternal(err, "QUERY-Dbwsg", "Errors.Internal")
|
||||
|
@@ -23,14 +23,14 @@ var (
|
||||
", projections.user_grants2.roles" +
|
||||
", projections.user_grants2.state" +
|
||||
", projections.user_grants2.user_id" +
|
||||
", projections.users3.username" +
|
||||
", projections.users3.type" +
|
||||
", projections.users3.resource_owner" +
|
||||
", projections.users3_humans.first_name" +
|
||||
", projections.users3_humans.last_name" +
|
||||
", projections.users3_humans.email" +
|
||||
", projections.users3_humans.display_name" +
|
||||
", projections.users3_humans.avatar_key" +
|
||||
", projections.users4.username" +
|
||||
", projections.users4.type" +
|
||||
", projections.users4.resource_owner" +
|
||||
", projections.users4_humans.first_name" +
|
||||
", projections.users4_humans.last_name" +
|
||||
", projections.users4_humans.email" +
|
||||
", projections.users4_humans.display_name" +
|
||||
", projections.users4_humans.avatar_key" +
|
||||
", projections.login_names.login_name" +
|
||||
", projections.user_grants2.resource_owner" +
|
||||
", projections.orgs.name" +
|
||||
@@ -38,8 +38,8 @@ var (
|
||||
", projections.user_grants2.project_id" +
|
||||
", projections.projects2.name" +
|
||||
" FROM projections.user_grants2" +
|
||||
" LEFT JOIN projections.users3 ON projections.user_grants2.user_id = projections.users3.id" +
|
||||
" LEFT JOIN projections.users3_humans ON projections.user_grants2.user_id = projections.users3_humans.user_id" +
|
||||
" LEFT JOIN projections.users4 ON projections.user_grants2.user_id = projections.users4.id" +
|
||||
" LEFT JOIN projections.users4_humans ON projections.user_grants2.user_id = projections.users4_humans.user_id" +
|
||||
" LEFT JOIN projections.orgs ON projections.user_grants2.resource_owner = projections.orgs.id" +
|
||||
" LEFT JOIN projections.projects2 ON projections.user_grants2.project_id = projections.projects2.id" +
|
||||
" LEFT JOIN projections.login_names ON projections.user_grants2.user_id = projections.login_names.user_id" +
|
||||
@@ -77,14 +77,14 @@ var (
|
||||
", projections.user_grants2.roles" +
|
||||
", projections.user_grants2.state" +
|
||||
", projections.user_grants2.user_id" +
|
||||
", projections.users3.username" +
|
||||
", projections.users3.type" +
|
||||
", projections.users3.resource_owner" +
|
||||
", projections.users3_humans.first_name" +
|
||||
", projections.users3_humans.last_name" +
|
||||
", projections.users3_humans.email" +
|
||||
", projections.users3_humans.display_name" +
|
||||
", projections.users3_humans.avatar_key" +
|
||||
", projections.users4.username" +
|
||||
", projections.users4.type" +
|
||||
", projections.users4.resource_owner" +
|
||||
", projections.users4_humans.first_name" +
|
||||
", projections.users4_humans.last_name" +
|
||||
", projections.users4_humans.email" +
|
||||
", projections.users4_humans.display_name" +
|
||||
", projections.users4_humans.avatar_key" +
|
||||
", projections.login_names.login_name" +
|
||||
", projections.user_grants2.resource_owner" +
|
||||
", projections.orgs.name" +
|
||||
@@ -93,8 +93,8 @@ var (
|
||||
", projections.projects2.name" +
|
||||
", COUNT(*) OVER ()" +
|
||||
" FROM projections.user_grants2" +
|
||||
" LEFT JOIN projections.users3 ON projections.user_grants2.user_id = projections.users3.id" +
|
||||
" LEFT JOIN projections.users3_humans ON projections.user_grants2.user_id = projections.users3_humans.user_id" +
|
||||
" LEFT JOIN projections.users4 ON projections.user_grants2.user_id = projections.users4.id" +
|
||||
" LEFT JOIN projections.users4_humans ON projections.user_grants2.user_id = projections.users4_humans.user_id" +
|
||||
" LEFT JOIN projections.orgs ON projections.user_grants2.resource_owner = projections.orgs.id" +
|
||||
" LEFT JOIN projections.projects2 ON projections.user_grants2.project_id = projections.projects2.id" +
|
||||
" LEFT JOIN projections.login_names ON projections.user_grants2.user_id = projections.login_names.user_id" +
|
||||
|
@@ -17,43 +17,44 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
userQuery = `SELECT projections.users3.id,` +
|
||||
` projections.users3.creation_date,` +
|
||||
` projections.users3.change_date,` +
|
||||
` projections.users3.resource_owner,` +
|
||||
` projections.users3.sequence,` +
|
||||
` projections.users3.state,` +
|
||||
` projections.users3.type,` +
|
||||
` projections.users3.username,` +
|
||||
userQuery = `SELECT projections.users4.id,` +
|
||||
` projections.users4.creation_date,` +
|
||||
` projections.users4.change_date,` +
|
||||
` projections.users4.resource_owner,` +
|
||||
` projections.users4.sequence,` +
|
||||
` projections.users4.state,` +
|
||||
` projections.users4.type,` +
|
||||
` projections.users4.username,` +
|
||||
` login_names.loginnames,` +
|
||||
` preferred_login_name.login_name,` +
|
||||
` projections.users3_humans.user_id,` +
|
||||
` projections.users3_humans.first_name,` +
|
||||
` projections.users3_humans.last_name,` +
|
||||
` projections.users3_humans.nick_name,` +
|
||||
` projections.users3_humans.display_name,` +
|
||||
` projections.users3_humans.preferred_language,` +
|
||||
` projections.users3_humans.gender,` +
|
||||
` projections.users3_humans.avatar_key,` +
|
||||
` projections.users3_humans.email,` +
|
||||
` projections.users3_humans.is_email_verified,` +
|
||||
` projections.users3_humans.phone,` +
|
||||
` projections.users3_humans.is_phone_verified,` +
|
||||
` projections.users3_machines.user_id,` +
|
||||
` projections.users3_machines.name,` +
|
||||
` projections.users3_machines.description` +
|
||||
` FROM projections.users3` +
|
||||
` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id` +
|
||||
` LEFT JOIN projections.users3_machines ON projections.users3.id = projections.users3_machines.user_id` +
|
||||
` projections.users4_humans.user_id,` +
|
||||
` projections.users4_humans.first_name,` +
|
||||
` projections.users4_humans.last_name,` +
|
||||
` projections.users4_humans.nick_name,` +
|
||||
` projections.users4_humans.display_name,` +
|
||||
` projections.users4_humans.preferred_language,` +
|
||||
` projections.users4_humans.gender,` +
|
||||
` projections.users4_humans.avatar_key,` +
|
||||
` projections.users4_humans.email,` +
|
||||
` projections.users4_humans.is_email_verified,` +
|
||||
` projections.users4_humans.phone,` +
|
||||
` projections.users4_humans.is_phone_verified,` +
|
||||
` projections.users4_machines.user_id,` +
|
||||
` projections.users4_machines.name,` +
|
||||
` projections.users4_machines.description,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM projections.users4` +
|
||||
` LEFT JOIN projections.users4_humans ON projections.users4.id = projections.users4_humans.user_id` +
|
||||
` LEFT JOIN projections.users4_machines ON projections.users4.id = projections.users4_machines.user_id` +
|
||||
` LEFT JOIN` +
|
||||
` (SELECT login_names.user_id, ARRAY_AGG(login_names.login_name)::TEXT[] AS loginnames` +
|
||||
` FROM projections.login_names AS login_names` +
|
||||
` WHERE login_names.instance_id = $1` +
|
||||
` GROUP BY login_names.user_id) AS login_names` +
|
||||
` ON login_names.user_id = projections.users3.id` +
|
||||
` ON login_names.user_id = projections.users4.id` +
|
||||
` LEFT JOIN` +
|
||||
` (SELECT preferred_login_name.user_id, preferred_login_name.login_name FROM projections.login_names AS preferred_login_name WHERE preferred_login_name.instance_id = $2 AND preferred_login_name.is_primary = $3) AS preferred_login_name` +
|
||||
` ON preferred_login_name.user_id = projections.users3.id`
|
||||
` ON preferred_login_name.user_id = projections.users4.id`
|
||||
userCols = []string{
|
||||
"id",
|
||||
"creation_date",
|
||||
@@ -82,22 +83,23 @@ var (
|
||||
"user_id",
|
||||
"name",
|
||||
"description",
|
||||
"count",
|
||||
}
|
||||
profileQuery = `SELECT projections.users3.id,` +
|
||||
` projections.users3.creation_date,` +
|
||||
` projections.users3.change_date,` +
|
||||
` projections.users3.resource_owner,` +
|
||||
` projections.users3.sequence,` +
|
||||
` projections.users3_humans.user_id,` +
|
||||
` projections.users3_humans.first_name,` +
|
||||
` projections.users3_humans.last_name,` +
|
||||
` projections.users3_humans.nick_name,` +
|
||||
` projections.users3_humans.display_name,` +
|
||||
` projections.users3_humans.preferred_language,` +
|
||||
` projections.users3_humans.gender,` +
|
||||
` projections.users3_humans.avatar_key` +
|
||||
` FROM projections.users3` +
|
||||
` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id`
|
||||
profileQuery = `SELECT projections.users4.id,` +
|
||||
` projections.users4.creation_date,` +
|
||||
` projections.users4.change_date,` +
|
||||
` projections.users4.resource_owner,` +
|
||||
` projections.users4.sequence,` +
|
||||
` projections.users4_humans.user_id,` +
|
||||
` projections.users4_humans.first_name,` +
|
||||
` projections.users4_humans.last_name,` +
|
||||
` projections.users4_humans.nick_name,` +
|
||||
` projections.users4_humans.display_name,` +
|
||||
` projections.users4_humans.preferred_language,` +
|
||||
` projections.users4_humans.gender,` +
|
||||
` projections.users4_humans.avatar_key` +
|
||||
` FROM projections.users4` +
|
||||
` LEFT JOIN projections.users4_humans ON projections.users4.id = projections.users4_humans.user_id`
|
||||
profileCols = []string{
|
||||
"id",
|
||||
"creation_date",
|
||||
@@ -113,16 +115,16 @@ var (
|
||||
"gender",
|
||||
"avatar_key",
|
||||
}
|
||||
emailQuery = `SELECT projections.users3.id,` +
|
||||
` projections.users3.creation_date,` +
|
||||
` projections.users3.change_date,` +
|
||||
` projections.users3.resource_owner,` +
|
||||
` projections.users3.sequence,` +
|
||||
` projections.users3_humans.user_id,` +
|
||||
` projections.users3_humans.email,` +
|
||||
` projections.users3_humans.is_email_verified` +
|
||||
` FROM projections.users3` +
|
||||
` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id`
|
||||
emailQuery = `SELECT projections.users4.id,` +
|
||||
` projections.users4.creation_date,` +
|
||||
` projections.users4.change_date,` +
|
||||
` projections.users4.resource_owner,` +
|
||||
` projections.users4.sequence,` +
|
||||
` projections.users4_humans.user_id,` +
|
||||
` projections.users4_humans.email,` +
|
||||
` projections.users4_humans.is_email_verified` +
|
||||
` FROM projections.users4` +
|
||||
` LEFT JOIN projections.users4_humans ON projections.users4.id = projections.users4_humans.user_id`
|
||||
emailCols = []string{
|
||||
"id",
|
||||
"creation_date",
|
||||
@@ -133,16 +135,16 @@ var (
|
||||
"email",
|
||||
"is_email_verified",
|
||||
}
|
||||
phoneQuery = `SELECT projections.users3.id,` +
|
||||
` projections.users3.creation_date,` +
|
||||
` projections.users3.change_date,` +
|
||||
` projections.users3.resource_owner,` +
|
||||
` projections.users3.sequence,` +
|
||||
` projections.users3_humans.user_id,` +
|
||||
` projections.users3_humans.phone,` +
|
||||
` projections.users3_humans.is_phone_verified` +
|
||||
` FROM projections.users3` +
|
||||
` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id`
|
||||
phoneQuery = `SELECT projections.users4.id,` +
|
||||
` projections.users4.creation_date,` +
|
||||
` projections.users4.change_date,` +
|
||||
` projections.users4.resource_owner,` +
|
||||
` projections.users4.sequence,` +
|
||||
` projections.users4_humans.user_id,` +
|
||||
` projections.users4_humans.phone,` +
|
||||
` projections.users4_humans.is_phone_verified` +
|
||||
` FROM projections.users4` +
|
||||
` LEFT JOIN projections.users4_humans ON projections.users4.id = projections.users4_humans.user_id`
|
||||
phoneCols = []string{
|
||||
"id",
|
||||
"creation_date",
|
||||
@@ -153,14 +155,14 @@ var (
|
||||
"phone",
|
||||
"is_phone_verified",
|
||||
}
|
||||
userUniqueQuery = `SELECT projections.users3.id,` +
|
||||
` projections.users3.state,` +
|
||||
` projections.users3.username,` +
|
||||
` projections.users3_humans.user_id,` +
|
||||
` projections.users3_humans.email,` +
|
||||
` projections.users3_humans.is_email_verified` +
|
||||
` FROM projections.users3` +
|
||||
` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id`
|
||||
userUniqueQuery = `SELECT projections.users4.id,` +
|
||||
` projections.users4.state,` +
|
||||
` projections.users4.username,` +
|
||||
` projections.users4_humans.user_id,` +
|
||||
` projections.users4_humans.email,` +
|
||||
` projections.users4_humans.is_email_verified` +
|
||||
` FROM projections.users4` +
|
||||
` LEFT JOIN projections.users4_humans ON projections.users4.id = projections.users4_humans.user_id`
|
||||
userUniqueCols = []string{
|
||||
"id",
|
||||
"state",
|
||||
@@ -169,42 +171,43 @@ var (
|
||||
"email",
|
||||
"is_email_verified",
|
||||
}
|
||||
notifyUserQuery = `SELECT projections.users3.id,` +
|
||||
` projections.users3.creation_date,` +
|
||||
` projections.users3.change_date,` +
|
||||
` projections.users3.resource_owner,` +
|
||||
` projections.users3.sequence,` +
|
||||
` projections.users3.state,` +
|
||||
` projections.users3.type,` +
|
||||
` projections.users3.username,` +
|
||||
notifyUserQuery = `SELECT projections.users4.id,` +
|
||||
` projections.users4.creation_date,` +
|
||||
` projections.users4.change_date,` +
|
||||
` projections.users4.resource_owner,` +
|
||||
` projections.users4.sequence,` +
|
||||
` projections.users4.state,` +
|
||||
` projections.users4.type,` +
|
||||
` projections.users4.username,` +
|
||||
` login_names.loginnames,` +
|
||||
` preferred_login_name.login_name,` +
|
||||
` projections.users3_humans.user_id,` +
|
||||
` projections.users3_humans.first_name,` +
|
||||
` projections.users3_humans.last_name,` +
|
||||
` projections.users3_humans.nick_name,` +
|
||||
` projections.users3_humans.display_name,` +
|
||||
` projections.users3_humans.preferred_language,` +
|
||||
` projections.users3_humans.gender,` +
|
||||
` projections.users3_humans.avatar_key,` +
|
||||
` projections.users3_notifications.user_id,` +
|
||||
` projections.users3_notifications.last_email,` +
|
||||
` projections.users3_notifications.verified_email,` +
|
||||
` projections.users3_notifications.last_phone,` +
|
||||
` projections.users3_notifications.verified_phone,` +
|
||||
` projections.users3_notifications.password_set` +
|
||||
` FROM projections.users3` +
|
||||
` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id` +
|
||||
` LEFT JOIN projections.users3_notifications ON projections.users3.id = projections.users3_notifications.user_id` +
|
||||
` projections.users4_humans.user_id,` +
|
||||
` projections.users4_humans.first_name,` +
|
||||
` projections.users4_humans.last_name,` +
|
||||
` projections.users4_humans.nick_name,` +
|
||||
` projections.users4_humans.display_name,` +
|
||||
` projections.users4_humans.preferred_language,` +
|
||||
` projections.users4_humans.gender,` +
|
||||
` projections.users4_humans.avatar_key,` +
|
||||
` projections.users4_notifications.user_id,` +
|
||||
` projections.users4_notifications.last_email,` +
|
||||
` projections.users4_notifications.verified_email,` +
|
||||
` projections.users4_notifications.last_phone,` +
|
||||
` projections.users4_notifications.verified_phone,` +
|
||||
` projections.users4_notifications.password_set,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM projections.users4` +
|
||||
` LEFT JOIN projections.users4_humans ON projections.users4.id = projections.users4_humans.user_id` +
|
||||
` LEFT JOIN projections.users4_notifications ON projections.users4.id = projections.users4_notifications.user_id` +
|
||||
` LEFT JOIN` +
|
||||
` (SELECT login_names.user_id, ARRAY_AGG(login_names.login_name) AS loginnames` +
|
||||
` FROM projections.login_names AS login_names` +
|
||||
` WHERE login_names.instance_id = $1` +
|
||||
` GROUP BY login_names.user_id) AS login_names` +
|
||||
` ON login_names.user_id = projections.users3.id` +
|
||||
` ON login_names.user_id = projections.users4.id` +
|
||||
` LEFT JOIN` +
|
||||
` (SELECT preferred_login_name.user_id, preferred_login_name.login_name FROM projections.login_names AS preferred_login_name WHERE preferred_login_name.instance_id = $2 AND preferred_login_name.is_primary = $3) AS preferred_login_name` +
|
||||
` ON preferred_login_name.user_id = projections.users3.id`
|
||||
` ON preferred_login_name.user_id = projections.users4.id`
|
||||
notifyUserCols = []string{
|
||||
"id",
|
||||
"creation_date",
|
||||
@@ -232,44 +235,45 @@ var (
|
||||
"last_phone",
|
||||
"verified_phone",
|
||||
"password_set",
|
||||
"count",
|
||||
}
|
||||
usersQuery = `SELECT projections.users3.id,` +
|
||||
` projections.users3.creation_date,` +
|
||||
` projections.users3.change_date,` +
|
||||
` projections.users3.resource_owner,` +
|
||||
` projections.users3.sequence,` +
|
||||
` projections.users3.state,` +
|
||||
` projections.users3.type,` +
|
||||
` projections.users3.username,` +
|
||||
usersQuery = `SELECT projections.users4.id,` +
|
||||
` projections.users4.creation_date,` +
|
||||
` projections.users4.change_date,` +
|
||||
` projections.users4.resource_owner,` +
|
||||
` projections.users4.sequence,` +
|
||||
` projections.users4.state,` +
|
||||
` projections.users4.type,` +
|
||||
` projections.users4.username,` +
|
||||
` login_names.loginnames,` +
|
||||
` preferred_login_name.login_name,` +
|
||||
` projections.users3_humans.user_id,` +
|
||||
` projections.users3_humans.first_name,` +
|
||||
` projections.users3_humans.last_name,` +
|
||||
` projections.users3_humans.nick_name,` +
|
||||
` projections.users3_humans.display_name,` +
|
||||
` projections.users3_humans.preferred_language,` +
|
||||
` projections.users3_humans.gender,` +
|
||||
` projections.users3_humans.avatar_key,` +
|
||||
` projections.users3_humans.email,` +
|
||||
` projections.users3_humans.is_email_verified,` +
|
||||
` projections.users3_humans.phone,` +
|
||||
` projections.users3_humans.is_phone_verified,` +
|
||||
` projections.users3_machines.user_id,` +
|
||||
` projections.users3_machines.name,` +
|
||||
` projections.users3_machines.description,` +
|
||||
` projections.users4_humans.user_id,` +
|
||||
` projections.users4_humans.first_name,` +
|
||||
` projections.users4_humans.last_name,` +
|
||||
` projections.users4_humans.nick_name,` +
|
||||
` projections.users4_humans.display_name,` +
|
||||
` projections.users4_humans.preferred_language,` +
|
||||
` projections.users4_humans.gender,` +
|
||||
` projections.users4_humans.avatar_key,` +
|
||||
` projections.users4_humans.email,` +
|
||||
` projections.users4_humans.is_email_verified,` +
|
||||
` projections.users4_humans.phone,` +
|
||||
` projections.users4_humans.is_phone_verified,` +
|
||||
` projections.users4_machines.user_id,` +
|
||||
` projections.users4_machines.name,` +
|
||||
` projections.users4_machines.description,` +
|
||||
` COUNT(*) OVER ()` +
|
||||
` FROM projections.users3` +
|
||||
` LEFT JOIN projections.users3_humans ON projections.users3.id = projections.users3_humans.user_id` +
|
||||
` LEFT JOIN projections.users3_machines ON projections.users3.id = projections.users3_machines.user_id` +
|
||||
` FROM projections.users4` +
|
||||
` LEFT JOIN projections.users4_humans ON projections.users4.id = projections.users4_humans.user_id` +
|
||||
` LEFT JOIN projections.users4_machines ON projections.users4.id = projections.users4_machines.user_id` +
|
||||
` LEFT JOIN` +
|
||||
` (SELECT login_names.user_id, ARRAY_AGG(login_names.login_name) AS loginnames` +
|
||||
` FROM projections.login_names AS login_names` +
|
||||
` GROUP BY login_names.user_id) AS login_names` +
|
||||
` ON login_names.user_id = projections.users3.id` +
|
||||
` ON login_names.user_id = projections.users4.id` +
|
||||
` LEFT JOIN` +
|
||||
` (SELECT preferred_login_name.user_id, preferred_login_name.login_name FROM projections.login_names AS preferred_login_name WHERE preferred_login_name.is_primary = $1) AS preferred_login_name` +
|
||||
` ON preferred_login_name.user_id = projections.users3.id`
|
||||
` ON preferred_login_name.user_id = projections.users4.id`
|
||||
usersCols = []string{
|
||||
"id",
|
||||
"creation_date",
|
||||
@@ -370,6 +374,7 @@ func Test_UserPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
1,
|
||||
},
|
||||
),
|
||||
},
|
||||
@@ -436,6 +441,7 @@ func Test_UserPrepares(t *testing.T) {
|
||||
"id",
|
||||
"name",
|
||||
"description",
|
||||
1,
|
||||
},
|
||||
),
|
||||
},
|
||||
@@ -879,6 +885,7 @@ func Test_UserPrepares(t *testing.T) {
|
||||
"lastPhone",
|
||||
"verifiedPhone",
|
||||
true,
|
||||
1,
|
||||
},
|
||||
),
|
||||
},
|
||||
@@ -942,6 +949,7 @@ func Test_UserPrepares(t *testing.T) {
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
1,
|
||||
},
|
||||
),
|
||||
err: func(err error) (error, bool) {
|
||||
|
@@ -29,7 +29,9 @@ func NewLoginPolicyAddedEvent(
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
allowDomainDiscovery,
|
||||
disableLoginWithEmail,
|
||||
disableLoginWithPhone bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@@ -51,6 +53,8 @@ func NewLoginPolicyAddedEvent(
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery,
|
||||
disableLoginWithEmail,
|
||||
disableLoginWithPhone,
|
||||
passwordlessType,
|
||||
defaultRedirectURI,
|
||||
passwordCheckLifetime,
|
||||
|
@@ -30,7 +30,9 @@ func NewLoginPolicyAddedEvent(
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
allowDomainDiscovery,
|
||||
disableLoginWithEmail,
|
||||
disableLoginWithPhone bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@@ -52,13 +54,16 @@ func NewLoginPolicyAddedEvent(
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery,
|
||||
disableLoginWithEmail,
|
||||
disableLoginWithPhone,
|
||||
passwordlessType,
|
||||
defaultRedirectURI,
|
||||
passwordCheckLifetime,
|
||||
externalLoginCheckLifetime,
|
||||
mfaInitSkipLifetime,
|
||||
secondFactorCheckLifetime,
|
||||
multiFactorCheckLifetime),
|
||||
multiFactorCheckLifetime,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -27,6 +27,8 @@ type LoginPolicyAddedEvent struct {
|
||||
HidePasswordReset bool `json:"hidePasswordReset,omitempty"`
|
||||
IgnoreUnknownUsernames bool `json:"ignoreUnknownUsernames,omitempty"`
|
||||
AllowDomainDiscovery bool `json:"allowDomainDiscovery,omitempty"`
|
||||
DisableLoginWithEmail bool `json:"disableLoginWithEmail,omitempty"`
|
||||
DisableLoginWithPhone bool `json:"disableLoginWithPhone,omitempty"`
|
||||
PasswordlessType domain.PasswordlessType `json:"passwordlessType,omitempty"`
|
||||
DefaultRedirectURI string `json:"defaultRedirectURI,omitempty"`
|
||||
PasswordCheckLifetime time.Duration `json:"passwordCheckLifetime,omitempty"`
|
||||
@@ -52,7 +54,9 @@ func NewLoginPolicyAddedEvent(
|
||||
forceMFA,
|
||||
hidePasswordReset,
|
||||
ignoreUnknownUsernames,
|
||||
allowDomainDiscovery bool,
|
||||
allowDomainDiscovery,
|
||||
disableLoginWithEmail,
|
||||
disableLoginWithPhone bool,
|
||||
passwordlessType domain.PasswordlessType,
|
||||
defaultRedirectURI string,
|
||||
passwordCheckLifetime,
|
||||
@@ -77,6 +81,8 @@ func NewLoginPolicyAddedEvent(
|
||||
MFAInitSkipLifetime: mfaInitSkipLifetime,
|
||||
SecondFactorCheckLifetime: secondFactorCheckLifetime,
|
||||
MultiFactorCheckLifetime: multiFactorCheckLifetime,
|
||||
DisableLoginWithEmail: disableLoginWithEmail,
|
||||
DisableLoginWithPhone: disableLoginWithPhone,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +109,8 @@ type LoginPolicyChangedEvent struct {
|
||||
HidePasswordReset *bool `json:"hidePasswordReset,omitempty"`
|
||||
IgnoreUnknownUsernames *bool `json:"ignoreUnknownUsernames,omitempty"`
|
||||
AllowDomainDiscovery *bool `json:"allowDomainDiscovery,omitempty"`
|
||||
DisableLoginWithEmail *bool `json:"disableLoginWithEmail,omitempty"`
|
||||
DisableLoginWithPhone *bool `json:"disableLoginWithPhone,omitempty"`
|
||||
PasswordlessType *domain.PasswordlessType `json:"passwordlessType,omitempty"`
|
||||
DefaultRedirectURI *string `json:"defaultRedirectURI,omitempty"`
|
||||
PasswordCheckLifetime *time.Duration `json:"passwordCheckLifetime,omitempty"`
|
||||
@@ -222,6 +230,18 @@ func ChangeDefaultRedirectURI(defaultRedirectURI string) func(*LoginPolicyChange
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeDisableLoginWithEmail(disableLoginWithEmail bool) func(*LoginPolicyChangedEvent) {
|
||||
return func(e *LoginPolicyChangedEvent) {
|
||||
e.DisableLoginWithEmail = &disableLoginWithEmail
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeDisableLoginWithPhone(DisableLoginWithPhone bool) func(*LoginPolicyChangedEvent) {
|
||||
return func(e *LoginPolicyChangedEvent) {
|
||||
e.DisableLoginWithPhone = &DisableLoginWithPhone
|
||||
}
|
||||
}
|
||||
|
||||
func LoginPolicyChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||
e := &LoginPolicyChangedEvent{
|
||||
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||
|
Reference in New Issue
Block a user