feat: add user v2 pw change required information on query (#7603)

* fix: add resource owner as query for user v2 ListUsers and clean up deprecated attribute

* fix: add resource owner as query for user v2 ListUsers and clean up deprecated attribute

* fix: add resource owner as query for user v2 ListUsers and clean up deprecated attribute

* fix: review changes

* fix: review changes

* fix: review changes

* fix: review changes

* fix: add password change required to user v2 get and list

* fix: update unit tests for query side with new column and projection

* fix: change projection in setup steps

* fix: change projection in setup steps

* fix: remove setup step 25

* fix: add password_change_required into ListUsers response

* fix: correct SetUserPassword parameters

* fix: rollback to change setup instead of projection directly

* fix: rollback to change setup instead of projection directly

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Stefan Benz 2024-03-28 07:21:21 +01:00 committed by GitHub
parent d26391a642
commit 217703395e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 723 additions and 459 deletions

View File

@ -13,15 +13,15 @@ var (
addLowerFieldsToVerifiedEmail string
)
type AddLowerFieldsToVerifiedEmail struct {
type User11AddLowerFieldsToVerifiedEmail struct {
dbClient *database.DB
}
func (mig *AddLowerFieldsToVerifiedEmail) Execute(ctx context.Context, _ eventstore.Event) error {
func (mig *User11AddLowerFieldsToVerifiedEmail) Execute(ctx context.Context, _ eventstore.Event) error {
_, err := mig.dbClient.ExecContext(ctx, addLowerFieldsToVerifiedEmail)
return err
}
func (mig *AddLowerFieldsToVerifiedEmail) String() string {
return "25_add_lower_fields_to_verified_email"
func (mig *User11AddLowerFieldsToVerifiedEmail) String() string {
return "25_user11_add_lower_fields_to_verified_email"
}

View File

@ -1,2 +1,2 @@
ALTER TABLE IF EXISTS projections.users10_notifications ADD COLUMN IF NOT EXISTS verified_email_lower TEXT GENERATED ALWAYS AS (lower(verified_email)) STORED;
CREATE INDEX IF NOT EXISTS users10_notifications_email_search ON projections.users10_notifications (instance_id, verified_email_lower);
ALTER TABLE IF EXISTS projections.users11_notifications ADD COLUMN IF NOT EXISTS verified_email_lower TEXT GENERATED ALWAYS AS (lower(verified_email)) STORED;
CREATE INDEX IF NOT EXISTS users11_notifications_email_search ON projections.users11_notifications (instance_id, verified_email_lower);

View File

@ -82,28 +82,28 @@ func MustNewConfig(v *viper.Viper) *Config {
}
type Steps struct {
s1ProjectionTable *ProjectionTable
s2AssetsTable *AssetTable
FirstInstance *FirstInstance
s5LastFailed *LastFailed
s6OwnerRemoveColumns *OwnerRemoveColumns
s7LogstoreTables *LogstoreTables
s8AuthTokens *AuthTokenIndexes
CorrectCreationDate *CorrectCreationDate
s12AddOTPColumns *AddOTPColumns
s13FixQuotaProjection *FixQuotaConstraints
s14NewEventsTable *NewEventsTable
s15CurrentStates *CurrentProjectionState
s16UniqueConstraintsLower *UniqueConstraintToLower
s17AddOffsetToUniqueConstraints *AddOffsetToCurrentStates
s18AddLowerFieldsToLoginNames *AddLowerFieldsToLoginNames
s19AddCurrentStatesIndex *AddCurrentSequencesIndex
s20AddByUserSessionIndex *AddByUserIndexToSession
s21AddBlockFieldToLimits *AddBlockFieldToLimits
s22ActiveInstancesIndex *ActiveInstanceEvents
s23CorrectGlobalUniqueConstraints *CorrectGlobalUniqueConstraints
s24AddActorToAuthTokens *AddActorToAuthTokens
s25AddLowerFieldsToVerifiedEmail *AddLowerFieldsToVerifiedEmail
s1ProjectionTable *ProjectionTable
s2AssetsTable *AssetTable
FirstInstance *FirstInstance
s5LastFailed *LastFailed
s6OwnerRemoveColumns *OwnerRemoveColumns
s7LogstoreTables *LogstoreTables
s8AuthTokens *AuthTokenIndexes
CorrectCreationDate *CorrectCreationDate
s12AddOTPColumns *AddOTPColumns
s13FixQuotaProjection *FixQuotaConstraints
s14NewEventsTable *NewEventsTable
s15CurrentStates *CurrentProjectionState
s16UniqueConstraintsLower *UniqueConstraintToLower
s17AddOffsetToUniqueConstraints *AddOffsetToCurrentStates
s18AddLowerFieldsToLoginNames *AddLowerFieldsToLoginNames
s19AddCurrentStatesIndex *AddCurrentSequencesIndex
s20AddByUserSessionIndex *AddByUserIndexToSession
s21AddBlockFieldToLimits *AddBlockFieldToLimits
s22ActiveInstancesIndex *ActiveInstanceEvents
s23CorrectGlobalUniqueConstraints *CorrectGlobalUniqueConstraints
s24AddActorToAuthTokens *AddActorToAuthTokens
s25User11AddLowerFieldsToVerifiedEmail *User11AddLowerFieldsToVerifiedEmail
}
func MustNewSteps(v *viper.Viper) *Steps {

View File

@ -137,7 +137,7 @@ func Setup(config *Config, steps *Steps, masterKey string) {
steps.s22ActiveInstancesIndex = &ActiveInstanceEvents{dbClient: queryDBClient}
steps.s23CorrectGlobalUniqueConstraints = &CorrectGlobalUniqueConstraints{dbClient: esPusherDBClient}
steps.s24AddActorToAuthTokens = &AddActorToAuthTokens{dbClient: queryDBClient}
steps.s25AddLowerFieldsToVerifiedEmail = &AddLowerFieldsToVerifiedEmail{dbClient: esPusherDBClient}
steps.s25User11AddLowerFieldsToVerifiedEmail = &User11AddLowerFieldsToVerifiedEmail{dbClient: esPusherDBClient}
err = projection.Create(ctx, projectionDBClient, eventstoreClient, config.Projections, nil, nil, nil)
logging.OnError(err).Fatal("unable to start projections")
@ -187,7 +187,7 @@ func Setup(config *Config, steps *Steps, masterKey string) {
for _, step := range []migration.Migration{
steps.s18AddLowerFieldsToLoginNames,
steps.s21AddBlockFieldToLimits,
steps.s25AddLowerFieldsToVerifiedEmail,
steps.s25User11AddLowerFieldsToVerifiedEmail,
} {
mustExecuteMigration(ctx, eventstoreClient, step, "migration failed")
}

View File

@ -52,7 +52,7 @@ func TestMain(m *testing.M) {
UserId: User.GetUserId(),
VerificationCode: User.GetPhoneCode(),
})
Tester.SetUserPassword(CTX, User.GetUserId(), integration.UserPassword)
Tester.SetUserPassword(CTX, User.GetUserId(), integration.UserPassword, false)
Tester.RegisterUserPasskey(CTX, User.GetUserId())
DeactivatedUser = Tester.CreateHumanUser(CTX)
Tester.Client.UserV2.DeactivateUser(CTX, &user.DeactivateUserRequest{UserId: DeactivatedUser.GetUserId()})
@ -717,11 +717,11 @@ func TestServer_DeleteSession_token(t *testing.T) {
func TestServer_DeleteSession_own_session(t *testing.T) {
// create two users for the test and a session each to get tokens for authorization
user1 := Tester.CreateHumanUser(CTX)
Tester.SetUserPassword(CTX, user1.GetUserId(), integration.UserPassword)
Tester.SetUserPassword(CTX, user1.GetUserId(), integration.UserPassword, false)
_, token1, _, _ := Tester.CreatePasswordSession(t, CTX, user1.GetUserId(), integration.UserPassword)
user2 := Tester.CreateHumanUser(CTX)
Tester.SetUserPassword(CTX, user2.GetUserId(), integration.UserPassword)
Tester.SetUserPassword(CTX, user2.GetUserId(), integration.UserPassword, false)
_, token2, _, _ := Tester.CreatePasswordSession(t, CTX, user2.GetUserId(), integration.UserPassword)
// create a new session for the first user

View File

@ -101,6 +101,7 @@ func humanToPb(userQ *query.Human, assetPrefix, owner string) *user.HumanUser {
Phone: string(userQ.Phone),
IsVerified: userQ.IsPhoneVerified,
},
PasswordChangeRequired: userQ.PasswordChangeRequired,
}
}

View File

@ -8,9 +8,8 @@ import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/muhlemmer/gu"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/timestamppb"
@ -102,6 +101,52 @@ func TestServer_GetUserByID(t *testing.T) {
},
},
},
{
name: "user by ID, passwordChangeRequired, ok",
args: args{
IamCTX,
&user.GetUserByIDRequest{},
func(ctx context.Context, username string, request *user.GetUserByIDRequest) error {
resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username)
request.UserId = resp.GetUserId()
Tester.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true)
return nil
},
},
want: &user.GetUserByIDResponse{
User: &user.User{
State: user.UserState_USER_STATE_ACTIVE,
Username: "",
LoginNames: nil,
PreferredLoginName: "",
Type: &user.User_Human{
Human: &user.HumanUser{
Profile: &user.HumanProfile{
GivenName: "Mickey",
FamilyName: "Mouse",
NickName: gu.Ptr("Mickey"),
DisplayName: gu.Ptr("Mickey Mouse"),
PreferredLanguage: gu.Ptr("nl"),
Gender: user.Gender_GENDER_MALE.Enum(),
AvatarUrl: "",
},
Email: &user.HumanEmail{
IsVerified: true,
},
Phone: &user.HumanPhone{
Phone: "+41791234567",
IsVerified: true,
},
PasswordChangeRequired: true,
},
},
},
Details: &object.Details{
ChangeDate: timestamppb.Now(),
ResourceOwner: orgResp.OrganizationId,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -313,7 +358,11 @@ func TestServer_ListUsers(t *testing.T) {
args: args{
IamCTX,
1,
&user.ListUsersRequest{},
&user.ListUsersRequest{
Queries: []*user.SearchQuery{
OrganizationIdQuery(orgResp.OrganizationId),
},
},
func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) {
infos := make([]userAttr, len(usernames))
userIDs := make([]string, len(usernames))
@ -358,12 +407,72 @@ func TestServer_ListUsers(t *testing.T) {
},
},
},
{
name: "list user by id, passwordChangeRequired, ok",
args: args{
IamCTX,
1,
&user.ListUsersRequest{
Queries: []*user.SearchQuery{
OrganizationIdQuery(orgResp.OrganizationId),
},
},
func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) {
infos := make([]userAttr, len(usernames))
userIDs := make([]string, len(usernames))
for i, username := range usernames {
resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username)
userIDs[i] = resp.GetUserId()
Tester.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true)
infos[i] = userAttr{resp.GetUserId(), username}
}
request.Queries = append(request.Queries, InUserIDsQuery(userIDs))
return infos, nil
},
},
want: &user.ListUsersResponse{
Details: &object.ListDetails{
TotalResult: 1,
Timestamp: timestamppb.Now(),
},
SortingColumn: 0,
Result: []*user.User{
{
State: user.UserState_USER_STATE_ACTIVE,
Type: &user.User_Human{
Human: &user.HumanUser{
Profile: &user.HumanProfile{
GivenName: "Mickey",
FamilyName: "Mouse",
NickName: gu.Ptr("Mickey"),
DisplayName: gu.Ptr("Mickey Mouse"),
PreferredLanguage: gu.Ptr("nl"),
Gender: user.Gender_GENDER_MALE.Enum(),
},
Email: &user.HumanEmail{
IsVerified: true,
},
Phone: &user.HumanPhone{
Phone: "+41791234567",
IsVerified: true,
},
PasswordChangeRequired: true,
},
},
},
},
},
},
{
name: "list user by id multiple, ok",
args: args{
IamCTX,
3,
&user.ListUsersRequest{},
&user.ListUsersRequest{
Queries: []*user.SearchQuery{
OrganizationIdQuery(orgResp.OrganizationId),
},
},
func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) {
infos := make([]userAttr, len(usernames))
userIDs := make([]string, len(usernames))
@ -455,7 +564,11 @@ func TestServer_ListUsers(t *testing.T) {
args: args{
IamCTX,
1,
&user.ListUsersRequest{},
&user.ListUsersRequest{
Queries: []*user.SearchQuery{
OrganizationIdQuery(orgResp.OrganizationId),
},
},
func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) {
infos := make([]userAttr, len(usernames))
userIDs := make([]string, len(usernames))
@ -505,7 +618,11 @@ func TestServer_ListUsers(t *testing.T) {
args: args{
IamCTX,
1,
&user.ListUsersRequest{},
&user.ListUsersRequest{
Queries: []*user.SearchQuery{
OrganizationIdQuery(orgResp.OrganizationId),
},
},
func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) {
infos := make([]userAttr, len(usernames))
for i, username := range usernames {
@ -553,7 +670,11 @@ func TestServer_ListUsers(t *testing.T) {
args: args{
IamCTX,
3,
&user.ListUsersRequest{},
&user.ListUsersRequest{
Queries: []*user.SearchQuery{
OrganizationIdQuery(orgResp.OrganizationId),
},
},
func(ctx context.Context, usernames []string, request *user.ListUsersRequest) ([]userAttr, error) {
infos := make([]userAttr, len(usernames))
for i, username := range usernames {
@ -644,6 +765,7 @@ func TestServer_ListUsers(t *testing.T) {
IamCTX,
3,
&user.ListUsersRequest{Queries: []*user.SearchQuery{
OrganizationIdQuery(orgResp.OrganizationId),
InUserEmailsQuery([]string{"notfound"}),
},
},

View File

@ -47,7 +47,7 @@ func TestMain(m *testing.M) {
CTX, _ = Tester.WithAuthorization(ctx, integration.OrgOwner), errCtx
User = Tester.CreateHumanUser(CTX)
Tester.SetUserPassword(CTX, User.GetUserId(), integration.UserPassword)
Tester.SetUserPassword(CTX, User.GetUserId(), integration.UserPassword, false)
Tester.RegisterUserPasskey(CTX, User.GetUserId())
CTXLOGIN, _ = Tester.WithAuthorization(ctx, integration.Login), errCtx
return m.Run()
@ -321,7 +321,7 @@ func Test_ZITADEL_API_terminated_session_user_disabled(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
disabledUser := Tester.CreateHumanUser(CTX)
Tester.SetUserPassword(CTX, disabledUser.GetUserId(), integration.UserPassword)
Tester.SetUserPassword(CTX, disabledUser.GetUserId(), integration.UserPassword, false)
authRequestID := createAuthRequest(t, clientID, redirectURI, oidc.ScopeOpenID, oidc.ScopeOfflineAccess, zitadelAudienceScope)
sessionID, sessionToken, startTime, changeTime := Tester.CreatePasswordSession(t, CTXLOGIN, disabledUser.GetUserId(), integration.UserPassword)
linkResp, err := Tester.Client.OIDCv2.CreateCallback(CTXLOGIN, &oidc_pb.CreateCallbackRequest{

View File

@ -277,10 +277,13 @@ func (s *Tester) RegisterUserU2F(ctx context.Context, userID string) {
logging.OnError(err).Fatal("create user u2f")
}
func (s *Tester) SetUserPassword(ctx context.Context, userID, password string) {
func (s *Tester) SetUserPassword(ctx context.Context, userID, password string, changeRequired bool) {
_, err := s.Client.UserV2.SetPassword(ctx, &user.SetPasswordRequest{
UserId: userID,
NewPassword: &user.Password{Password: password},
UserId: userID,
NewPassword: &user.Password{
Password: password,
ChangeRequired: changeRequired,
},
})
logging.OnError(err).Fatal("set user password")
}

View File

@ -1,6 +1,6 @@
with usr as (
select u.id, u.creation_date, u.change_date, u.sequence, u.state, u.resource_owner, u.username, n.login_name as preferred_login_name
from projections.users10 u
from projections.users11 u
left join projections.login_names3 n on u.id = n.user_id and u.instance_id = n.instance_id
where u.id = $1
and u.instance_id = $2
@ -9,7 +9,7 @@ with usr as (
human as (
select $1 as user_id, row_to_json(r) as human from (
select first_name, last_name, nick_name, display_name, avatar_key, preferred_language, gender, email, is_email_verified, phone, is_phone_verified
from projections.users10_humans
from projections.users11_humans
where user_id = $1
and instance_id = $2
) r
@ -17,7 +17,7 @@ human as (
machine as (
select $1 as user_id, row_to_json(r) as machine from (
select name, description
from projections.users10_machines
from projections.users11_machines
where user_id = $1
and instance_id = $2
) r

View File

@ -21,21 +21,21 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names3.login_name" +
", projections.users10_humans.email" +
", projections.users10_humans.first_name" +
", projections.users10_humans.last_name" +
", projections.users10_humans.display_name" +
", projections.users10_machines.name" +
", projections.users10_humans.avatar_key" +
", projections.users10.type" +
", projections.users11_humans.email" +
", projections.users11_humans.first_name" +
", projections.users11_humans.last_name" +
", projections.users11_humans.display_name" +
", projections.users11_machines.name" +
", projections.users11_humans.avatar_key" +
", projections.users11.type" +
", COUNT(*) OVER () " +
"FROM projections.instance_members4 AS members " +
"LEFT JOIN projections.users10_humans " +
"ON members.user_id = projections.users10_humans.user_id AND members.instance_id = projections.users10_humans.instance_id " +
"LEFT JOIN projections.users10_machines " +
"ON members.user_id = projections.users10_machines.user_id AND members.instance_id = projections.users10_machines.instance_id " +
"LEFT JOIN projections.users10 " +
"ON members.user_id = projections.users10.id AND members.instance_id = projections.users10.instance_id " +
"LEFT JOIN projections.users11_humans " +
"ON members.user_id = projections.users11_humans.user_id AND members.instance_id = projections.users11_humans.instance_id " +
"LEFT JOIN projections.users11_machines " +
"ON members.user_id = projections.users11_machines.user_id AND members.instance_id = projections.users11_machines.instance_id " +
"LEFT JOIN projections.users11 " +
"ON members.user_id = projections.users11.id AND members.instance_id = projections.users11.instance_id " +
"LEFT JOIN projections.login_names3 " +
"ON members.user_id = projections.login_names3.user_id AND members.instance_id = projections.login_names3.instance_id " +
"AS OF SYSTEM TIME '-1 ms' " +

View File

@ -21,24 +21,24 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names3.login_name" +
", projections.users10_humans.email" +
", projections.users10_humans.first_name" +
", projections.users10_humans.last_name" +
", projections.users10_humans.display_name" +
", projections.users10_machines.name" +
", projections.users10_humans.avatar_key" +
", projections.users10.type" +
", projections.users11_humans.email" +
", projections.users11_humans.first_name" +
", projections.users11_humans.last_name" +
", projections.users11_humans.display_name" +
", projections.users11_machines.name" +
", projections.users11_humans.avatar_key" +
", projections.users11.type" +
", COUNT(*) OVER () " +
"FROM projections.org_members4 AS members " +
"LEFT JOIN projections.users10_humans " +
"ON members.user_id = projections.users10_humans.user_id " +
"AND members.instance_id = projections.users10_humans.instance_id " +
"LEFT JOIN projections.users10_machines " +
"ON members.user_id = projections.users10_machines.user_id " +
"AND members.instance_id = projections.users10_machines.instance_id " +
"LEFT JOIN projections.users10 " +
"ON members.user_id = projections.users10.id " +
"AND members.instance_id = projections.users10.instance_id " +
"LEFT JOIN projections.users11_humans " +
"ON members.user_id = projections.users11_humans.user_id " +
"AND members.instance_id = projections.users11_humans.instance_id " +
"LEFT JOIN projections.users11_machines " +
"ON members.user_id = projections.users11_machines.user_id " +
"AND members.instance_id = projections.users11_machines.instance_id " +
"LEFT JOIN projections.users11 " +
"ON members.user_id = projections.users11.id " +
"AND members.instance_id = projections.users11.instance_id " +
"LEFT JOIN projections.login_names3 " +
"ON members.user_id = projections.login_names3.user_id " +
"AND members.instance_id = projections.login_names3.instance_id " +

View File

@ -21,24 +21,24 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names3.login_name" +
", projections.users10_humans.email" +
", projections.users10_humans.first_name" +
", projections.users10_humans.last_name" +
", projections.users10_humans.display_name" +
", projections.users10_machines.name" +
", projections.users10_humans.avatar_key" +
", projections.users10.type" +
", projections.users11_humans.email" +
", projections.users11_humans.first_name" +
", projections.users11_humans.last_name" +
", projections.users11_humans.display_name" +
", projections.users11_machines.name" +
", projections.users11_humans.avatar_key" +
", projections.users11.type" +
", COUNT(*) OVER () " +
"FROM projections.project_grant_members4 AS members " +
"LEFT JOIN projections.users10_humans " +
"ON members.user_id = projections.users10_humans.user_id " +
"AND members.instance_id = projections.users10_humans.instance_id " +
"LEFT JOIN projections.users10_machines " +
"ON members.user_id = projections.users10_machines.user_id " +
"AND members.instance_id = projections.users10_machines.instance_id " +
"LEFT JOIN projections.users10 " +
"ON members.user_id = projections.users10.id " +
"AND members.instance_id = projections.users10.instance_id " +
"LEFT JOIN projections.users11_humans " +
"ON members.user_id = projections.users11_humans.user_id " +
"AND members.instance_id = projections.users11_humans.instance_id " +
"LEFT JOIN projections.users11_machines " +
"ON members.user_id = projections.users11_machines.user_id " +
"AND members.instance_id = projections.users11_machines.instance_id " +
"LEFT JOIN projections.users11 " +
"ON members.user_id = projections.users11.id " +
"AND members.instance_id = projections.users11.instance_id " +
"LEFT JOIN projections.login_names3 " +
"ON members.user_id = projections.login_names3.user_id " +
"AND members.instance_id = projections.login_names3.instance_id " +

View File

@ -21,24 +21,24 @@ var (
", members.user_id" +
", members.roles" +
", projections.login_names3.login_name" +
", projections.users10_humans.email" +
", projections.users10_humans.first_name" +
", projections.users10_humans.last_name" +
", projections.users10_humans.display_name" +
", projections.users10_machines.name" +
", projections.users10_humans.avatar_key" +
", projections.users10.type" +
", projections.users11_humans.email" +
", projections.users11_humans.first_name" +
", projections.users11_humans.last_name" +
", projections.users11_humans.display_name" +
", projections.users11_machines.name" +
", projections.users11_humans.avatar_key" +
", projections.users11.type" +
", COUNT(*) OVER () " +
"FROM projections.project_members4 AS members " +
"LEFT JOIN projections.users10_humans " +
"ON members.user_id = projections.users10_humans.user_id " +
"AND members.instance_id = projections.users10_humans.instance_id " +
"LEFT JOIN projections.users10_machines " +
"ON members.user_id = projections.users10_machines.user_id " +
"AND members.instance_id = projections.users10_machines.instance_id " +
"LEFT JOIN projections.users10 " +
"ON members.user_id = projections.users10.id " +
"AND members.instance_id = projections.users10.instance_id " +
"LEFT JOIN projections.users11_humans " +
"ON members.user_id = projections.users11_humans.user_id " +
"AND members.instance_id = projections.users11_humans.instance_id " +
"LEFT JOIN projections.users11_machines " +
"ON members.user_id = projections.users11_machines.user_id " +
"AND members.instance_id = projections.users11_machines.instance_id " +
"LEFT JOIN projections.users11 " +
"ON members.user_id = projections.users11.id " +
"AND members.instance_id = projections.users11.instance_id " +
"LEFT JOIN projections.login_names3 " +
"ON members.user_id = projections.login_names3.user_id " +
"AND members.instance_id = projections.login_names3.instance_id " +

View File

@ -15,7 +15,7 @@ import (
)
const (
UserTable = "projections.users10"
UserTable = "projections.users11"
UserHumanTable = UserTable + "_" + UserHumanSuffix
UserMachineTable = UserTable + "_" + UserMachineSuffix
UserNotifyTable = UserTable + "_" + UserNotifySuffix
@ -30,9 +30,10 @@ const (
UserUsernameCol = "username"
UserTypeCol = "type"
UserHumanSuffix = "humans"
HumanUserIDCol = "user_id"
HumanUserInstanceIDCol = "instance_id"
UserHumanSuffix = "humans"
HumanUserIDCol = "user_id"
HumanUserInstanceIDCol = "instance_id"
HumanPasswordChangeRequired = "password_change_required"
// profile
HumanFirstNameCol = "first_name"
@ -113,6 +114,7 @@ func (*userProjection) Init() *old_handler.Check {
handler.NewColumn(HumanIsEmailVerifiedCol, handler.ColumnTypeBool, handler.Default(false)),
handler.NewColumn(HumanPhoneCol, handler.ColumnTypeText, handler.Nullable()),
handler.NewColumn(HumanIsPhoneVerifiedCol, handler.ColumnTypeBool, handler.Nullable()),
handler.NewColumn(HumanPasswordChangeRequired, handler.ColumnTypeBool),
},
handler.NewPrimaryKey(HumanUserInstanceIDCol, HumanUserIDCol),
UserHumanSuffix,
@ -342,6 +344,7 @@ func (p *userProjection) reduceHumanAdded(event eventstore.Event) (*handler.Stat
handler.NewCol(HumanGenderCol, &sql.NullInt16{Int16: int16(e.Gender), Valid: e.Gender.Specified()}),
handler.NewCol(HumanEmailCol, e.EmailAddress),
handler.NewCol(HumanPhoneCol, &sql.NullString{String: string(e.PhoneNumber), Valid: e.PhoneNumber != ""}),
handler.NewCol(HumanPasswordChangeRequired, e.ChangeRequired),
},
handler.WithTableSuffix(UserHumanSuffix),
),
@ -390,6 +393,7 @@ func (p *userProjection) reduceHumanRegistered(event eventstore.Event) (*handler
handler.NewCol(HumanGenderCol, &sql.NullInt16{Int16: int16(e.Gender), Valid: e.Gender.Specified()}),
handler.NewCol(HumanEmailCol, e.EmailAddress),
handler.NewCol(HumanPhoneCol, &sql.NullString{String: string(e.PhoneNumber), Valid: e.PhoneNumber != ""}),
handler.NewCol(HumanPasswordChangeRequired, e.ChangeRequired),
},
handler.WithTableSuffix(UserHumanSuffix),
),
@ -904,17 +908,28 @@ func (p *userProjection) reduceHumanPasswordChanged(event eventstore.Event) (*ha
if !ok {
return nil, zerrors.ThrowInvalidArgumentf(nil, "HANDL-jqXUY", "reduce.wrong.event.type %s", user.HumanPasswordChangedType)
}
return handler.NewUpdateStatement(
return handler.NewMultiStatement(
e,
[]handler.Column{
handler.NewCol(NotifyPasswordSetCol, true),
},
[]handler.Condition{
handler.NewCond(NotifyUserIDCol, e.Aggregate().ID),
handler.NewCond(NotifyInstanceIDCol, e.Aggregate().InstanceID),
},
handler.WithTableSuffix(UserNotifySuffix),
handler.AddUpdateStatement(
[]handler.Column{
handler.NewCol(HumanPasswordChangeRequired, e.ChangeRequired),
},
[]handler.Condition{
handler.NewCond(HumanUserIDCol, e.Aggregate().ID),
handler.NewCond(HumanUserInstanceIDCol, e.Aggregate().InstanceID),
},
handler.WithTableSuffix(UserHumanSuffix),
),
handler.AddUpdateStatement(
[]handler.Column{
handler.NewCol(NotifyPasswordSetCol, true),
},
[]handler.Condition{
handler.NewCond(NotifyUserIDCol, e.Aggregate().ID),
handler.NewCond(NotifyInstanceIDCol, e.Aggregate().InstanceID),
},
handler.WithTableSuffix(UserNotifySuffix),
),
), nil
}

View File

@ -40,7 +40,8 @@ func TestUserProjection_reduces(t *testing.T) {
"preferredLanguage": "ch-DE",
"gender": 1,
"email": "email@zitadel.com",
"phone": "+41 00 000 00 00"
"phone": "+41 00 000 00 00",
"changeRequired": true
}`),
), user.HumanAddedEventMapper),
},
@ -51,7 +52,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users10 (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.users11 (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{},
@ -65,7 +66,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users10_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.users11_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone, password_change_required) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -77,10 +78,11 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullInt16{Int16: int16(domain.GenderFemale), Valid: true},
domain.EmailAddress("email@zitadel.com"),
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
true,
},
},
{
expectedStmt: "INSERT INTO projections.users10_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users11_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 +122,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users10 (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.users11 (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 +136,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users10_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.users11_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone, password_change_required) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -146,10 +148,11 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullInt16{Int16: int16(domain.GenderFemale), Valid: true},
domain.EmailAddress("email@zitadel.com"),
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
false,
},
},
{
expectedStmt: "INSERT INTO projections.users10_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users11_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -184,7 +187,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users10 (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.users11 (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{},
@ -198,7 +201,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users10_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.users11_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone, password_change_required) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -210,10 +213,11 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullInt16{},
domain.EmailAddress("email@zitadel.com"),
&sql.NullString{},
false,
},
},
{
expectedStmt: "INSERT INTO projections.users10_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users11_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -242,7 +246,8 @@ func TestUserProjection_reduces(t *testing.T) {
"preferredLanguage": "ch-DE",
"gender": 1,
"email": "email@zitadel.com",
"phone": "+41 00 000 00 00"
"phone": "+41 00 000 00 00",
"changeRequired": true
}`),
), user.HumanRegisteredEventMapper),
},
@ -253,7 +258,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users10 (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.users11 (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{},
@ -267,7 +272,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users10_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.users11_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone, password_change_required) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -279,10 +284,11 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullInt16{Int16: int16(domain.GenderFemale), Valid: true},
domain.EmailAddress("email@zitadel.com"),
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
true,
},
},
{
expectedStmt: "INSERT INTO projections.users10_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users11_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -322,7 +328,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users10 (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.users11 (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{},
@ -336,7 +342,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users10_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.users11_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone, password_change_required) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -348,10 +354,11 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullInt16{Int16: int16(domain.GenderFemale), Valid: true},
domain.EmailAddress("email@zitadel.com"),
&sql.NullString{String: "+41 00 000 00 00", Valid: true},
false,
},
},
{
expectedStmt: "INSERT INTO projections.users10_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users11_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -386,7 +393,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users10 (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.users11 (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{},
@ -400,7 +407,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users10_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.users11_humans (user_id, instance_id, first_name, last_name, nick_name, display_name, preferred_language, gender, email, phone, password_change_required) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -412,10 +419,11 @@ func TestUserProjection_reduces(t *testing.T) {
&sql.NullInt16{},
domain.EmailAddress("email@zitadel.com"),
&sql.NullString{},
false,
},
},
{
expectedStmt: "INSERT INTO projections.users10_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users11_notifications (user_id, instance_id, last_email, last_phone, password_set) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -445,7 +453,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateInitial,
"agg-id",
@ -473,7 +481,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateInitial,
"agg-id",
@ -501,7 +509,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateActive,
"agg-id",
@ -529,7 +537,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11 SET state = $1 WHERE (id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
domain.UserStateActive,
"agg-id",
@ -557,7 +565,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users11 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateLocked,
@ -587,7 +595,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users11 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateActive,
@ -617,7 +625,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users11 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateInactive,
@ -647,7 +655,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users11 SET (change_date, state, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
domain.UserStateActive,
@ -677,7 +685,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.users10 WHERE (id = $1) AND (instance_id = $2)",
expectedStmt: "DELETE FROM projections.users11 WHERE (id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -706,7 +714,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users11 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
"username",
@ -738,7 +746,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedStmt: "UPDATE projections.users11 SET (change_date, username, sequence) = ($1, $2, $3) WHERE (id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
"id@temporary.domain",
@ -775,7 +783,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -784,7 +792,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_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.users11_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",
@ -824,7 +832,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -833,7 +841,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_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.users11_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",
@ -868,7 +876,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -877,7 +885,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
domain.PhoneNumber("+41 00 000 00 00"),
false,
@ -886,7 +894,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_notifications SET last_phone = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_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",
@ -916,7 +924,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -925,7 +933,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
domain.PhoneNumber("+41 00 000 00 00"),
false,
@ -934,7 +942,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_notifications SET last_phone = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_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",
@ -962,7 +970,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -971,7 +979,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
@ -980,7 +988,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
@ -1009,7 +1017,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1018,7 +1026,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11_humans SET (phone, is_phone_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
@ -1027,7 +1035,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11_notifications SET (last_phone, verified_phone) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
nil,
nil,
@ -1056,7 +1064,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1065,7 +1073,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
@ -1073,7 +1081,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_notifications SET verified_phone = last_phone WHERE (user_id = $1) AND (instance_id = $2)",
expectedStmt: "UPDATE projections.users11_notifications SET verified_phone = last_phone WHERE (user_id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -1100,7 +1108,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1109,7 +1117,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_humans SET is_phone_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
@ -1117,7 +1125,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_notifications SET verified_phone = last_phone WHERE (user_id = $1) AND (instance_id = $2)",
expectedStmt: "UPDATE projections.users11_notifications SET verified_phone = last_phone WHERE (user_id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -1146,7 +1154,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1155,7 +1163,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
domain.EmailAddress("email@zitadel.com"),
false,
@ -1164,7 +1172,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_notifications SET last_email = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_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",
@ -1194,7 +1202,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1203,7 +1211,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11_humans SET (email, is_email_verified) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
domain.EmailAddress("email@zitadel.com"),
false,
@ -1212,7 +1220,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_notifications SET last_email = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_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",
@ -1240,7 +1248,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1249,7 +1257,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
@ -1257,7 +1265,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_notifications SET verified_email = last_email WHERE (user_id = $1) AND (instance_id = $2)",
expectedStmt: "UPDATE projections.users11_notifications SET verified_email = last_email WHERE (user_id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -1284,7 +1292,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1293,7 +1301,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_humans SET is_email_verified = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
@ -1301,7 +1309,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_notifications SET verified_email = last_email WHERE (user_id = $1) AND (instance_id = $2)",
expectedStmt: "UPDATE projections.users11_notifications SET verified_email = last_email WHERE (user_id = $1) AND (instance_id = $2)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -1330,7 +1338,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1339,7 +1347,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"users/agg-id/avatar",
"agg-id",
@ -1367,7 +1375,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1376,7 +1384,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_humans SET avatar_key = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
nil,
"agg-id",
@ -1387,6 +1395,82 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
},
{
name: "reduceHumanPasswordChanged",
args: args{
event: getEvent(
testEvent(
user.HumanPasswordChangedType,
user.AggregateType,
[]byte(`{
"changeRequired": true
}`),
), user.HumanPasswordChangedEventMapper),
},
reduce: (&userProjection{}).reduceHumanPasswordChanged,
want: wantReduce{
aggregateType: user.AggregateType,
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users11_humans SET password_change_required = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.users11_notifications SET password_set = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
"instance-id",
},
},
},
},
},
},
{
name: "reduceHumanPasswordChanged, false",
args: args{
event: getEvent(
testEvent(
user.HumanPasswordChangedType,
user.AggregateType,
[]byte(`{
"changeRequired": false
}`),
), user.HumanPasswordChangedEventMapper),
},
reduce: (&userProjection{}).reduceHumanPasswordChanged,
want: wantReduce{
aggregateType: user.AggregateType,
sequence: 15,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users11_humans SET password_change_required = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
false,
"agg-id",
"instance-id",
},
},
{
expectedStmt: "UPDATE projections.users11_notifications SET password_set = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
true,
"agg-id",
"instance-id",
},
},
},
},
},
},
{
name: "reduceMachineAddedEvent no description",
args: args{
@ -1407,7 +1491,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users10 (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.users11 (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{},
@ -1421,7 +1505,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users10_machines (user_id, instance_id, name, description, access_token_type) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users11_machines (user_id, instance_id, name, description, access_token_type) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -1455,7 +1539,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "INSERT INTO projections.users10 (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.users11 (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{},
@ -1469,7 +1553,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.users10_machines (user_id, instance_id, name, description, access_token_type) VALUES ($1, $2, $3, $4, $5)",
expectedStmt: "INSERT INTO projections.users11_machines (user_id, instance_id, name, description, access_token_type) VALUES ($1, $2, $3, $4, $5)",
expectedArgs: []interface{}{
"agg-id",
"instance-id",
@ -1502,7 +1586,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1511,7 +1595,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_machines SET (name, description) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11_machines SET (name, description) = ($1, $2) WHERE (user_id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
"machine-name",
"description",
@ -1542,7 +1626,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1551,7 +1635,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_machines SET name = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_machines SET name = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"machine-name",
"agg-id",
@ -1581,7 +1665,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1590,7 +1674,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_machines SET description = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_machines SET description = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
"description",
"agg-id",
@ -1639,7 +1723,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1648,7 +1732,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_machines SET secret = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_machines SET secret = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
&crypto.CryptoValue{
CryptoType: crypto.TypeHash,
@ -1680,7 +1764,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.users10 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedStmt: "UPDATE projections.users11 SET (change_date, sequence) = ($1, $2) WHERE (id = $3) AND (instance_id = $4)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
@ -1689,7 +1773,7 @@ func TestUserProjection_reduces(t *testing.T) {
},
},
{
expectedStmt: "UPDATE projections.users10_machines SET secret = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedStmt: "UPDATE projections.users11_machines SET secret = $1 WHERE (user_id = $2) AND (instance_id = $3)",
expectedArgs: []interface{}{
nil,
"agg-id",
@ -1717,7 +1801,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.users10 WHERE (instance_id = $1) AND (resource_owner = $2)",
expectedStmt: "DELETE FROM projections.users11 WHERE (instance_id = $1) AND (resource_owner = $2)",
expectedArgs: []interface{}{
"instance-id",
"agg-id",
@ -1744,7 +1828,7 @@ func TestUserProjection_reduces(t *testing.T) {
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "DELETE FROM projections.users10 WHERE (instance_id = $1)",
expectedStmt: "DELETE FROM projections.users11 WHERE (instance_id = $1)",
expectedArgs: []interface{}{
"agg-id",
},

View File

@ -31,7 +31,7 @@ var (
` projections.sessions8.user_resource_owner,` +
` projections.sessions8.user_checked_at,` +
` projections.login_names3.login_name,` +
` projections.users10_humans.display_name,` +
` projections.users11_humans.display_name,` +
` projections.sessions8.password_checked_at,` +
` projections.sessions8.intent_checked_at,` +
` projections.sessions8.webauthn_checked_at,` +
@ -48,8 +48,8 @@ var (
` projections.sessions8.expiration` +
` FROM projections.sessions8` +
` LEFT JOIN projections.login_names3 ON projections.sessions8.user_id = projections.login_names3.user_id AND projections.sessions8.instance_id = projections.login_names3.instance_id` +
` LEFT JOIN projections.users10_humans ON projections.sessions8.user_id = projections.users10_humans.user_id AND projections.sessions8.instance_id = projections.users10_humans.instance_id` +
` LEFT JOIN projections.users10 ON projections.sessions8.user_id = projections.users10.id AND projections.sessions8.instance_id = projections.users10.instance_id` +
` LEFT JOIN projections.users11_humans ON projections.sessions8.user_id = projections.users11_humans.user_id AND projections.sessions8.instance_id = projections.users11_humans.instance_id` +
` LEFT JOIN projections.users11 ON projections.sessions8.user_id = projections.users11.id AND projections.sessions8.instance_id = projections.users11.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
expectedSessionsQuery = regexp.QuoteMeta(`SELECT projections.sessions8.id,` +
` projections.sessions8.creation_date,` +
@ -62,7 +62,7 @@ var (
` projections.sessions8.user_resource_owner,` +
` projections.sessions8.user_checked_at,` +
` projections.login_names3.login_name,` +
` projections.users10_humans.display_name,` +
` projections.users11_humans.display_name,` +
` projections.sessions8.password_checked_at,` +
` projections.sessions8.intent_checked_at,` +
` projections.sessions8.webauthn_checked_at,` +
@ -75,8 +75,8 @@ var (
` COUNT(*) OVER ()` +
` FROM projections.sessions8` +
` LEFT JOIN projections.login_names3 ON projections.sessions8.user_id = projections.login_names3.user_id AND projections.sessions8.instance_id = projections.login_names3.instance_id` +
` LEFT JOIN projections.users10_humans ON projections.sessions8.user_id = projections.users10_humans.user_id AND projections.sessions8.instance_id = projections.users10_humans.instance_id` +
` LEFT JOIN projections.users10 ON projections.sessions8.user_id = projections.users10.id AND projections.sessions8.instance_id = projections.users10.instance_id` +
` LEFT JOIN projections.users11_humans ON projections.sessions8.user_id = projections.users11_humans.user_id AND projections.sessions8.instance_id = projections.users11_humans.instance_id` +
` LEFT JOIN projections.users11 ON projections.sessions8.user_id = projections.users11.id AND projections.sessions8.instance_id = projections.users11.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`)
sessionCols = []string{

View File

@ -42,17 +42,18 @@ type User struct {
}
type Human struct {
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
NickName string `json:"nick_name,omitempty"`
DisplayName string `json:"display_name,omitempty"`
AvatarKey string `json:"avatar_key,omitempty"`
PreferredLanguage language.Tag `json:"preferred_language,omitempty"`
Gender domain.Gender `json:"gender,omitempty"`
Email domain.EmailAddress `json:"email,omitempty"`
IsEmailVerified bool `json:"is_email_verified,omitempty"`
Phone domain.PhoneNumber `json:"phone,omitempty"`
IsPhoneVerified bool `json:"is_phone_verified,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
NickName string `json:"nick_name,omitempty"`
DisplayName string `json:"display_name,omitempty"`
AvatarKey string `json:"avatar_key,omitempty"`
PreferredLanguage language.Tag `json:"preferred_language,omitempty"`
Gender domain.Gender `json:"gender,omitempty"`
Email domain.EmailAddress `json:"email,omitempty"`
IsEmailVerified bool `json:"is_email_verified,omitempty"`
Phone domain.PhoneNumber `json:"phone,omitempty"`
IsPhoneVerified bool `json:"is_phone_verified,omitempty"`
PasswordChangeRequired bool `json:"password_change_required,omitempty"`
}
type Profile struct {
@ -275,6 +276,11 @@ var (
name: projection.HumanIsPhoneVerifiedCol,
table: humanTable,
}
HumanPasswordChangeRequiredCol = Column{
name: projection.HumanPasswordChangeRequired,
table: humanTable,
}
)
var (
@ -816,6 +822,7 @@ func scanUser(row *sql.Row) (*User, error) {
isEmailVerified := sql.NullBool{}
phone := sql.NullString{}
isPhoneVerified := sql.NullBool{}
passwordChangeRequired := sql.NullBool{}
machineID := sql.NullString{}
name := sql.NullString{}
@ -846,6 +853,7 @@ func scanUser(row *sql.Row) (*User, error) {
&isEmailVerified,
&phone,
&isPhoneVerified,
&passwordChangeRequired,
&machineID,
&name,
&description,
@ -865,17 +873,18 @@ func scanUser(row *sql.Row) (*User, error) {
if humanID.Valid {
u.Human = &Human{
FirstName: firstName.String,
LastName: lastName.String,
NickName: nickName.String,
DisplayName: displayName.String,
AvatarKey: avatarKey.String,
PreferredLanguage: language.Make(preferredLanguage.String),
Gender: domain.Gender(gender.Int32),
Email: domain.EmailAddress(email.String),
IsEmailVerified: isEmailVerified.Bool,
Phone: domain.PhoneNumber(phone.String),
IsPhoneVerified: isPhoneVerified.Bool,
FirstName: firstName.String,
LastName: lastName.String,
NickName: nickName.String,
DisplayName: displayName.String,
AvatarKey: avatarKey.String,
PreferredLanguage: language.Make(preferredLanguage.String),
Gender: domain.Gender(gender.Int32),
Email: domain.EmailAddress(email.String),
IsEmailVerified: isEmailVerified.Bool,
Phone: domain.PhoneNumber(phone.String),
IsPhoneVerified: isPhoneVerified.Bool,
PasswordChangeRequired: passwordChangeRequired.Bool,
}
} else if machineID.Valid {
u.Machine = &Machine{
@ -920,6 +929,7 @@ func prepareUserQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilder
HumanIsEmailVerifiedCol.identifier(),
HumanPhoneCol.identifier(),
HumanIsPhoneVerifiedCol.identifier(),
HumanPasswordChangeRequiredCol.identifier(),
MachineUserIDCol.identifier(),
MachineNameCol.identifier(),
MachineDescriptionCol.identifier(),
@ -1306,6 +1316,7 @@ func prepareUsersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilde
HumanIsEmailVerifiedCol.identifier(),
HumanPhoneCol.identifier(),
HumanIsPhoneVerifiedCol.identifier(),
HumanPasswordChangeRequiredCol.identifier(),
MachineUserIDCol.identifier(),
MachineNameCol.identifier(),
MachineDescriptionCol.identifier(),
@ -1344,6 +1355,7 @@ func prepareUsersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilde
isEmailVerified := sql.NullBool{}
phone := sql.NullString{}
isPhoneVerified := sql.NullBool{}
passwordChangeRequired := sql.NullBool{}
machineID := sql.NullString{}
name := sql.NullString{}
@ -1374,6 +1386,7 @@ func prepareUsersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilde
&isEmailVerified,
&phone,
&isPhoneVerified,
&passwordChangeRequired,
&machineID,
&name,
&description,
@ -1392,17 +1405,18 @@ func prepareUsersQuery(ctx context.Context, db prepareDatabase) (sq.SelectBuilde
if humanID.Valid {
u.Human = &Human{
FirstName: firstName.String,
LastName: lastName.String,
NickName: nickName.String,
DisplayName: displayName.String,
AvatarKey: avatarKey.String,
PreferredLanguage: language.Make(preferredLanguage.String),
Gender: domain.Gender(gender.Int32),
Email: domain.EmailAddress(email.String),
IsEmailVerified: isEmailVerified.Bool,
Phone: domain.PhoneNumber(phone.String),
IsPhoneVerified: isPhoneVerified.Bool,
FirstName: firstName.String,
LastName: lastName.String,
NickName: nickName.String,
DisplayName: displayName.String,
AvatarKey: avatarKey.String,
PreferredLanguage: language.Make(preferredLanguage.String),
Gender: domain.Gender(gender.Int32),
Email: domain.EmailAddress(email.String),
IsEmailVerified: isEmailVerified.Bool,
Phone: domain.PhoneNumber(phone.String),
IsPhoneVerified: isPhoneVerified.Bool,
PasswordChangeRequired: passwordChangeRequired.Bool,
}
} else if machineID.Valid {
u.Machine = &Machine{

View File

@ -39,38 +39,38 @@ var (
"method_type",
"count",
}
prepareActiveAuthMethodTypesStmt = `SELECT projections.users10_notifications.password_set,` +
prepareActiveAuthMethodTypesStmt = `SELECT projections.users11_notifications.password_set,` +
` auth_method_types.method_type,` +
` user_idps_count.count` +
` FROM projections.users10` +
` LEFT JOIN projections.users10_notifications ON projections.users10.id = projections.users10_notifications.user_id AND projections.users10.instance_id = projections.users10_notifications.instance_id` +
` FROM projections.users11` +
` LEFT JOIN projections.users11_notifications ON projections.users11.id = projections.users11_notifications.user_id AND projections.users11.instance_id = projections.users11_notifications.instance_id` +
` LEFT JOIN (SELECT DISTINCT(auth_method_types.method_type), auth_method_types.user_id, auth_method_types.instance_id FROM projections.user_auth_methods4 AS auth_method_types` +
` WHERE auth_method_types.state = $1) AS auth_method_types` +
` ON auth_method_types.user_id = projections.users10.id AND auth_method_types.instance_id = projections.users10.instance_id` +
` ON auth_method_types.user_id = projections.users11.id AND auth_method_types.instance_id = projections.users11.instance_id` +
` LEFT JOIN (SELECT user_idps_count.user_id, user_idps_count.instance_id, COUNT(user_idps_count.user_id) AS count FROM projections.idp_user_links3 AS user_idps_count` +
` GROUP BY user_idps_count.user_id, user_idps_count.instance_id) AS user_idps_count` +
` ON user_idps_count.user_id = projections.users10.id AND user_idps_count.instance_id = projections.users10.instance_id` +
` ON user_idps_count.user_id = projections.users11.id AND user_idps_count.instance_id = projections.users11.instance_id` +
` AS OF SYSTEM TIME '-1 ms`
prepareActiveAuthMethodTypesCols = []string{
"password_set",
"method_type",
"idps_count",
}
prepareAuthMethodTypesRequiredStmt = `SELECT projections.users10_notifications.password_set,` +
prepareAuthMethodTypesRequiredStmt = `SELECT projections.users11_notifications.password_set,` +
` auth_method_types.method_type,` +
` user_idps_count.count,` +
` auth_methods_force_mfa.force_mfa,` +
` auth_methods_force_mfa.force_mfa_local_only` +
` FROM projections.users10` +
` LEFT JOIN projections.users10_notifications ON projections.users10.id = projections.users10_notifications.user_id AND projections.users10.instance_id = projections.users10_notifications.instance_id` +
` FROM projections.users11` +
` LEFT JOIN projections.users11_notifications ON projections.users11.id = projections.users11_notifications.user_id AND projections.users11.instance_id = projections.users11_notifications.instance_id` +
` LEFT JOIN (SELECT DISTINCT(auth_method_types.method_type), auth_method_types.user_id, auth_method_types.instance_id FROM projections.user_auth_methods4 AS auth_method_types` +
` WHERE auth_method_types.state = $1) AS auth_method_types` +
` ON auth_method_types.user_id = projections.users10.id AND auth_method_types.instance_id = projections.users10.instance_id` +
` ON auth_method_types.user_id = projections.users11.id AND auth_method_types.instance_id = projections.users11.instance_id` +
` LEFT JOIN (SELECT user_idps_count.user_id, user_idps_count.instance_id, COUNT(user_idps_count.user_id) AS count FROM projections.idp_user_links3 AS user_idps_count` +
` GROUP BY user_idps_count.user_id, user_idps_count.instance_id) AS user_idps_count` +
` ON user_idps_count.user_id = projections.users10.id AND user_idps_count.instance_id = projections.users10.instance_id` +
` ON user_idps_count.user_id = projections.users11.id AND user_idps_count.instance_id = projections.users11.instance_id` +
` LEFT JOIN (SELECT auth_methods_force_mfa.force_mfa, auth_methods_force_mfa.force_mfa_local_only, auth_methods_force_mfa.instance_id, auth_methods_force_mfa.aggregate_id FROM projections.login_policies5 AS auth_methods_force_mfa ORDER BY auth_methods_force_mfa.is_default) AS auth_methods_force_mfa` +
` ON (auth_methods_force_mfa.aggregate_id = projections.users10.instance_id OR auth_methods_force_mfa.aggregate_id = projections.users10.resource_owner) AND auth_methods_force_mfa.instance_id = projections.users10.instance_id` +
` ON (auth_methods_force_mfa.aggregate_id = projections.users11.instance_id OR auth_methods_force_mfa.aggregate_id = projections.users11.resource_owner) AND auth_methods_force_mfa.instance_id = projections.users11.instance_id` +
` AS OF SYSTEM TIME '-1 ms
`
prepareAuthMethodTypesRequiredCols = []string{

View File

@ -58,20 +58,21 @@ SELECT
, h.is_email_verified
, h.phone
, h.is_phone_verified
, h.password_change_required
, m.user_id
, m.name
, m.description
, m.secret
, m.access_token_type
, count(*) OVER ()
FROM projections.users10 u
FROM projections.users11 u
LEFT JOIN
projections.users10_humans h
projections.users11_humans h
ON
u.id = h.user_id
AND u.instance_id = h.instance_id
LEFT JOIN
projections.users10_machines m
projections.users11_machines m
ON
u.id = m.user_id
AND u.instance_id = m.instance_id

View File

@ -94,6 +94,7 @@ SELECT
, h.is_email_verified
, h.phone
, h.is_phone_verified
, h.password_change_required
, m.user_id
, m.name
, m.description
@ -102,17 +103,17 @@ SELECT
, count(*) OVER ()
FROM found_users fu
JOIN
projections.users10 u
projections.users11 u
ON
fu.id = u.id
AND fu.instance_id = u.instance_id
LEFT JOIN
projections.users10_humans h
projections.users11_humans h
ON
fu.id = h.user_id
AND fu.instance_id = h.instance_id
LEFT JOIN
projections.users10_machines m
projections.users11_machines m
ON
fu.id = m.user_id
AND fu.instance_id = m.instance_id

View File

@ -23,14 +23,14 @@ var (
", projections.user_grants5.roles" +
", projections.user_grants5.state" +
", projections.user_grants5.user_id" +
", projections.users10.username" +
", projections.users10.type" +
", projections.users10.resource_owner" +
", projections.users10_humans.first_name" +
", projections.users10_humans.last_name" +
", projections.users10_humans.email" +
", projections.users10_humans.display_name" +
", projections.users10_humans.avatar_key" +
", projections.users11.username" +
", projections.users11.type" +
", projections.users11.resource_owner" +
", projections.users11_humans.first_name" +
", projections.users11_humans.last_name" +
", projections.users11_humans.email" +
", projections.users11_humans.display_name" +
", projections.users11_humans.avatar_key" +
", projections.login_names3.login_name" +
", projections.user_grants5.resource_owner" +
", projections.orgs1.name" +
@ -41,11 +41,11 @@ var (
", granted_orgs.name" +
", granted_orgs.primary_domain" +
" FROM projections.user_grants5" +
" LEFT JOIN projections.users10 ON projections.user_grants5.user_id = projections.users10.id AND projections.user_grants5.instance_id = projections.users10.instance_id" +
" LEFT JOIN projections.users10_humans ON projections.user_grants5.user_id = projections.users10_humans.user_id AND projections.user_grants5.instance_id = projections.users10_humans.instance_id" +
" LEFT JOIN projections.users11 ON projections.user_grants5.user_id = projections.users11.id AND projections.user_grants5.instance_id = projections.users11.instance_id" +
" LEFT JOIN projections.users11_humans ON projections.user_grants5.user_id = projections.users11_humans.user_id AND projections.user_grants5.instance_id = projections.users11_humans.instance_id" +
" LEFT JOIN projections.orgs1 ON projections.user_grants5.resource_owner = projections.orgs1.id AND projections.user_grants5.instance_id = projections.orgs1.instance_id" +
" LEFT JOIN projections.projects4 ON projections.user_grants5.project_id = projections.projects4.id AND projections.user_grants5.instance_id = projections.projects4.instance_id" +
" LEFT JOIN projections.orgs1 AS granted_orgs ON projections.users10.resource_owner = granted_orgs.id AND projections.users10.instance_id = granted_orgs.instance_id" +
" LEFT JOIN projections.orgs1 AS granted_orgs ON projections.users11.resource_owner = granted_orgs.id AND projections.users11.instance_id = granted_orgs.instance_id" +
" LEFT JOIN projections.login_names3 ON projections.user_grants5.user_id = projections.login_names3.user_id AND projections.user_grants5.instance_id = projections.login_names3.instance_id" +
` AS OF SYSTEM TIME '-1 ms' ` +
" WHERE projections.login_names3.is_primary = $1")
@ -85,14 +85,14 @@ var (
", projections.user_grants5.roles" +
", projections.user_grants5.state" +
", projections.user_grants5.user_id" +
", projections.users10.username" +
", projections.users10.type" +
", projections.users10.resource_owner" +
", projections.users10_humans.first_name" +
", projections.users10_humans.last_name" +
", projections.users10_humans.email" +
", projections.users10_humans.display_name" +
", projections.users10_humans.avatar_key" +
", projections.users11.username" +
", projections.users11.type" +
", projections.users11.resource_owner" +
", projections.users11_humans.first_name" +
", projections.users11_humans.last_name" +
", projections.users11_humans.email" +
", projections.users11_humans.display_name" +
", projections.users11_humans.avatar_key" +
", projections.login_names3.login_name" +
", projections.user_grants5.resource_owner" +
", projections.orgs1.name" +
@ -104,11 +104,11 @@ var (
", granted_orgs.primary_domain" +
", COUNT(*) OVER ()" +
" FROM projections.user_grants5" +
" LEFT JOIN projections.users10 ON projections.user_grants5.user_id = projections.users10.id AND projections.user_grants5.instance_id = projections.users10.instance_id" +
" LEFT JOIN projections.users10_humans ON projections.user_grants5.user_id = projections.users10_humans.user_id AND projections.user_grants5.instance_id = projections.users10_humans.instance_id" +
" LEFT JOIN projections.users11 ON projections.user_grants5.user_id = projections.users11.id AND projections.user_grants5.instance_id = projections.users11.instance_id" +
" LEFT JOIN projections.users11_humans ON projections.user_grants5.user_id = projections.users11_humans.user_id AND projections.user_grants5.instance_id = projections.users11_humans.instance_id" +
" LEFT JOIN projections.orgs1 ON projections.user_grants5.resource_owner = projections.orgs1.id AND projections.user_grants5.instance_id = projections.orgs1.instance_id" +
" LEFT JOIN projections.projects4 ON projections.user_grants5.project_id = projections.projects4.id AND projections.user_grants5.instance_id = projections.projects4.instance_id" +
" LEFT JOIN projections.orgs1 AS granted_orgs ON projections.users10.resource_owner = granted_orgs.id AND projections.users10.instance_id = granted_orgs.instance_id" +
" LEFT JOIN projections.orgs1 AS granted_orgs ON projections.users11.resource_owner = granted_orgs.id AND projections.users11.instance_id = granted_orgs.instance_id" +
" LEFT JOIN projections.login_names3 ON projections.user_grants5.user_id = projections.login_names3.user_id AND projections.user_grants5.instance_id = projections.login_names3.instance_id" +
` AS OF SYSTEM TIME '-1 ms' ` +
" WHERE projections.login_names3.is_primary = $1")

View File

@ -62,14 +62,14 @@ SELECT
, n.verified_phone
, n.password_set
, count(*) OVER ()
FROM projections.users10 u
FROM projections.users11 u
LEFT JOIN
projections.users10_humans h
projections.users11_humans h
ON
u.id = h.user_id
AND u.instance_id = h.instance_id
LEFT JOIN
projections.users10_notifications n
projections.users11_notifications n
ON
u.id = n.user_id
AND u.instance_id = n.instance_id

View File

@ -99,17 +99,17 @@ SELECT
, count(*) OVER ()
FROM found_users fu
JOIN
projections.users10 u
projections.users11 u
ON
fu.id = u.id
AND fu.instance_id = u.instance_id
LEFT JOIN
projections.users10_humans h
projections.users11_humans h
ON
fu.id = h.user_id
AND fu.instance_id = h.instance_id
LEFT JOIN
projections.users10_notifications n
projections.users11_notifications n
ON
fu.id = n.user_id
AND fu.instance_id = n.instance_id

View File

@ -148,43 +148,44 @@ var (
preferredLoginNameQuery = `SELECT preferred_login_name.user_id, preferred_login_name.login_name, preferred_login_name.instance_id` +
` FROM projections.login_names3 AS preferred_login_name` +
` WHERE preferred_login_name.is_primary = $1`
userQuery = `SELECT projections.users10.id,` +
` projections.users10.creation_date,` +
` projections.users10.change_date,` +
` projections.users10.resource_owner,` +
` projections.users10.sequence,` +
` projections.users10.state,` +
` projections.users10.type,` +
` projections.users10.username,` +
userQuery = `SELECT projections.users11.id,` +
` projections.users11.creation_date,` +
` projections.users11.change_date,` +
` projections.users11.resource_owner,` +
` projections.users11.sequence,` +
` projections.users11.state,` +
` projections.users11.type,` +
` projections.users11.username,` +
` login_names.loginnames,` +
` preferred_login_name.login_name,` +
` projections.users10_humans.user_id,` +
` projections.users10_humans.first_name,` +
` projections.users10_humans.last_name,` +
` projections.users10_humans.nick_name,` +
` projections.users10_humans.display_name,` +
` projections.users10_humans.preferred_language,` +
` projections.users10_humans.gender,` +
` projections.users10_humans.avatar_key,` +
` projections.users10_humans.email,` +
` projections.users10_humans.is_email_verified,` +
` projections.users10_humans.phone,` +
` projections.users10_humans.is_phone_verified,` +
` projections.users10_machines.user_id,` +
` projections.users10_machines.name,` +
` projections.users10_machines.description,` +
` projections.users10_machines.secret,` +
` projections.users10_machines.access_token_type,` +
` projections.users11_humans.user_id,` +
` projections.users11_humans.first_name,` +
` projections.users11_humans.last_name,` +
` projections.users11_humans.nick_name,` +
` projections.users11_humans.display_name,` +
` projections.users11_humans.preferred_language,` +
` projections.users11_humans.gender,` +
` projections.users11_humans.avatar_key,` +
` projections.users11_humans.email,` +
` projections.users11_humans.is_email_verified,` +
` projections.users11_humans.phone,` +
` projections.users11_humans.is_phone_verified,` +
` projections.users11_humans.password_change_required,` +
` projections.users11_machines.user_id,` +
` projections.users11_machines.name,` +
` projections.users11_machines.description,` +
` projections.users11_machines.secret,` +
` projections.users11_machines.access_token_type,` +
` COUNT(*) OVER ()` +
` FROM projections.users10` +
` LEFT JOIN projections.users10_humans ON projections.users10.id = projections.users10_humans.user_id AND projections.users10.instance_id = projections.users10_humans.instance_id` +
` LEFT JOIN projections.users10_machines ON projections.users10.id = projections.users10_machines.user_id AND projections.users10.instance_id = projections.users10_machines.instance_id` +
` FROM projections.users11` +
` LEFT JOIN projections.users11_humans ON projections.users11.id = projections.users11_humans.user_id AND projections.users11.instance_id = projections.users11_humans.instance_id` +
` LEFT JOIN projections.users11_machines ON projections.users11.id = projections.users11_machines.user_id AND projections.users11.instance_id = projections.users11_machines.instance_id` +
` LEFT JOIN` +
` (` + loginNamesQuery + `) AS login_names` +
` ON login_names.user_id = projections.users10.id AND login_names.instance_id = projections.users10.instance_id` +
` ON login_names.user_id = projections.users11.id AND login_names.instance_id = projections.users11.instance_id` +
` LEFT JOIN` +
` (` + preferredLoginNameQuery + `) AS preferred_login_name` +
` ON preferred_login_name.user_id = projections.users10.id AND preferred_login_name.instance_id = projections.users10.instance_id` +
` ON preferred_login_name.user_id = projections.users11.id AND preferred_login_name.instance_id = projections.users11.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
userCols = []string{
"id",
@ -210,6 +211,7 @@ var (
"is_email_verified",
"phone",
"is_phone_verified",
"password_change_required",
// machine
"user_id",
"name",
@ -218,21 +220,21 @@ var (
"access_token_type",
"count",
}
profileQuery = `SELECT projections.users10.id,` +
` projections.users10.creation_date,` +
` projections.users10.change_date,` +
` projections.users10.resource_owner,` +
` projections.users10.sequence,` +
` projections.users10_humans.user_id,` +
` projections.users10_humans.first_name,` +
` projections.users10_humans.last_name,` +
` projections.users10_humans.nick_name,` +
` projections.users10_humans.display_name,` +
` projections.users10_humans.preferred_language,` +
` projections.users10_humans.gender,` +
` projections.users10_humans.avatar_key` +
` FROM projections.users10` +
` LEFT JOIN projections.users10_humans ON projections.users10.id = projections.users10_humans.user_id AND projections.users10.instance_id = projections.users10_humans.instance_id` +
profileQuery = `SELECT projections.users11.id,` +
` projections.users11.creation_date,` +
` projections.users11.change_date,` +
` projections.users11.resource_owner,` +
` projections.users11.sequence,` +
` projections.users11_humans.user_id,` +
` projections.users11_humans.first_name,` +
` projections.users11_humans.last_name,` +
` projections.users11_humans.nick_name,` +
` projections.users11_humans.display_name,` +
` projections.users11_humans.preferred_language,` +
` projections.users11_humans.gender,` +
` projections.users11_humans.avatar_key` +
` FROM projections.users11` +
` LEFT JOIN projections.users11_humans ON projections.users11.id = projections.users11_humans.user_id AND projections.users11.instance_id = projections.users11_humans.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
profileCols = []string{
"id",
@ -249,16 +251,16 @@ var (
"gender",
"avatar_key",
}
emailQuery = `SELECT projections.users10.id,` +
` projections.users10.creation_date,` +
` projections.users10.change_date,` +
` projections.users10.resource_owner,` +
` projections.users10.sequence,` +
` projections.users10_humans.user_id,` +
` projections.users10_humans.email,` +
` projections.users10_humans.is_email_verified` +
` FROM projections.users10` +
` LEFT JOIN projections.users10_humans ON projections.users10.id = projections.users10_humans.user_id AND projections.users10.instance_id = projections.users10_humans.instance_id` +
emailQuery = `SELECT projections.users11.id,` +
` projections.users11.creation_date,` +
` projections.users11.change_date,` +
` projections.users11.resource_owner,` +
` projections.users11.sequence,` +
` projections.users11_humans.user_id,` +
` projections.users11_humans.email,` +
` projections.users11_humans.is_email_verified` +
` FROM projections.users11` +
` LEFT JOIN projections.users11_humans ON projections.users11.id = projections.users11_humans.user_id AND projections.users11.instance_id = projections.users11_humans.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
emailCols = []string{
"id",
@ -270,16 +272,16 @@ var (
"email",
"is_email_verified",
}
phoneQuery = `SELECT projections.users10.id,` +
` projections.users10.creation_date,` +
` projections.users10.change_date,` +
` projections.users10.resource_owner,` +
` projections.users10.sequence,` +
` projections.users10_humans.user_id,` +
` projections.users10_humans.phone,` +
` projections.users10_humans.is_phone_verified` +
` FROM projections.users10` +
` LEFT JOIN projections.users10_humans ON projections.users10.id = projections.users10_humans.user_id AND projections.users10.instance_id = projections.users10_humans.instance_id` +
phoneQuery = `SELECT projections.users11.id,` +
` projections.users11.creation_date,` +
` projections.users11.change_date,` +
` projections.users11.resource_owner,` +
` projections.users11.sequence,` +
` projections.users11_humans.user_id,` +
` projections.users11_humans.phone,` +
` projections.users11_humans.is_phone_verified` +
` FROM projections.users11` +
` LEFT JOIN projections.users11_humans ON projections.users11.id = projections.users11_humans.user_id AND projections.users11.instance_id = projections.users11_humans.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
phoneCols = []string{
"id",
@ -291,14 +293,14 @@ var (
"phone",
"is_phone_verified",
}
userUniqueQuery = `SELECT projections.users10.id,` +
` projections.users10.state,` +
` projections.users10.username,` +
` projections.users10_humans.user_id,` +
` projections.users10_humans.email,` +
` projections.users10_humans.is_email_verified` +
` FROM projections.users10` +
` LEFT JOIN projections.users10_humans ON projections.users10.id = projections.users10_humans.user_id AND projections.users10.instance_id = projections.users10_humans.instance_id` +
userUniqueQuery = `SELECT projections.users11.id,` +
` projections.users11.state,` +
` projections.users11.username,` +
` projections.users11_humans.user_id,` +
` projections.users11_humans.email,` +
` projections.users11_humans.is_email_verified` +
` FROM projections.users11` +
` LEFT JOIN projections.users11_humans ON projections.users11.id = projections.users11_humans.user_id AND projections.users11.instance_id = projections.users11_humans.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
userUniqueCols = []string{
"id",
@ -308,40 +310,40 @@ var (
"email",
"is_email_verified",
}
notifyUserQuery = `SELECT projections.users10.id,` +
` projections.users10.creation_date,` +
` projections.users10.change_date,` +
` projections.users10.resource_owner,` +
` projections.users10.sequence,` +
` projections.users10.state,` +
` projections.users10.type,` +
` projections.users10.username,` +
notifyUserQuery = `SELECT projections.users11.id,` +
` projections.users11.creation_date,` +
` projections.users11.change_date,` +
` projections.users11.resource_owner,` +
` projections.users11.sequence,` +
` projections.users11.state,` +
` projections.users11.type,` +
` projections.users11.username,` +
` login_names.loginnames,` +
` preferred_login_name.login_name,` +
` projections.users10_humans.user_id,` +
` projections.users10_humans.first_name,` +
` projections.users10_humans.last_name,` +
` projections.users10_humans.nick_name,` +
` projections.users10_humans.display_name,` +
` projections.users10_humans.preferred_language,` +
` projections.users10_humans.gender,` +
` projections.users10_humans.avatar_key,` +
` projections.users10_notifications.user_id,` +
` projections.users10_notifications.last_email,` +
` projections.users10_notifications.verified_email,` +
` projections.users10_notifications.last_phone,` +
` projections.users10_notifications.verified_phone,` +
` projections.users10_notifications.password_set,` +
` projections.users11_humans.user_id,` +
` projections.users11_humans.first_name,` +
` projections.users11_humans.last_name,` +
` projections.users11_humans.nick_name,` +
` projections.users11_humans.display_name,` +
` projections.users11_humans.preferred_language,` +
` projections.users11_humans.gender,` +
` projections.users11_humans.avatar_key,` +
` projections.users11_notifications.user_id,` +
` projections.users11_notifications.last_email,` +
` projections.users11_notifications.verified_email,` +
` projections.users11_notifications.last_phone,` +
` projections.users11_notifications.verified_phone,` +
` projections.users11_notifications.password_set,` +
` COUNT(*) OVER ()` +
` FROM projections.users10` +
` LEFT JOIN projections.users10_humans ON projections.users10.id = projections.users10_humans.user_id AND projections.users10.instance_id = projections.users10_humans.instance_id` +
` LEFT JOIN projections.users10_notifications ON projections.users10.id = projections.users10_notifications.user_id AND projections.users10.instance_id = projections.users10_notifications.instance_id` +
` FROM projections.users11` +
` LEFT JOIN projections.users11_humans ON projections.users11.id = projections.users11_humans.user_id AND projections.users11.instance_id = projections.users11_humans.instance_id` +
` LEFT JOIN projections.users11_notifications ON projections.users11.id = projections.users11_notifications.user_id AND projections.users11.instance_id = projections.users11_notifications.instance_id` +
` LEFT JOIN` +
` (` + loginNamesQuery + `) AS login_names` +
` ON login_names.user_id = projections.users10.id AND login_names.instance_id = projections.users10.instance_id` +
` ON login_names.user_id = projections.users11.id AND login_names.instance_id = projections.users11.instance_id` +
` LEFT JOIN` +
` (` + preferredLoginNameQuery + `) AS preferred_login_name` +
` ON preferred_login_name.user_id = projections.users10.id AND preferred_login_name.instance_id = projections.users10.instance_id` +
` ON preferred_login_name.user_id = projections.users11.id AND preferred_login_name.instance_id = projections.users11.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
notifyUserCols = []string{
"id",
@ -372,43 +374,44 @@ var (
"password_set",
"count",
}
usersQuery = `SELECT projections.users10.id,` +
` projections.users10.creation_date,` +
` projections.users10.change_date,` +
` projections.users10.resource_owner,` +
` projections.users10.sequence,` +
` projections.users10.state,` +
` projections.users10.type,` +
` projections.users10.username,` +
usersQuery = `SELECT projections.users11.id,` +
` projections.users11.creation_date,` +
` projections.users11.change_date,` +
` projections.users11.resource_owner,` +
` projections.users11.sequence,` +
` projections.users11.state,` +
` projections.users11.type,` +
` projections.users11.username,` +
` login_names.loginnames,` +
` preferred_login_name.login_name,` +
` projections.users10_humans.user_id,` +
` projections.users10_humans.first_name,` +
` projections.users10_humans.last_name,` +
` projections.users10_humans.nick_name,` +
` projections.users10_humans.display_name,` +
` projections.users10_humans.preferred_language,` +
` projections.users10_humans.gender,` +
` projections.users10_humans.avatar_key,` +
` projections.users10_humans.email,` +
` projections.users10_humans.is_email_verified,` +
` projections.users10_humans.phone,` +
` projections.users10_humans.is_phone_verified,` +
` projections.users10_machines.user_id,` +
` projections.users10_machines.name,` +
` projections.users10_machines.description,` +
` projections.users10_machines.secret,` +
` projections.users10_machines.access_token_type,` +
` projections.users11_humans.user_id,` +
` projections.users11_humans.first_name,` +
` projections.users11_humans.last_name,` +
` projections.users11_humans.nick_name,` +
` projections.users11_humans.display_name,` +
` projections.users11_humans.preferred_language,` +
` projections.users11_humans.gender,` +
` projections.users11_humans.avatar_key,` +
` projections.users11_humans.email,` +
` projections.users11_humans.is_email_verified,` +
` projections.users11_humans.phone,` +
` projections.users11_humans.is_phone_verified,` +
` projections.users11_humans.password_change_required,` +
` projections.users11_machines.user_id,` +
` projections.users11_machines.name,` +
` projections.users11_machines.description,` +
` projections.users11_machines.secret,` +
` projections.users11_machines.access_token_type,` +
` COUNT(*) OVER ()` +
` FROM projections.users10` +
` LEFT JOIN projections.users10_humans ON projections.users10.id = projections.users10_humans.user_id AND projections.users10.instance_id = projections.users10_humans.instance_id` +
` LEFT JOIN projections.users10_machines ON projections.users10.id = projections.users10_machines.user_id AND projections.users10.instance_id = projections.users10_machines.instance_id` +
` FROM projections.users11` +
` LEFT JOIN projections.users11_humans ON projections.users11.id = projections.users11_humans.user_id AND projections.users11.instance_id = projections.users11_humans.instance_id` +
` LEFT JOIN projections.users11_machines ON projections.users11.id = projections.users11_machines.user_id AND projections.users11.instance_id = projections.users11_machines.instance_id` +
` LEFT JOIN` +
` (` + loginNamesQuery + `) AS login_names` +
` ON login_names.user_id = projections.users10.id AND login_names.instance_id = projections.users10.instance_id` +
` ON login_names.user_id = projections.users11.id AND login_names.instance_id = projections.users11.instance_id` +
` LEFT JOIN` +
` (` + preferredLoginNameQuery + `) AS preferred_login_name` +
` ON preferred_login_name.user_id = projections.users10.id AND preferred_login_name.instance_id = projections.users10.instance_id` +
` ON preferred_login_name.user_id = projections.users11.id AND preferred_login_name.instance_id = projections.users11.instance_id` +
` AS OF SYSTEM TIME '-1 ms'`
usersCols = []string{
"id",
@ -434,6 +437,7 @@ var (
"is_email_verified",
"phone",
"is_phone_verified",
"password_change_required",
// machine
"user_id",
"name",
@ -504,6 +508,7 @@ func Test_UserPrepares(t *testing.T) {
true,
"phone",
true,
true,
// machine
nil,
nil,
@ -526,17 +531,18 @@ func Test_UserPrepares(t *testing.T) {
LoginNames: database.TextArray[string]{"login_name1", "login_name2"},
PreferredLoginName: "login_name1",
Human: &Human{
FirstName: "first_name",
LastName: "last_name",
NickName: "nick_name",
DisplayName: "display_name",
AvatarKey: "avatar_key",
PreferredLanguage: language.German,
Gender: domain.GenderUnspecified,
Email: "email",
IsEmailVerified: true,
Phone: "phone",
IsPhoneVerified: true,
FirstName: "first_name",
LastName: "last_name",
NickName: "nick_name",
DisplayName: "display_name",
AvatarKey: "avatar_key",
PreferredLanguage: language.German,
Gender: domain.GenderUnspecified,
Email: "email",
IsEmailVerified: true,
Phone: "phone",
IsPhoneVerified: true,
PasswordChangeRequired: true,
},
},
},
@ -571,6 +577,7 @@ func Test_UserPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// machine
"id",
"name",
@ -631,6 +638,7 @@ func Test_UserPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// machine
"id",
"name",
@ -1222,6 +1230,7 @@ func Test_UserPrepares(t *testing.T) {
true,
"phone",
true,
true,
// machine
nil,
nil,
@ -1249,17 +1258,18 @@ func Test_UserPrepares(t *testing.T) {
LoginNames: database.TextArray[string]{"login_name1", "login_name2"},
PreferredLoginName: "login_name1",
Human: &Human{
FirstName: "first_name",
LastName: "last_name",
NickName: "nick_name",
DisplayName: "display_name",
AvatarKey: "avatar_key",
PreferredLanguage: language.German,
Gender: domain.GenderUnspecified,
Email: "email",
IsEmailVerified: true,
Phone: "phone",
IsPhoneVerified: true,
FirstName: "first_name",
LastName: "last_name",
NickName: "nick_name",
DisplayName: "display_name",
AvatarKey: "avatar_key",
PreferredLanguage: language.German,
Gender: domain.GenderUnspecified,
Email: "email",
IsEmailVerified: true,
Phone: "phone",
IsPhoneVerified: true,
PasswordChangeRequired: true,
},
},
},
@ -1297,6 +1307,7 @@ func Test_UserPrepares(t *testing.T) {
true,
"phone",
true,
true,
// machine
nil,
nil,
@ -1328,6 +1339,7 @@ func Test_UserPrepares(t *testing.T) {
nil,
nil,
nil,
nil,
// machine
"id",
"name",
@ -1355,17 +1367,18 @@ func Test_UserPrepares(t *testing.T) {
LoginNames: database.TextArray[string]{"login_name1", "login_name2"},
PreferredLoginName: "login_name1",
Human: &Human{
FirstName: "first_name",
LastName: "last_name",
NickName: "nick_name",
DisplayName: "display_name",
AvatarKey: "avatar_key",
PreferredLanguage: language.German,
Gender: domain.GenderUnspecified,
Email: "email",
IsEmailVerified: true,
Phone: "phone",
IsPhoneVerified: true,
FirstName: "first_name",
LastName: "last_name",
NickName: "nick_name",
DisplayName: "display_name",
AvatarKey: "avatar_key",
PreferredLanguage: language.German,
Gender: domain.GenderUnspecified,
Email: "email",
IsEmailVerified: true,
Phone: "phone",
IsPhoneVerified: true,
PasswordChangeRequired: true,
},
},
{

View File

@ -19,8 +19,8 @@ SELECT s.creation_date,
s.sequence,
s.instance_id
FROM auth.user_sessions s
LEFT JOIN projections.users10 u ON s.user_id = u.id AND s.instance_id = u.instance_id
LEFT JOIN projections.users10_humans h ON s.user_id = h.user_id AND s.instance_id = h.instance_id
LEFT JOIN projections.users11 u ON s.user_id = u.id AND s.instance_id = u.instance_id
LEFT JOIN projections.users11_humans h ON s.user_id = h.user_id AND s.instance_id = h.instance_id
LEFT JOIN projections.login_names3 l ON s.user_id = l.user_id AND s.instance_id = l.instance_id AND l.is_primary = true
WHERE (s.user_agent_id = $1)
AND (s.user_id = $2)

View File

@ -19,8 +19,8 @@ SELECT s.creation_date,
s.sequence,
s.instance_id
FROM auth.user_sessions s
LEFT JOIN projections.users10 u ON s.user_id = u.id AND s.instance_id = u.instance_id
LEFT JOIN projections.users10_humans h ON s.user_id = h.user_id AND s.instance_id = h.instance_id
LEFT JOIN projections.users11 u ON s.user_id = u.id AND s.instance_id = u.instance_id
LEFT JOIN projections.users11_humans h ON s.user_id = h.user_id AND s.instance_id = h.instance_id
LEFT JOIN projections.login_names3 l ON s.user_id = l.user_id AND s.instance_id = l.instance_id AND l.is_primary = true
WHERE (s.user_agent_id = $1)
AND (s.instance_id = $2)

View File

@ -134,34 +134,44 @@ message SetMetadataEntry {
}
message HumanUser {
// Unique identifier of the user.
string user_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\"";
}
];
// State of the user, for example active, inactive, locked, deleted, initial.
UserState state = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "current state of the user";
}
];
// Username of the user, which can be globally unique or unique on organization level.
string username = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"minnie-mouse\"";
}
];
// Possible usable login names for the user.
repeated string login_names = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"gigi@zitadel.com\", \"gigi@zitadel.zitadel.ch\"]";
}
];
// Preferred login name of the user.
string preferred_login_name = 5 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"gigi@zitadel.com\"";
}
];
// Profile information of the user.
HumanProfile profile = 6;
// Email of the user, if defined.
HumanEmail email = 7;
// Phone of the user, if defined.
HumanPhone phone = 8;
// User is required to change the used password on the next login.
bool password_change_required = 9;
}
message User {