fix(notify): notify user in projection (#3889)

* start implement notify user in projection

* fix(stmt): add copy to multi stmt

* use projections for notify users

* feat: notifications from projections

* feat: notifications from projections

* cleanup

* pre-release

* fix tests

* fix types

* fix command

* fix queryNotifyUser

* fix: build version

* fix: HumanPasswordlessInitCodeSent

Co-authored-by: adlerhurst <silvan.reusser@gmail.com>
This commit is contained in:
Livio Spring
2022-07-06 14:09:49 +02:00
committed by GitHub
parent d15a15c809
commit a1d404291d
46 changed files with 2018 additions and 1839 deletions

View File

@@ -20,18 +20,18 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names.login_name" +
", projections.users_humans.email" +
", projections.users_humans.first_name" +
", projections.users_humans.last_name" +
", projections.users_humans.display_name" +
", projections.users_machines.name" +
", projections.users_humans.avatar_key" +
", projections.users2_humans.email" +
", projections.users2_humans.first_name" +
", projections.users2_humans.last_name" +
", projections.users2_humans.display_name" +
", projections.users2_machines.name" +
", projections.users2_humans.avatar_key" +
", COUNT(*) OVER () " +
"FROM projections.instance_members as members " +
"LEFT JOIN projections.users_humans " +
"ON members.user_id = projections.users_humans.user_id " +
"LEFT JOIN projections.users_machines " +
"ON members.user_id = projections.users_machines.user_id " +
"LEFT JOIN projections.users2_humans " +
"ON members.user_id = projections.users2_humans.user_id " +
"LEFT JOIN projections.users2_machines " +
"ON members.user_id = projections.users2_machines.user_id " +
"LEFT JOIN projections.login_names " +
"ON members.user_id = projections.login_names.user_id " +
"WHERE projections.login_names.is_primary = $1")

View File

@@ -20,18 +20,18 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names.login_name" +
", projections.users_humans.email" +
", projections.users_humans.first_name" +
", projections.users_humans.last_name" +
", projections.users_humans.display_name" +
", projections.users_machines.name" +
", projections.users_humans.avatar_key" +
", projections.users2_humans.email" +
", projections.users2_humans.first_name" +
", projections.users2_humans.last_name" +
", projections.users2_humans.display_name" +
", projections.users2_machines.name" +
", projections.users2_humans.avatar_key" +
", COUNT(*) OVER () " +
"FROM projections.org_members as members " +
"LEFT JOIN projections.users_humans " +
"ON members.user_id = projections.users_humans.user_id " +
"LEFT JOIN projections.users_machines " +
"ON members.user_id = projections.users_machines.user_id " +
"LEFT JOIN projections.users2_humans " +
"ON members.user_id = projections.users2_humans.user_id " +
"LEFT JOIN projections.users2_machines " +
"ON members.user_id = projections.users2_machines.user_id " +
"LEFT JOIN projections.login_names " +
"ON members.user_id = projections.login_names.user_id " +
"WHERE projections.login_names.is_primary = $1")

View File

@@ -20,18 +20,18 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names.login_name" +
", projections.users_humans.email" +
", projections.users_humans.first_name" +
", projections.users_humans.last_name" +
", projections.users_humans.display_name" +
", projections.users_machines.name" +
", projections.users_humans.avatar_key" +
", projections.users2_humans.email" +
", projections.users2_humans.first_name" +
", projections.users2_humans.last_name" +
", projections.users2_humans.display_name" +
", projections.users2_machines.name" +
", projections.users2_humans.avatar_key" +
", COUNT(*) OVER () " +
"FROM projections.project_grant_members as members " +
"LEFT JOIN projections.users_humans " +
"ON members.user_id = projections.users_humans.user_id " +
"LEFT JOIN projections.users_machines " +
"ON members.user_id = projections.users_machines.user_id " +
"LEFT JOIN projections.users2_humans " +
"ON members.user_id = projections.users2_humans.user_id " +
"LEFT JOIN projections.users2_machines " +
"ON members.user_id = projections.users2_machines.user_id " +
"LEFT JOIN projections.login_names " +
"ON members.user_id = projections.login_names.user_id " +
"LEFT JOIN projections.project_grants " +

View File

@@ -20,18 +20,18 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names.login_name" +
", projections.users_humans.email" +
", projections.users_humans.first_name" +
", projections.users_humans.last_name" +
", projections.users_humans.display_name" +
", projections.users_machines.name" +
", projections.users_humans.avatar_key" +
", projections.users2_humans.email" +
", projections.users2_humans.first_name" +
", projections.users2_humans.last_name" +
", projections.users2_humans.display_name" +
", projections.users2_machines.name" +
", projections.users2_humans.avatar_key" +
", COUNT(*) OVER () " +
"FROM projections.project_members as members " +
"LEFT JOIN projections.users_humans " +
"ON members.user_id = projections.users_humans.user_id " +
"LEFT JOIN projections.users_machines " +
"ON members.user_id = projections.users_machines.user_id " +
"LEFT JOIN projections.users2_humans " +
"ON members.user_id = projections.users2_humans.user_id " +
"LEFT JOIN projections.users2_machines " +
"ON members.user_id = projections.users2_machines.user_id " +
"LEFT JOIN projections.login_names " +
"ON members.user_id = projections.login_names.user_id " +
"WHERE projections.login_names.is_primary = $1")

View File

@@ -358,6 +358,32 @@ func (p *labelPolicyProjection) reduceActivated(event eventstore.Event) (*handle
handler.NewCol(LabelPolicyDarkLogoURLCol, nil),
handler.NewCol(LabelPolicyDarkIconURLCol, nil),
},
[]handler.Column{
handler.NewCol(LabelPolicyChangeDateCol, nil),
handler.NewCol(LabelPolicySequenceCol, nil),
handler.NewCol(LabelPolicyStateCol, nil),
handler.NewCol(LabelPolicyCreationDateCol, nil),
handler.NewCol(LabelPolicyResourceOwnerCol, nil),
handler.NewCol(LabelPolicyInstanceIDCol, nil),
handler.NewCol(LabelPolicyIDCol, nil),
handler.NewCol(LabelPolicyIsDefaultCol, nil),
handler.NewCol(LabelPolicyHideLoginNameSuffixCol, nil),
handler.NewCol(LabelPolicyFontURLCol, nil),
handler.NewCol(LabelPolicyWatermarkDisabledCol, nil),
handler.NewCol(LabelPolicyShouldErrorPopupCol, nil),
handler.NewCol(LabelPolicyLightPrimaryColorCol, nil),
handler.NewCol(LabelPolicyLightWarnColorCol, nil),
handler.NewCol(LabelPolicyLightBackgroundColorCol, nil),
handler.NewCol(LabelPolicyLightFontColorCol, nil),
handler.NewCol(LabelPolicyLightLogoURLCol, nil),
handler.NewCol(LabelPolicyLightIconURLCol, nil),
handler.NewCol(LabelPolicyDarkPrimaryColorCol, nil),
handler.NewCol(LabelPolicyDarkWarnColorCol, nil),
handler.NewCol(LabelPolicyDarkBackgroundColorCol, nil),
handler.NewCol(LabelPolicyDarkFontColorCol, nil),
handler.NewCol(LabelPolicyDarkLogoURLCol, nil),
handler.NewCol(LabelPolicyDarkIconURLCol, nil),
},
[]handler.Condition{
handler.NewCond(LabelPolicyIDCol, event.Aggregate().ID),
handler.NewCond(LabelPolicyStateCol, domain.LabelPolicyStatePreview),

View File

@@ -18,6 +18,7 @@ const (
)
var (
projectionConfig crdb.StatementHandlerConfig
OrgProjection *orgProjection
ActionProjection *actionProjection
FlowProjection *flowProjection
@@ -58,10 +59,11 @@ var (
OIDCSettingsProjection *oidcSettingsProjection
DebugNotificationProviderProjection *debugNotificationProviderProjection
KeyProjection *keyProjection
NotificationsProjection interface{}
)
func Start(ctx context.Context, sqlClient *sql.DB, es *eventstore.Eventstore, config Config, keyEncryptionAlgorithm crypto.EncryptionAlgorithm) error {
projectionConfig := crdb.StatementHandlerConfig{
projectionConfig = crdb.StatementHandlerConfig{
ProjectionHandlerConfig: handler.ProjectionHandlerConfig{
HandlerConfig: handler.HandlerConfig{
Eventstore: es,
@@ -120,6 +122,11 @@ func Start(ctx context.Context, sqlClient *sql.DB, es *eventstore.Eventstore, co
return nil
}
func ApplyCustomConfig(customConfig CustomConfig) crdb.StatementHandlerConfig {
return applyCustomConfig(projectionConfig, customConfig)
}
func applyCustomConfig(config crdb.StatementHandlerConfig, customConfig CustomConfig) crdb.StatementHandlerConfig {
if customConfig.BulkLimit != nil {
config.BulkLimit = *customConfig.BulkLimit

View File

@@ -17,9 +17,10 @@ type userProjection struct {
}
const (
UserTable = "projections.users"
UserTable = "projections.users2"
UserHumanTable = UserTable + "_" + UserHumanSuffix
UserMachineTable = UserTable + "_" + UserMachineSuffix
UserNotifyTable = UserTable + "_" + UserNotifySuffix
UserIDCol = "id"
UserCreationDateCol = "creation_date"
@@ -58,6 +59,16 @@ const (
MachineUserInstanceIDCol = "instance_id"
MachineNameCol = "name"
MachineDescriptionCol = "description"
// notify
UserNotifySuffix = "notifications"
NotifyUserIDCol = "user_id"
NotifyInstanceIDCol = "instance_id"
NotifyLastEmailCol = "last_email"
NotifyVerifiedEmailCol = "verified_email"
NotifyLastPhoneCol = "last_phone"
NotifyVerifiedPhoneCol = "verified_phone"
NotifyPasswordSetCol = "password_set"
)
func newUserProjection(ctx context.Context, config crdb.StatementHandlerConfig) *userProjection {
@@ -110,6 +121,19 @@ func newUserProjection(ctx context.Context, config crdb.StatementHandlerConfig)
UserMachineSuffix,
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_machine_ref_user")),
),
crdb.NewSuffixedTable([]*crdb.Column{
crdb.NewColumn(NotifyUserIDCol, crdb.ColumnTypeText),
crdb.NewColumn(NotifyInstanceIDCol, crdb.ColumnTypeText),
crdb.NewColumn(NotifyLastEmailCol, crdb.ColumnTypeText, crdb.Nullable()),
crdb.NewColumn(NotifyVerifiedEmailCol, crdb.ColumnTypeText, crdb.Nullable()),
crdb.NewColumn(NotifyLastPhoneCol, crdb.ColumnTypeText, crdb.Nullable()),
crdb.NewColumn(NotifyVerifiedPhoneCol, crdb.ColumnTypeText, crdb.Nullable()),
crdb.NewColumn(NotifyPasswordSetCol, crdb.ColumnTypeBool, crdb.Default(false)),
},
crdb.NewPrimaryKey(NotifyUserIDCol, NotifyInstanceIDCol),
UserNotifySuffix,
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys("fk_notify_ref_user")),
),
)
p.StatementHandler = crdb.NewStatementHandler(ctx, config)
return p
@@ -240,6 +264,10 @@ func (p *userProjection) reducers() []handler.AggregateReducer {
Event: user.MachineChangedEventType,
Reduce: p.reduceMachineChanged,
},
{
Event: user.HumanPasswordChangedType,
Reduce: p.reduceHumanPasswordChanged,
},
},
},
}
@@ -280,6 +308,16 @@ func (p *userProjection) reduceHumanAdded(event eventstore.Event) (*handler.Stat
},
crdb.WithTableSuffix(UserHumanSuffix),
),
crdb.AddCreateStatement(
[]handler.Column{
handler.NewCol(NotifyUserIDCol, e.Aggregate().ID),
handler.NewCol(NotifyInstanceIDCol, e.Aggregate().InstanceID),
handler.NewCol(NotifyLastEmailCol, e.EmailAddress),
handler.NewCol(NotifyLastPhoneCol, &sql.NullString{String: e.PhoneNumber, Valid: e.PhoneNumber != ""}),
handler.NewCol(NotifyPasswordSetCol, e.Secret != nil),
},
crdb.WithTableSuffix(UserNotifySuffix),
),
), nil
}
@@ -318,6 +356,16 @@ func (p *userProjection) reduceHumanRegistered(event eventstore.Event) (*handler
},
crdb.WithTableSuffix(UserHumanSuffix),
),
crdb.AddCreateStatement(
[]handler.Column{
handler.NewCol(NotifyUserIDCol, e.Aggregate().ID),
handler.NewCol(NotifyInstanceIDCol, e.Aggregate().InstanceID),
handler.NewCol(NotifyLastEmailCol, e.EmailAddress),
handler.NewCol(NotifyLastPhoneCol, &sql.NullString{String: e.PhoneNumber, Valid: e.PhoneNumber != ""}),
handler.NewCol(NotifyPasswordSetCol, e.Secret != nil),
},
crdb.WithTableSuffix(UserNotifySuffix),
),
), nil
}
@@ -552,6 +600,16 @@ func (p *userProjection) reduceHumanPhoneChanged(event eventstore.Event) (*handl
},
crdb.WithTableSuffix(UserHumanSuffix),
),
crdb.AddUpdateStatement(
[]handler.Column{
handler.NewCol(NotifyLastPhoneCol, &sql.NullString{String: e.PhoneNumber, Valid: e.PhoneNumber != ""}),
},
[]handler.Condition{
handler.NewCond(NotifyUserIDCol, e.Aggregate().ID),
handler.NewCond(NotifyInstanceIDCol, e.Aggregate().InstanceID),
},
crdb.WithTableSuffix(UserNotifySuffix),
),
), nil
}
@@ -584,6 +642,17 @@ func (p *userProjection) reduceHumanPhoneRemoved(event eventstore.Event) (*handl
},
crdb.WithTableSuffix(UserHumanSuffix),
),
crdb.AddUpdateStatement(
[]handler.Column{
handler.NewCol(NotifyLastPhoneCol, nil),
handler.NewCol(NotifyVerifiedPhoneCol, nil),
},
[]handler.Condition{
handler.NewCond(NotifyUserIDCol, e.Aggregate().ID),
handler.NewCond(NotifyInstanceIDCol, e.Aggregate().InstanceID),
},
crdb.WithTableSuffix(UserNotifySuffix),
),
), nil
}
@@ -615,6 +684,23 @@ func (p *userProjection) reduceHumanPhoneVerified(event eventstore.Event) (*hand
},
crdb.WithTableSuffix(UserHumanSuffix),
),
crdb.AddCopyStatement(
[]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),
},
[]handler.Condition{
handler.NewCond(NotifyUserIDCol, e.Aggregate().ID),
handler.NewCond(NotifyInstanceIDCol, e.Aggregate().InstanceID),
},
crdb.WithTableSuffix(UserNotifySuffix),
),
), nil
}
@@ -647,6 +733,16 @@ func (p *userProjection) reduceHumanEmailChanged(event eventstore.Event) (*handl
},
crdb.WithTableSuffix(UserHumanSuffix),
),
crdb.AddUpdateStatement(
[]handler.Column{
handler.NewCol(NotifyLastEmailCol, &sql.NullString{String: e.EmailAddress, Valid: e.EmailAddress != ""}),
},
[]handler.Condition{
handler.NewCond(NotifyUserIDCol, e.Aggregate().ID),
handler.NewCond(NotifyInstanceIDCol, e.Aggregate().InstanceID),
},
crdb.WithTableSuffix(UserNotifySuffix),
),
), nil
}
@@ -678,6 +774,23 @@ func (p *userProjection) reduceHumanEmailVerified(event eventstore.Event) (*hand
},
crdb.WithTableSuffix(UserHumanSuffix),
),
crdb.AddCopyStatement(
[]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),
},
[]handler.Condition{
handler.NewCond(NotifyUserIDCol, e.Aggregate().ID),
handler.NewCond(NotifyInstanceIDCol, e.Aggregate().InstanceID),
},
crdb.WithTableSuffix(UserNotifySuffix),
),
), nil
}
@@ -743,6 +856,25 @@ func (p *userProjection) reduceHumanAvatarRemoved(event eventstore.Event) (*hand
), nil
}
func (p *userProjection) reduceHumanPasswordChanged(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*user.HumanPasswordChangedEvent)
if !ok {
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-jqXUY", "reduce.wrong.event.type %s", user.HumanPasswordChangedType)
}
return crdb.NewUpdateStatement(
e,
[]handler.Column{
handler.NewCol(NotifyPasswordSetCol, true),
},
[]handler.Condition{
handler.NewCond(NotifyUserIDCol, e.Aggregate().ID),
handler.NewCond(NotifyInstanceIDCol, e.Aggregate().InstanceID),
},
crdb.WithTableSuffix(UserNotifySuffix),
), nil
}
func (p *userProjection) reduceMachineAdded(event eventstore.Event) (*handler.Statement, error) {
e, ok := event.(*user.MachineAddedEvent)
if !ok {

View File

@@ -50,7 +50,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users (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.users2 (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.users_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.users2_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",
@@ -78,6 +78,16 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
},
},
{
expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
"email@zitadel.com",
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
false,
},
},
},
},
},
@@ -110,7 +120,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users (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.users2 (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{},
@@ -124,7 +134,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users_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.users2_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",
@@ -138,6 +148,16 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
},
},
{
expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
"email@zitadel.com",
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
false,
},
},
},
},
},
@@ -165,7 +185,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users (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.users2 (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{},
@@ -179,7 +199,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users_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.users2_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",
@@ -193,6 +213,16 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullString{},
},
},
{
expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
"email@zitadel.com",
&sql.NullString{String: "", Valid: false},
false,
},
},
},
},
},
@@ -225,7 +255,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users (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.users2 (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{},
@@ -239,7 +269,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users_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.users2_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",
@@ -253,6 +283,16 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
},
},
{
expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
"email@zitadel.com",
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
false,
},
},
},
},
},
@@ -285,7 +325,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users (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.users2 (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{},
@@ -299,7 +339,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users_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.users2_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",
@@ -313,6 +353,16 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
},
},
{
expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
"email@zitadel.com",
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
false,
},
},
},
},
},
@@ -340,7 +390,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users (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.users2 (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{},
@@ -354,7 +404,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users_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.users2_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",
@@ -368,6 +418,16 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullString{},
},
},
{
expectedStmt: "INSERT INTO projections.users2_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
"email@zitadel.com",
&sql.NullString{String: "", Valid: false},
false,
},
},
},
},
},
@@ -390,7 +450,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateInitial,
"agg-id",
@@ -419,7 +479,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateInitial,
"agg-id",
@@ -448,7 +508,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateActive,
"agg-id",
@@ -477,7 +537,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2 SET (state) = ($1) WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateActive,
"agg-id",
@@ -506,7 +566,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users2 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateLocked,
@@ -537,7 +597,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users2 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateActive,
@@ -568,7 +628,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users2 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateInactive,
@@ -599,7 +659,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users2 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateActive,
@@ -630,7 +690,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.users WHERE (id = $1) AND (instance_id = $2)",
expectedStmt: "DELETE FROM projections.users2 WHERE (id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -660,7 +720,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users2 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
"username",
@@ -698,7 +758,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -707,7 +767,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_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.users2_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",
@@ -748,7 +808,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -757,7 +817,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_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.users2_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",
@@ -793,7 +853,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -802,7 +862,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
"+41 00 000 00 00",
false,
@@ -810,6 +870,14 @@ func TestUserProjection_reduces(t *testing.T) {
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.users2_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",
"instance-id",
},
},
},
},
},
@@ -834,7 +902,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -843,7 +911,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
"+41 00 000 00 00",
false,
@@ -851,6 +919,14 @@ func TestUserProjection_reduces(t *testing.T) {
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.users2_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",
"instance-id",
},
},
},
},
},
@@ -873,7 +949,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -882,7 +958,16 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
"agg-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.users2_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
@@ -912,7 +997,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -921,7 +1006,16 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
"agg-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.users2_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
@@ -951,7 +1045,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -960,13 +1054,20 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (is_phone_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2_humans SET (is_phone_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
"instance-id",
},
},
{
expectedStmt: "UPSERT INTO projections.users2_notifications (user_id, instance_id, verified_phone) SELECT user_id, instance_id, last_phone FROM projections.users2_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
},
},
},
},
},
@@ -989,7 +1090,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -998,13 +1099,20 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (is_phone_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2_humans SET (is_phone_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
"instance-id",
},
},
{
expectedStmt: "UPSERT INTO projections.users2_notifications (user_id, instance_id, verified_phone) SELECT user_id, instance_id, last_phone FROM projections.users2_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
},
},
},
},
},
@@ -1029,7 +1137,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1038,7 +1146,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
"email@zitadel.com",
false,
@@ -1046,6 +1154,14 @@ func TestUserProjection_reduces(t *testing.T) {
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.users2_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",
"instance-id",
},
},
},
},
},
@@ -1070,7 +1186,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1079,7 +1195,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
"email@zitadel.com",
false,
@@ -1087,6 +1203,14 @@ func TestUserProjection_reduces(t *testing.T) {
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.users2_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",
"instance-id",
},
},
},
},
},
@@ -1109,7 +1233,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1118,13 +1242,20 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (is_email_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2_humans SET (is_email_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
"instance-id",
},
},
{
expectedStmt: "UPSERT INTO projections.users2_notifications (user_id, instance_id, verified_email) SELECT user_id, instance_id, last_email FROM projections.users2_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
},
},
},
},
},
@@ -1147,7 +1278,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1156,13 +1287,20 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (is_email_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2_humans SET (is_email_verified) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
"instance-id",
},
},
{
expectedStmt: "UPSERT INTO projections.users2_notifications (user_id, instance_id, verified_email) SELECT user_id, instance_id, last_email FROM projections.users2_notifications AS copy_table WHERE copy_table.user_id = $1 AND copy_table.instance_id = $2",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
},
},
},
},
},
@@ -1187,7 +1325,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1196,7 +1334,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (avatar_key) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2_humans SET (avatar_key) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"users/agg-id/avatar",
"agg-id",
@@ -1225,7 +1363,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1234,7 +1372,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_humans SET (avatar_key) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2_humans SET (avatar_key) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
nil,
"agg-id",
@@ -1266,7 +1404,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users (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.users2 (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{},
@@ -1280,7 +1418,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
expectedStmt: "INSERT INTO projections.users2_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -1314,7 +1452,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users (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.users2 (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{},
@@ -1328,7 +1466,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
expectedStmt: "INSERT INTO projections.users2_machines (user_id, instance_id, name, description) VALUES ($1, $2, $3, $4)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@@ -1361,7 +1499,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1370,7 +1508,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_machines SET (name, description) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2_machines SET (name, description) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
"machine-name",
"description",
@@ -1402,7 +1540,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1411,7 +1549,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_machines SET (name) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2_machines SET (name) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"machine-name",
"agg-id",
@@ -1442,7 +1580,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users2 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@@ -1451,7 +1589,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users_machines SET (description) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users2_machines SET (description) = ($1) WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"description",
"agg-id",

View File

@@ -11,9 +11,7 @@ import (
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/query/projection"
)
@@ -92,6 +90,31 @@ type Machine struct {
Description string
}
type NotifyUser struct {
ID string
CreationDate time.Time
ChangeDate time.Time
ResourceOwner string
Sequence uint64
State domain.UserState
Type domain.UserType
Username string
LoginNames []string
PreferredLoginName string
FirstName string
LastName string
NickName string
DisplayName string
AvatarKey string
PreferredLanguage language.Tag
Gender domain.Gender
LastEmail string
VerifiedEmail string
LastPhone string
VerifiedPhone string
PasswordSet bool
}
type UserSearchQueries struct {
SearchRequest
Queries []SearchQuery
@@ -237,6 +260,38 @@ var (
}
)
var (
notifyTable = table{
name: projection.UserNotifyTable,
}
NotifyUserIDCol = Column{
name: projection.NotifyUserIDCol,
table: notifyTable,
}
NotifyEmailCol = Column{
name: projection.NotifyLastEmailCol,
table: notifyTable,
isOrderByLower: true,
}
NotifyVerifiedEmailCol = Column{
name: projection.NotifyVerifiedEmailCol,
table: notifyTable,
isOrderByLower: true,
}
NotifyPhoneCol = Column{
name: projection.NotifyLastPhoneCol,
table: notifyTable,
}
NotifyVerifiedPhoneCol = Column{
name: projection.NotifyVerifiedPhoneCol,
table: notifyTable,
}
NotifyPasswordSetCol = Column{
name: projection.NotifyPasswordSetCol,
table: notifyTable,
}
)
func (q *Queries) GetUserByID(ctx context.Context, shouldTriggered bool, userID string, queries ...SearchQuery) (*User, error) {
if shouldTriggered {
projection.UserProjection.TriggerBulk(ctx)
@@ -327,6 +382,28 @@ 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) {
if shouldTriggered {
projection.UserProjection.TriggerBulk(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{
UserIDCol.identifier(): userID,
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).
@@ -748,6 +825,143 @@ func preparePhoneQuery() (sq.SelectBuilder, func(*sql.Row) (*Phone, error)) {
}
}
func prepareNotifyUserQuery(instanceID string) (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) {
loginNamesQuery, loginNamesArgs, err := sq.Select(
userLoginNamesUserIDCol.identifier(),
"ARRAY_AGG("+userLoginNamesNameCol.identifier()+") as "+userLoginNamesListCol.name).
From(userLoginNamesTable.identifier()).
GroupBy(userLoginNamesUserIDCol.identifier()).
Where(sq.Eq{
userLoginNamesInstanceIDCol.identifier(): instanceID,
}).ToSql()
if err != nil {
return sq.SelectBuilder{}, nil
}
preferredLoginNameQuery, preferredLoginNameArgs, err := sq.Select(
userPreferredLoginNameUserIDCol.identifier(),
userPreferredLoginNameCol.identifier()).
From(userPreferredLoginNameTable.identifier()).
Where(sq.Eq{
userPreferredLoginNameIsPrimaryCol.identifier(): true,
userPreferredLoginNameInstanceIDCol.identifier(): instanceID,
}).ToSql()
if err != nil {
return sq.SelectBuilder{}, nil
}
return sq.Select(
UserIDCol.identifier(),
UserCreationDateCol.identifier(),
UserChangeDateCol.identifier(),
UserResourceOwnerCol.identifier(),
UserSequenceCol.identifier(),
UserStateCol.identifier(),
UserTypeCol.identifier(),
UserUsernameCol.identifier(),
userLoginNamesListCol.identifier(),
userPreferredLoginNameCol.identifier(),
HumanUserIDCol.identifier(),
HumanFirstNameCol.identifier(),
HumanLastNameCol.identifier(),
HumanNickNameCol.identifier(),
HumanDisplayNameCol.identifier(),
HumanPreferredLanguageCol.identifier(),
HumanGenderCol.identifier(),
HumanAvatarURLCol.identifier(),
NotifyUserIDCol.identifier(),
NotifyEmailCol.identifier(),
NotifyVerifiedEmailCol.identifier(),
NotifyPhoneCol.identifier(),
NotifyVerifiedPhoneCol.identifier(),
NotifyPasswordSetCol.identifier(),
).
From(userTable.identifier()).
LeftJoin(join(HumanUserIDCol, UserIDCol)).
LeftJoin(join(NotifyUserIDCol, UserIDCol)).
LeftJoin("("+loginNamesQuery+") as "+userLoginNamesTable.alias+" on "+userLoginNamesUserIDCol.identifier()+" = "+UserIDCol.identifier(), loginNamesArgs...).
LeftJoin("("+preferredLoginNameQuery+") as "+userPreferredLoginNameTable.alias+" on "+userPreferredLoginNameUserIDCol.identifier()+" = "+UserIDCol.identifier(), preferredLoginNameArgs...).
PlaceholderFormat(sq.Dollar),
func(row *sql.Row) (*NotifyUser, error) {
u := new(NotifyUser)
loginNames := pq.StringArray{}
preferredLoginName := sql.NullString{}
humanID := sql.NullString{}
firstName := sql.NullString{}
lastName := sql.NullString{}
nickName := sql.NullString{}
displayName := sql.NullString{}
preferredLanguage := sql.NullString{}
gender := sql.NullInt32{}
avatarKey := sql.NullString{}
notifyUserID := sql.NullString{}
notifyEmail := sql.NullString{}
notifyVerifiedEmail := sql.NullString{}
notifyPhone := sql.NullString{}
notifyVerifiedPhone := sql.NullString{}
notifyPasswordSet := sql.NullBool{}
err := row.Scan(
&u.ID,
&u.CreationDate,
&u.ChangeDate,
&u.ResourceOwner,
&u.Sequence,
&u.State,
&u.Type,
&u.Username,
&loginNames,
&preferredLoginName,
&humanID,
&firstName,
&lastName,
&nickName,
&displayName,
&preferredLanguage,
&gender,
&avatarKey,
&notifyUserID,
&notifyEmail,
&notifyVerifiedEmail,
&notifyPhone,
&notifyVerifiedPhone,
&notifyPasswordSet,
)
if err != nil {
if errs.Is(err, sql.ErrNoRows) {
return nil, errors.ThrowNotFound(err, "QUERY-Dgqd2", "Errors.User.NotFound")
}
return nil, errors.ThrowInternal(err, "QUERY-Dbwsg", "Errors.Internal")
}
if !notifyUserID.Valid {
return nil, errors.ThrowPreconditionFailed(nil, "QUERY-Sfw3f", "Errors.User.NotFound")
}
u.LoginNames = loginNames
if preferredLoginName.Valid {
u.PreferredLoginName = preferredLoginName.String
}
if humanID.Valid {
u.FirstName = firstName.String
u.LastName = lastName.String
u.NickName = nickName.String
u.DisplayName = displayName.String
u.AvatarKey = avatarKey.String
u.PreferredLanguage = language.Make(preferredLanguage.String)
u.Gender = domain.Gender(gender.Int32)
}
u.LastEmail = notifyEmail.String
u.VerifiedEmail = notifyVerifiedEmail.String
u.LastPhone = notifyPhone.String
u.VerifiedPhone = notifyVerifiedPhone.String
u.PasswordSet = notifyPasswordSet.Bool
return u, nil
}
}
func prepareUserUniqueQuery() (sq.SelectBuilder, func(*sql.Row) (bool, error)) {
return sq.Select(
UserIDCol.identifier(),

View File

@@ -24,14 +24,14 @@ var (
", projections.user_grants.roles" +
", projections.user_grants.state" +
", projections.user_grants.user_id" +
", projections.users.username" +
", projections.users.type" +
", projections.users.resource_owner" +
", projections.users_humans.first_name" +
", projections.users_humans.last_name" +
", projections.users_humans.email" +
", projections.users_humans.display_name" +
", projections.users_humans.avatar_key" +
", projections.users2.username" +
", projections.users2.type" +
", projections.users2.resource_owner" +
", projections.users2_humans.first_name" +
", projections.users2_humans.last_name" +
", projections.users2_humans.email" +
", projections.users2_humans.display_name" +
", projections.users2_humans.avatar_key" +
", projections.login_names.login_name" +
", projections.user_grants.resource_owner" +
", projections.orgs.name" +
@@ -39,8 +39,8 @@ var (
", projections.user_grants.project_id" +
", projections.projects.name" +
" FROM projections.user_grants" +
" LEFT JOIN projections.users ON projections.user_grants.user_id = projections.users.id" +
" LEFT JOIN projections.users_humans ON projections.user_grants.user_id = projections.users_humans.user_id" +
" LEFT JOIN projections.users2 ON projections.user_grants.user_id = projections.users2.id" +
" LEFT JOIN projections.users2_humans ON projections.user_grants.user_id = projections.users2_humans.user_id" +
" LEFT JOIN projections.orgs ON projections.user_grants.resource_owner = projections.orgs.id" +
" LEFT JOIN projections.projects ON projections.user_grants.project_id = projections.projects.id" +
" LEFT JOIN projections.login_names ON projections.user_grants.user_id = projections.login_names.user_id" +
@@ -78,14 +78,14 @@ var (
", projections.user_grants.roles" +
", projections.user_grants.state" +
", projections.user_grants.user_id" +
", projections.users.username" +
", projections.users.type" +
", projections.users.resource_owner" +
", projections.users_humans.first_name" +
", projections.users_humans.last_name" +
", projections.users_humans.email" +
", projections.users_humans.display_name" +
", projections.users_humans.avatar_key" +
", projections.users2.username" +
", projections.users2.type" +
", projections.users2.resource_owner" +
", projections.users2_humans.first_name" +
", projections.users2_humans.last_name" +
", projections.users2_humans.email" +
", projections.users2_humans.display_name" +
", projections.users2_humans.avatar_key" +
", projections.login_names.login_name" +
", projections.user_grants.resource_owner" +
", projections.orgs.name" +
@@ -94,8 +94,8 @@ var (
", projections.projects.name" +
", COUNT(*) OVER ()" +
" FROM projections.user_grants" +
" LEFT JOIN projections.users ON projections.user_grants.user_id = projections.users.id" +
" LEFT JOIN projections.users_humans ON projections.user_grants.user_id = projections.users_humans.user_id" +
" LEFT JOIN projections.users2 ON projections.user_grants.user_id = projections.users2.id" +
" LEFT JOIN projections.users2_humans ON projections.user_grants.user_id = projections.users2_humans.user_id" +
" LEFT JOIN projections.orgs ON projections.user_grants.resource_owner = projections.orgs.id" +
" LEFT JOIN projections.projects ON projections.user_grants.project_id = projections.projects.id" +
" LEFT JOIN projections.login_names ON projections.user_grants.user_id = projections.login_names.user_id" +

View File

@@ -17,43 +17,43 @@ import (
)
var (
userQuery = `SELECT projections.users.id,` +
` projections.users.creation_date,` +
` projections.users.change_date,` +
` projections.users.resource_owner,` +
` projections.users.sequence,` +
` projections.users.state,` +
` projections.users.type,` +
` projections.users.username,` +
userQuery = `SELECT projections.users2.id,` +
` projections.users2.creation_date,` +
` projections.users2.change_date,` +
` projections.users2.resource_owner,` +
` projections.users2.sequence,` +
` projections.users2.state,` +
` projections.users2.type,` +
` projections.users2.username,` +
` login_names.loginnames,` +
` preferred_login_name.login_name,` +
` projections.users_humans.user_id,` +
` projections.users_humans.first_name,` +
` projections.users_humans.last_name,` +
` projections.users_humans.nick_name,` +
` projections.users_humans.display_name,` +
` projections.users_humans.preferred_language,` +
` projections.users_humans.gender,` +
` projections.users_humans.avatar_key,` +
` projections.users_humans.email,` +
` projections.users_humans.is_email_verified,` +
` projections.users_humans.phone,` +
` projections.users_humans.is_phone_verified,` +
` projections.users_machines.user_id,` +
` projections.users_machines.name,` +
` projections.users_machines.description` +
` FROM projections.users` +
` LEFT JOIN projections.users_humans ON projections.users.id = projections.users_humans.user_id` +
` LEFT JOIN projections.users_machines ON projections.users.id = projections.users_machines.user_id` +
` projections.users2_humans.user_id,` +
` projections.users2_humans.first_name,` +
` projections.users2_humans.last_name,` +
` projections.users2_humans.nick_name,` +
` projections.users2_humans.display_name,` +
` projections.users2_humans.preferred_language,` +
` projections.users2_humans.gender,` +
` projections.users2_humans.avatar_key,` +
` projections.users2_humans.email,` +
` projections.users2_humans.is_email_verified,` +
` projections.users2_humans.phone,` +
` projections.users2_humans.is_phone_verified,` +
` projections.users2_machines.user_id,` +
` projections.users2_machines.name,` +
` projections.users2_machines.description` +
` FROM projections.users2` +
` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id` +
` LEFT JOIN projections.users2_machines ON projections.users2.id = projections.users2_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` +
` WHERE login_names.instance_id = $1` +
` GROUP BY login_names.user_id) as login_names` +
` on login_names.user_id = projections.users.id` +
` on login_names.user_id = projections.users2.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.users.id`
` on preferred_login_name.user_id = projections.users2.id`
userCols = []string{
"id",
"creation_date",
@@ -83,21 +83,21 @@ var (
"name",
"description",
}
profileQuery = `SELECT projections.users.id,` +
` projections.users.creation_date,` +
` projections.users.change_date,` +
` projections.users.resource_owner,` +
` projections.users.sequence,` +
` projections.users_humans.user_id,` +
` projections.users_humans.first_name,` +
` projections.users_humans.last_name,` +
` projections.users_humans.nick_name,` +
` projections.users_humans.display_name,` +
` projections.users_humans.preferred_language,` +
` projections.users_humans.gender,` +
` projections.users_humans.avatar_key` +
` FROM projections.users` +
` LEFT JOIN projections.users_humans ON projections.users.id = projections.users_humans.user_id`
profileQuery = `SELECT projections.users2.id,` +
` projections.users2.creation_date,` +
` projections.users2.change_date,` +
` projections.users2.resource_owner,` +
` projections.users2.sequence,` +
` projections.users2_humans.user_id,` +
` projections.users2_humans.first_name,` +
` projections.users2_humans.last_name,` +
` projections.users2_humans.nick_name,` +
` projections.users2_humans.display_name,` +
` projections.users2_humans.preferred_language,` +
` projections.users2_humans.gender,` +
` projections.users2_humans.avatar_key` +
` FROM projections.users2` +
` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id`
profileCols = []string{
"id",
"creation_date",
@@ -113,16 +113,16 @@ var (
"gender",
"avatar_key",
}
emailQuery = `SELECT projections.users.id,` +
` projections.users.creation_date,` +
` projections.users.change_date,` +
` projections.users.resource_owner,` +
` projections.users.sequence,` +
` projections.users_humans.user_id,` +
` projections.users_humans.email,` +
` projections.users_humans.is_email_verified` +
` FROM projections.users` +
` LEFT JOIN projections.users_humans ON projections.users.id = projections.users_humans.user_id`
emailQuery = `SELECT projections.users2.id,` +
` projections.users2.creation_date,` +
` projections.users2.change_date,` +
` projections.users2.resource_owner,` +
` projections.users2.sequence,` +
` projections.users2_humans.user_id,` +
` projections.users2_humans.email,` +
` projections.users2_humans.is_email_verified` +
` FROM projections.users2` +
` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id`
emailCols = []string{
"id",
"creation_date",
@@ -133,16 +133,16 @@ var (
"email",
"is_email_verified",
}
phoneQuery = `SELECT projections.users.id,` +
` projections.users.creation_date,` +
` projections.users.change_date,` +
` projections.users.resource_owner,` +
` projections.users.sequence,` +
` projections.users_humans.user_id,` +
` projections.users_humans.phone,` +
` projections.users_humans.is_phone_verified` +
` FROM projections.users` +
` LEFT JOIN projections.users_humans ON projections.users.id = projections.users_humans.user_id`
phoneQuery = `SELECT projections.users2.id,` +
` projections.users2.creation_date,` +
` projections.users2.change_date,` +
` projections.users2.resource_owner,` +
` projections.users2.sequence,` +
` projections.users2_humans.user_id,` +
` projections.users2_humans.phone,` +
` projections.users2_humans.is_phone_verified` +
` FROM projections.users2` +
` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id`
phoneCols = []string{
"id",
"creation_date",
@@ -153,15 +153,14 @@ var (
"phone",
"is_phone_verified",
}
userUniqueQuery = `SELECT projections.users.id,` +
` projections.users.state,` +
` projections.users.username,` +
` projections.users_humans.user_id,` +
` projections.users_humans.email,` +
` projections.users_humans.is_email_verified` +
` FROM projections.users` +
` LEFT JOIN projections.users_humans ON projections.users.id = projections.users_humans.user_id`
userUniqueQuery = `SELECT projections.users2.id,` +
` projections.users2.state,` +
` projections.users2.username,` +
` projections.users2_humans.user_id,` +
` projections.users2_humans.email,` +
` projections.users2_humans.is_email_verified` +
` FROM projections.users2` +
` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id`
userUniqueCols = []string{
"id",
"state",
@@ -170,43 +169,107 @@ var (
"email",
"is_email_verified",
}
usersQuery = `SELECT projections.users.id,` +
` projections.users.creation_date,` +
` projections.users.change_date,` +
` projections.users.resource_owner,` +
` projections.users.sequence,` +
` projections.users.state,` +
` projections.users.type,` +
` projections.users.username,` +
notifyUserQuery = `SELECT projections.users2.id,` +
` projections.users2.creation_date,` +
` projections.users2.change_date,` +
` projections.users2.resource_owner,` +
` projections.users2.sequence,` +
` projections.users2.state,` +
` projections.users2.type,` +
` projections.users2.username,` +
` login_names.loginnames,` +
` preferred_login_name.login_name,` +
` projections.users_humans.user_id,` +
` projections.users_humans.first_name,` +
` projections.users_humans.last_name,` +
` projections.users_humans.nick_name,` +
` projections.users_humans.display_name,` +
` projections.users_humans.preferred_language,` +
` projections.users_humans.gender,` +
` projections.users_humans.avatar_key,` +
` projections.users_humans.email,` +
` projections.users_humans.is_email_verified,` +
` projections.users_humans.phone,` +
` projections.users_humans.is_phone_verified,` +
` projections.users_machines.user_id,` +
` projections.users_machines.name,` +
` projections.users_machines.description,` +
` projections.users2_humans.user_id,` +
` projections.users2_humans.first_name,` +
` projections.users2_humans.last_name,` +
` projections.users2_humans.nick_name,` +
` projections.users2_humans.display_name,` +
` projections.users2_humans.preferred_language,` +
` projections.users2_humans.gender,` +
` projections.users2_humans.avatar_key,` +
` projections.users2_notifications.user_id,` +
` projections.users2_notifications.last_email,` +
` projections.users2_notifications.verified_email,` +
` projections.users2_notifications.last_phone,` +
` projections.users2_notifications.verified_phone,` +
` projections.users2_notifications.password_set` +
` FROM projections.users2` +
` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id` +
` LEFT JOIN projections.users2_notifications ON projections.users2.id = projections.users2_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.users2.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.users2.id`
notifyUserCols = []string{
"id",
"creation_date",
"change_date",
"resource_owner",
"sequence",
"state",
"type",
"username",
"loginnames",
"login_name",
//human
"user_id",
"first_name",
"last_name",
"nick_name",
"display_name",
"preferred_language",
"gender",
"avatar_key",
//machine
"user_id",
"last_email",
"verified_email",
"last_phone",
"verified_phone",
"password_set",
}
usersQuery = `SELECT projections.users2.id,` +
` projections.users2.creation_date,` +
` projections.users2.change_date,` +
` projections.users2.resource_owner,` +
` projections.users2.sequence,` +
` projections.users2.state,` +
` projections.users2.type,` +
` projections.users2.username,` +
` login_names.loginnames,` +
` preferred_login_name.login_name,` +
` projections.users2_humans.user_id,` +
` projections.users2_humans.first_name,` +
` projections.users2_humans.last_name,` +
` projections.users2_humans.nick_name,` +
` projections.users2_humans.display_name,` +
` projections.users2_humans.preferred_language,` +
` projections.users2_humans.gender,` +
` projections.users2_humans.avatar_key,` +
` projections.users2_humans.email,` +
` projections.users2_humans.is_email_verified,` +
` projections.users2_humans.phone,` +
` projections.users2_humans.is_phone_verified,` +
` projections.users2_machines.user_id,` +
` projections.users2_machines.name,` +
` projections.users2_machines.description,` +
` COUNT(*) OVER ()` +
` FROM projections.users` +
` LEFT JOIN projections.users_humans ON projections.users.id = projections.users_humans.user_id` +
` LEFT JOIN projections.users_machines ON projections.users.id = projections.users_machines.user_id` +
` FROM projections.users2` +
` LEFT JOIN projections.users2_humans ON projections.users2.id = projections.users2_humans.user_id` +
` LEFT JOIN projections.users2_machines ON projections.users2.id = projections.users2_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.users.id` +
` on login_names.user_id = projections.users2.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.users.id`
` on preferred_login_name.user_id = projections.users2.id`
usersCols = []string{
"id",
"creation_date",
@@ -760,6 +823,155 @@ func Test_UserPrepares(t *testing.T) {
},
object: nil,
},
{
name: "prepareNotifyUserQuery no result",
prepare: func() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) {
return prepareNotifyUserQuery("instanceID")
},
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(notifyUserQuery),
nil,
nil,
),
err: func(err error) (error, bool) {
if !errs.IsNotFound(err) {
return fmt.Errorf("err should be zitadel.NotFoundError got: %w", err), false
}
return nil, true
},
},
object: (*NotifyUser)(nil),
},
{
name: "prepareNotifyUserQuery notify found",
prepare: func() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) {
return prepareNotifyUserQuery("instanceID")
},
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(notifyUserQuery),
notifyUserCols,
[]driver.Value{
"id",
testNow,
testNow,
"resource_owner",
uint64(20211108),
domain.UserStateActive,
domain.UserTypeHuman,
"username",
pq.StringArray{"login_name1", "login_name2"},
"login_name1",
//human
"id",
"first_name",
"last_name",
"nick_name",
"display_name",
"de",
domain.GenderUnspecified,
"avatar_key",
//notify
"id",
"lastEmail",
"verifiedEmail",
"lastPhone",
"verifiedPhone",
true,
},
),
},
object: &NotifyUser{
ID: "id",
CreationDate: testNow,
ChangeDate: testNow,
ResourceOwner: "resource_owner",
Sequence: 20211108,
State: domain.UserStateActive,
Type: domain.UserTypeHuman,
Username: "username",
LoginNames: []string{"login_name1", "login_name2"},
PreferredLoginName: "login_name1",
FirstName: "first_name",
LastName: "last_name",
NickName: "nick_name",
DisplayName: "display_name",
AvatarKey: "avatar_key",
PreferredLanguage: language.German,
Gender: domain.GenderUnspecified,
LastEmail: "lastEmail",
VerifiedEmail: "verifiedEmail",
LastPhone: "lastPhone",
VerifiedPhone: "verifiedPhone",
PasswordSet: true,
},
},
{
name: "prepareNotifyUserQuery not notify found (error)",
prepare: func() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) {
return prepareNotifyUserQuery("instanceID")
},
want: want{
sqlExpectations: mockQuery(
regexp.QuoteMeta(notifyUserQuery),
notifyUserCols,
[]driver.Value{
"id",
testNow,
testNow,
"resource_owner",
uint64(20211108),
domain.UserStateActive,
domain.UserTypeHuman,
"username",
pq.StringArray{"login_name1", "login_name2"},
"login_name1",
//human
"id",
"first_name",
"last_name",
"nick_name",
"display_name",
"de",
domain.GenderUnspecified,
"avatar_key",
nil,
nil,
nil,
nil,
nil,
nil,
},
),
err: func(err error) (error, bool) {
if !errs.IsPreconditionFailed(err) {
return fmt.Errorf("err should be zitadel.PredconditionError got: %w", err), false
}
return nil, true
},
},
object: (*NotifyUser)(nil),
},
{
name: "prepareNotifyUserQuery sql err",
prepare: func() (sq.SelectBuilder, func(*sql.Row) (*NotifyUser, error)) {
return prepareNotifyUserQuery("instanceID")
},
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(notifyUserQuery),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
if !errors.Is(err, sql.ErrConnDone) {
return fmt.Errorf("err should be sql.ErrConnDone got: %w", err), false
}
return nil, true
},
},
object: nil,
},
{
name: "prepareUsersQuery no result",
prepare: prepareUsersQuery,