mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:37:32 +00:00
fix(login): improve auth handlers (#7969)
# Which Problems Are Solved During the implementation of #7486 it was noticed, that projections in the `auth` database schema could be blocked. Investigations suggested, that this is due to the use of [GORM](https://gorm.io/index.html) and it's inability to use an existing (sql) transaction. With the improved / simplified handling (see below) there should also be a minimal improvement in performance, resp. reduced database update statements. # How the Problems Are Solved The handlers in `auth` are exchanged to proper (sql) statements and gorm usage is removed for any writing part. To further improve / simplify the handling of the users, a new `auth.users3` table is created, where only attributes are handled, which are not yet available from the `projections.users`, `projections.login_name` and `projections.user_auth_methods` do not provide. This reduces the events handled in that specific handler by a lot. # Additional Changes None # Additional Context relates to #7486
This commit is contained in:
@@ -1517,12 +1517,12 @@ func userSessionByIDs(ctx context.Context, provider userSessionViewProvider, eve
|
||||
user_repo.HumanPasswordlessTokenCheckFailedType,
|
||||
user_repo.HumanU2FTokenCheckSucceededType,
|
||||
user_repo.HumanU2FTokenCheckFailedType:
|
||||
eventData, err := user_view_model.UserSessionFromEvent(event)
|
||||
userAgentID, err := user_view_model.UserAgentIDFromEvent(event)
|
||||
if err != nil {
|
||||
logging.WithFields("traceID", tracing.TraceIDFromCtx(ctx)).WithError(err).Debug("error getting event data")
|
||||
return user_view_model.UserSessionToModel(session), nil
|
||||
}
|
||||
if eventData.UserAgentID != agentID {
|
||||
if userAgentID != agentID {
|
||||
continue
|
||||
}
|
||||
case user_repo.UserRemovedType:
|
||||
|
@@ -2,6 +2,7 @@ package eventstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -75,11 +76,11 @@ type mockUser struct {
|
||||
|
||||
func (m *mockViewUserSession) UserSessionByIDs(string, string, string) (*user_view_model.UserSessionView, error) {
|
||||
return &user_view_model.UserSessionView{
|
||||
ExternalLoginVerification: m.ExternalLoginVerification,
|
||||
PasswordlessVerification: m.PasswordlessVerification,
|
||||
PasswordVerification: m.PasswordVerification,
|
||||
SecondFactorVerification: m.SecondFactorVerification,
|
||||
MultiFactorVerification: m.MultiFactorVerification,
|
||||
ExternalLoginVerification: sql.NullTime{Time: m.ExternalLoginVerification},
|
||||
PasswordlessVerification: sql.NullTime{Time: m.PasswordlessVerification},
|
||||
PasswordVerification: sql.NullTime{Time: m.PasswordVerification},
|
||||
SecondFactorVerification: sql.NullTime{Time: m.SecondFactorVerification},
|
||||
MultiFactorVerification: sql.NullTime{Time: m.MultiFactorVerification},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -90,7 +91,7 @@ func (m *mockViewUserSession) UserSessionsByAgentID(string, string) ([]*user_vie
|
||||
ResourceOwner: user.ResourceOwner,
|
||||
State: int32(user.SessionState),
|
||||
UserID: user.UserID,
|
||||
LoginName: user.LoginName,
|
||||
LoginName: sql.NullString{String: user.LoginName},
|
||||
}
|
||||
}
|
||||
return sessions, nil
|
||||
|
@@ -3,8 +3,6 @@ package handler
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
auth_view "github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/view"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
|
||||
@@ -98,50 +96,84 @@ func (t *RefreshToken) Reducers() []handler.AggregateReducer {
|
||||
}
|
||||
|
||||
func (t *RefreshToken) Reduce(event eventstore.Event) (_ *handler.Statement, err error) {
|
||||
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
|
||||
switch event.Type() {
|
||||
case user.HumanRefreshTokenAddedType:
|
||||
token := new(view_model.RefreshTokenView)
|
||||
err := token.AppendEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.view.PutRefreshToken(token)
|
||||
case user.HumanRefreshTokenRenewedType:
|
||||
e := new(user.HumanRefreshTokenRenewedEvent)
|
||||
if err := event.Unmarshal(e); err != nil {
|
||||
logging.WithError(err).Error("could not unmarshal event data")
|
||||
return zerrors.ThrowInternal(nil, "MODEL-BHn75", "could not unmarshal data")
|
||||
}
|
||||
token, err := t.view.RefreshTokenByID(e.TokenID, event.Aggregate().InstanceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = token.AppendEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return t.view.PutRefreshToken(token)
|
||||
case user.HumanRefreshTokenRemovedType:
|
||||
e := new(user.HumanRefreshTokenRemovedEvent)
|
||||
if err := event.Unmarshal(e); err != nil {
|
||||
logging.WithError(err).Error("could not unmarshal event data")
|
||||
return zerrors.ThrowInternal(nil, "MODEL-Bz653", "could not unmarshal data")
|
||||
}
|
||||
return t.view.DeleteRefreshToken(e.TokenID, event.Aggregate().InstanceID)
|
||||
case user.UserLockedType,
|
||||
user.UserDeactivatedType,
|
||||
user.UserRemovedType:
|
||||
|
||||
return t.view.DeleteUserRefreshTokens(event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
case instance.InstanceRemovedEventType:
|
||||
|
||||
return t.view.DeleteInstanceRefreshTokens(event.Aggregate().InstanceID)
|
||||
case org.OrgRemovedEventType:
|
||||
return t.view.DeleteOrgRefreshTokens(event)
|
||||
default:
|
||||
return nil
|
||||
// in case anything needs to be change here check if appendEvent function needs the change as well
|
||||
switch event.Type() {
|
||||
case user.HumanRefreshTokenAddedType:
|
||||
e, ok := event.(*user.HumanRefreshTokenAddedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-IoF6j", "reduce.wrong.event.type %s", user.HumanRefreshTokenAddedType)
|
||||
}
|
||||
}), nil
|
||||
columns := []handler.Column{
|
||||
handler.NewCol(view_model.RefreshTokenKeyClientID, e.ClientID),
|
||||
handler.NewCol(view_model.RefreshTokenKeyUserAgentID, e.UserAgentID),
|
||||
handler.NewCol(view_model.RefreshTokenKeyUserID, e.Aggregate().ID),
|
||||
handler.NewCol(view_model.RefreshTokenKeyInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCol(view_model.RefreshTokenKeyTokenID, e.TokenID),
|
||||
handler.NewCol(view_model.RefreshTokenKeyResourceOwner, e.Aggregate().ResourceOwner),
|
||||
handler.NewCol(view_model.RefreshTokenKeyCreationDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.RefreshTokenKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.RefreshTokenKeySequence, event.Sequence()),
|
||||
handler.NewCol(view_model.RefreshTokenKeyAMR, e.AuthMethodsReferences),
|
||||
handler.NewCol(view_model.RefreshTokenKeyAuthTime, e.AuthTime),
|
||||
handler.NewCol(view_model.RefreshTokenKeyAudience, e.Audience),
|
||||
handler.NewCol(view_model.RefreshTokenKeyExpiration, event.CreatedAt().Add(e.Expiration)),
|
||||
handler.NewCol(view_model.RefreshTokenKeyIdleExpiration, event.CreatedAt().Add(e.IdleExpiration)),
|
||||
handler.NewCol(view_model.RefreshTokenKeyScopes, e.Scopes),
|
||||
handler.NewCol(view_model.RefreshTokenKeyToken, e.TokenID),
|
||||
handler.NewCol(view_model.RefreshTokenKeyActor, view_model.TokenActor{TokenActor: e.Actor}),
|
||||
}
|
||||
return handler.NewUpsertStatement(event, columns[0:3], columns), nil
|
||||
case user.HumanRefreshTokenRenewedType:
|
||||
e, ok := event.(*user.HumanRefreshTokenRenewedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-AG43hq", "reduce.wrong.event.type %s", user.HumanRefreshTokenRenewedType)
|
||||
}
|
||||
return handler.NewUpdateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol(view_model.RefreshTokenKeyIdleExpiration, event.CreatedAt().Add(e.IdleExpiration)),
|
||||
handler.NewCol(view_model.RefreshTokenKeyToken, e.RefreshToken),
|
||||
handler.NewCol(view_model.RefreshTokenKeyChangeDate, e.CreatedAt()),
|
||||
handler.NewCol(view_model.RefreshTokenKeySequence, event.Sequence()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.RefreshTokenKeyTokenID, e.TokenID),
|
||||
handler.NewCond(view_model.RefreshTokenKeyInstanceID, e.Aggregate().InstanceID),
|
||||
},
|
||||
), nil
|
||||
case user.HumanRefreshTokenRemovedType:
|
||||
e, ok := event.(*user.HumanRefreshTokenRemovedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-SFF3t", "reduce.wrong.event.type %s", user.HumanRefreshTokenRemovedType)
|
||||
}
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.RefreshTokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.RefreshTokenKeyTokenID, e.TokenID),
|
||||
},
|
||||
), nil
|
||||
case user.UserLockedType,
|
||||
user.UserDeactivatedType,
|
||||
user.UserRemovedType:
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.RefreshTokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.RefreshTokenKeyUserID, event.Aggregate().ID),
|
||||
},
|
||||
), nil
|
||||
case instance.InstanceRemovedEventType:
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.RefreshTokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
},
|
||||
), nil
|
||||
case org.OrgRemovedEventType:
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.RefreshTokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.RefreshTokenKeyResourceOwner, event.Aggregate().ResourceOwner),
|
||||
},
|
||||
), nil
|
||||
default:
|
||||
return handler.NewNoOpStatement(event), nil
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ package handler
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/muhlemmer/gu"
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
auth_view "github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/view"
|
||||
@@ -150,129 +151,189 @@ func (t *Token) Reducers() []handler.AggregateReducer {
|
||||
}
|
||||
|
||||
func (t *Token) Reduce(event eventstore.Event) (_ *handler.Statement, err error) { //nolint:gocognit
|
||||
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
|
||||
switch event.Type() {
|
||||
case user.UserTokenAddedType,
|
||||
user.PersonalAccessTokenAddedType:
|
||||
token := new(view_model.TokenView)
|
||||
err := token.AppendEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return t.view.PutToken(token)
|
||||
case user.UserV1ProfileChangedType,
|
||||
user.HumanProfileChangedType:
|
||||
user := new(view_model.UserView)
|
||||
err := user.AppendEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tokens, err := t.view.TokensByUserID(event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, token := range tokens {
|
||||
token.PreferredLanguage = user.PreferredLanguage
|
||||
}
|
||||
return t.view.PutTokens(tokens)
|
||||
case user.UserV1SignedOutType,
|
||||
user.HumanSignedOutType:
|
||||
id, err := agentIDFromSession(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.view.DeleteSessionTokens(id, event)
|
||||
case user.UserLockedType,
|
||||
user.UserDeactivatedType,
|
||||
user.UserRemovedType:
|
||||
|
||||
return t.view.DeleteUserTokens(event)
|
||||
case user.UserTokenRemovedType,
|
||||
user.PersonalAccessTokenRemovedType:
|
||||
id, err := tokenIDFromRemovedEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.view.DeleteToken(id, event.Aggregate().InstanceID)
|
||||
case user.HumanRefreshTokenRemovedType:
|
||||
id, err := refreshTokenIDFromRemovedEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.view.DeleteTokensFromRefreshToken(id, event.Aggregate().InstanceID)
|
||||
case project.ApplicationDeactivatedType,
|
||||
project.ApplicationRemovedType:
|
||||
application, err := applicationFromSession(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.view.DeleteApplicationTokens(event, application.AppID)
|
||||
case project.ProjectDeactivatedType,
|
||||
project.ProjectRemovedType:
|
||||
project, err := t.getProjectByID(context.Background(), event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
applicationIDs := make([]string, 0, len(project.Applications))
|
||||
for _, app := range project.Applications {
|
||||
if app.OIDCConfig != nil && app.OIDCConfig.ClientID != "" {
|
||||
applicationIDs = append(applicationIDs, app.OIDCConfig.ClientID)
|
||||
}
|
||||
}
|
||||
|
||||
return t.view.DeleteApplicationTokens(event, applicationIDs...)
|
||||
case instance.InstanceRemovedEventType:
|
||||
return t.view.DeleteInstanceTokens(event)
|
||||
case org.OrgRemovedEventType:
|
||||
// deletes all tokens including PATs, which is expected for now
|
||||
// if there is an undo of the org deletion in the future,
|
||||
// we will need to have a look on how to handle the deleted PATs
|
||||
return t.view.DeleteOrgTokens(event)
|
||||
default:
|
||||
return nil
|
||||
// in case anything needs to be change here check if appendEvent function needs the change as well
|
||||
switch event.Type() {
|
||||
case user.UserTokenAddedType:
|
||||
e, ok := event.(*user.UserTokenAddedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-W4tnq", "reduce.wrong.event.type %s", user.UserTokenAddedType)
|
||||
}
|
||||
}), nil
|
||||
return handler.NewCreateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol(view_model.TokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCol(view_model.TokenKeyUserID, event.Aggregate().ID),
|
||||
handler.NewCol(view_model.TokenKeyResourceOwner, event.Aggregate().ResourceOwner),
|
||||
handler.NewCol(view_model.TokenKeyID, e.TokenID),
|
||||
handler.NewCol(view_model.TokenKeyCreationDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.TokenKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.TokenKeySequence, event.Sequence()),
|
||||
handler.NewCol(view_model.TokenKeyApplicationID, e.ApplicationID),
|
||||
handler.NewCol(view_model.TokenKeyUserAgentID, e.UserAgentID),
|
||||
handler.NewCol(view_model.TokenKeyAudience, e.Audience),
|
||||
handler.NewCol(view_model.TokenKeyScopes, e.Scopes),
|
||||
handler.NewCol(view_model.TokenKeyExpiration, e.Expiration),
|
||||
handler.NewCol(view_model.TokenKeyPreferredLanguage, e.PreferredLanguage),
|
||||
handler.NewCol(view_model.TokenKeyRefreshTokenID, e.RefreshTokenID),
|
||||
handler.NewCol(view_model.TokenKeyActor, view_model.TokenActor{TokenActor: e.Actor}),
|
||||
handler.NewCol(view_model.TokenKeyIsPat, false),
|
||||
},
|
||||
), nil
|
||||
case user.PersonalAccessTokenAddedType:
|
||||
e, ok := event.(*user.PersonalAccessTokenAddedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-zF3rb", "reduce.wrong.event.type %s", user.PersonalAccessTokenAddedType)
|
||||
}
|
||||
return handler.NewCreateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol(view_model.TokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCol(view_model.TokenKeyUserID, event.Aggregate().ID),
|
||||
handler.NewCol(view_model.TokenKeyResourceOwner, event.Aggregate().ResourceOwner),
|
||||
handler.NewCol(view_model.TokenKeyID, e.TokenID),
|
||||
handler.NewCol(view_model.TokenKeyCreationDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.TokenKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.TokenKeySequence, event.Sequence()),
|
||||
handler.NewCol(view_model.TokenKeyScopes, e.Scopes),
|
||||
handler.NewCol(view_model.TokenKeyExpiration, e.Expiration),
|
||||
handler.NewCol(view_model.TokenKeyIsPat, true),
|
||||
},
|
||||
), nil
|
||||
case user.UserV1ProfileChangedType,
|
||||
user.HumanProfileChangedType:
|
||||
e, ok := event.(*user.HumanProfileChangedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-ASF2t", "reduce.wrong.event.type %s", user.HumanProfileChangedType)
|
||||
}
|
||||
if e.PreferredLanguage == nil {
|
||||
return handler.NewNoOpStatement(event), nil
|
||||
}
|
||||
return handler.NewUpdateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol(view_model.TokenKeyPreferredLanguage, gu.Value(e.PreferredLanguage).String()),
|
||||
handler.NewCol(view_model.TokenKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.TokenKeySequence, event.Sequence()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.TokenKeyInstanceID, e.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.TokenKeyUserID, e.Aggregate().ID),
|
||||
},
|
||||
), nil
|
||||
case user.UserV1SignedOutType,
|
||||
user.HumanSignedOutType:
|
||||
e, ok := event.(*user.HumanSignedOutEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-Wtn2q", "reduce.wrong.event.type %s", user.HumanSignedOutType)
|
||||
}
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.TokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.TokenKeyUserID, event.Aggregate().ID),
|
||||
handler.NewCond(view_model.TokenKeyUserAgentID, e.UserAgentID),
|
||||
},
|
||||
), nil
|
||||
case user.UserLockedType,
|
||||
user.UserDeactivatedType,
|
||||
user.UserRemovedType:
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.TokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.TokenKeyUserID, event.Aggregate().ID),
|
||||
},
|
||||
), nil
|
||||
case user.UserTokenRemovedType,
|
||||
user.PersonalAccessTokenRemovedType:
|
||||
var tokenID string
|
||||
switch e := event.(type) {
|
||||
case *user.UserTokenRemovedEvent:
|
||||
tokenID = e.TokenID
|
||||
case *user.PersonalAccessTokenRemovedEvent:
|
||||
tokenID = e.TokenID
|
||||
default:
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-SF3ga", "reduce.wrong.event.type %s", user.UserTokenRemovedType)
|
||||
}
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.TokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.TokenKeyID, tokenID),
|
||||
},
|
||||
), nil
|
||||
case user.HumanRefreshTokenRemovedType:
|
||||
e, ok := event.(*user.HumanRefreshTokenRemovedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-Sfe11", "reduce.wrong.event.type %s", user.HumanRefreshTokenRemovedType)
|
||||
}
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.TokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.TokenKeyRefreshTokenID, e.TokenID),
|
||||
},
|
||||
), nil
|
||||
case project.ApplicationDeactivatedType,
|
||||
project.ApplicationRemovedType:
|
||||
var applicationID string
|
||||
switch e := event.(type) {
|
||||
case *project.ApplicationDeactivatedEvent:
|
||||
applicationID = e.AppID
|
||||
case *project.ApplicationRemovedEvent:
|
||||
applicationID = e.AppID
|
||||
default:
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-SF3fq", "reduce.wrong.event.type %v", []eventstore.EventType{project.ApplicationDeactivatedType, project.ApplicationRemovedType})
|
||||
}
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.TokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.TokenKeyApplicationID, applicationID),
|
||||
},
|
||||
), nil
|
||||
case project.ProjectDeactivatedType,
|
||||
project.ProjectRemovedType:
|
||||
project, err := t.getProjectByID(context.Background(), event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
applicationIDs := make([]string, 0, len(project.Applications))
|
||||
for _, app := range project.Applications {
|
||||
if app.OIDCConfig != nil && app.OIDCConfig.ClientID != "" {
|
||||
applicationIDs = append(applicationIDs, app.OIDCConfig.ClientID)
|
||||
}
|
||||
}
|
||||
if len(applicationIDs) == 0 {
|
||||
return handler.NewNoOpStatement(event), nil
|
||||
}
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.TokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewOneOfTextCond(view_model.TokenKeyApplicationID, applicationIDs),
|
||||
},
|
||||
), nil
|
||||
case instance.InstanceRemovedEventType:
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.TokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
},
|
||||
), nil
|
||||
case org.OrgRemovedEventType:
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.TokenKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.TokenKeyResourceOwner, event.Aggregate().ResourceOwner),
|
||||
},
|
||||
), nil
|
||||
default:
|
||||
return handler.NewNoOpStatement(event), nil
|
||||
}
|
||||
}
|
||||
|
||||
type userAgentIDPayload struct {
|
||||
ID string `json:"userAgentID"`
|
||||
}
|
||||
|
||||
func agentIDFromSession(event eventstore.Event) (string, error) {
|
||||
session := make(map[string]interface{})
|
||||
if err := event.Unmarshal(&session); err != nil {
|
||||
payload := new(userAgentIDPayload)
|
||||
if err := event.Unmarshal(payload); err != nil {
|
||||
logging.WithError(err).Error("could not unmarshal event data")
|
||||
return "", zerrors.ThrowInternal(nil, "MODEL-sd325", "could not unmarshal data")
|
||||
}
|
||||
agentID, _ := session["userAgentID"].(string)
|
||||
return agentID, nil
|
||||
}
|
||||
|
||||
func applicationFromSession(event eventstore.Event) (*project_es_model.Application, error) {
|
||||
application := new(project_es_model.Application)
|
||||
if err := event.Unmarshal(application); err != nil {
|
||||
logging.WithError(err).Error("could not unmarshal event data")
|
||||
return nil, zerrors.ThrowInternal(nil, "MODEL-Hrw1q", "could not unmarshal data")
|
||||
}
|
||||
return application, nil
|
||||
}
|
||||
|
||||
func tokenIDFromRemovedEvent(event eventstore.Event) (string, error) {
|
||||
removed := make(map[string]interface{})
|
||||
if err := event.Unmarshal(&removed); err != nil {
|
||||
logging.WithError(err).Error("could not unmarshal event data")
|
||||
return "", zerrors.ThrowInternal(nil, "MODEL-Sff32", "could not unmarshal data")
|
||||
}
|
||||
return removed["tokenId"].(string), nil
|
||||
}
|
||||
|
||||
func refreshTokenIDFromRemovedEvent(event eventstore.Event) (string, error) {
|
||||
removed := make(map[string]interface{})
|
||||
if err := event.Unmarshal(&removed); err != nil {
|
||||
logging.WithError(err).Error("could not unmarshal event data")
|
||||
return "", zerrors.ThrowInternal(nil, "MODEL-Dfb3w", "could not unmarshal data")
|
||||
}
|
||||
return removed["tokenId"].(string), nil
|
||||
return payload.ID, nil
|
||||
}
|
||||
|
||||
func (t *Token) getProjectByID(ctx context.Context, projID, instanceID string) (*proj_model.Project, error) {
|
||||
|
@@ -4,25 +4,20 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
auth_view "github.com/zitadel/zitadel/internal/auth/repository/eventsourcing/view"
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/handler/v2"
|
||||
es_models "github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
org_model "github.com/zitadel/zitadel/internal/org/model"
|
||||
org_es_model "github.com/zitadel/zitadel/internal/org/repository/eventsourcing/model"
|
||||
org_view "github.com/zitadel/zitadel/internal/org/repository/view"
|
||||
query2 "github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
user_repo "github.com/zitadel/zitadel/internal/repository/user"
|
||||
usr_view "github.com/zitadel/zitadel/internal/user/repository/view"
|
||||
view_model "github.com/zitadel/zitadel/internal/user/repository/view/model"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
userTable = "auth.users2"
|
||||
userTable = "auth.users3"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
@@ -58,26 +53,14 @@ func (u *User) Reducers() []handler.AggregateReducer {
|
||||
{
|
||||
Aggregate: user_repo.AggregateType,
|
||||
EventReducers: []handler.EventReducer{
|
||||
{
|
||||
Event: user_repo.HumanOTPSMSAddedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanOTPSMSRemovedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanOTPEmailAddedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanOTPEmailRemovedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.MachineAddedEventType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanAddedType,
|
||||
Reduce: u.ProcessUser,
|
||||
@@ -94,62 +77,14 @@ func (u *User) Reducers() []handler.AggregateReducer {
|
||||
Event: user_repo.HumanRegisteredType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserV1ProfileChangedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserV1EmailChangedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserV1EmailVerifiedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserV1PhoneChangedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserV1PhoneVerifiedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserV1PhoneRemovedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserV1AddressChangedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserDeactivatedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserReactivatedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserLockedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserUnlockedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserV1MFAOTPAddedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserV1MFAOTPVerifiedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserV1MFAOTPRemovedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserV1MFAInitSkippedType,
|
||||
Reduce: u.ProcessUser,
|
||||
@@ -158,86 +93,22 @@ func (u *User) Reducers() []handler.AggregateReducer {
|
||||
Event: user_repo.UserV1PasswordChangedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanProfileChangedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanEmailChangedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanEmailVerifiedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanAvatarAddedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanAvatarRemovedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanPhoneChangedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanPhoneVerifiedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanPhoneRemovedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanAddressChangedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanMFAOTPAddedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanMFAOTPVerifiedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanMFAOTPRemovedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanU2FTokenAddedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanU2FTokenVerifiedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanU2FTokenRemovedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanPasswordlessTokenAddedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanPasswordlessTokenVerifiedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanPasswordlessTokenRemovedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanMFAInitSkippedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.MachineChangedEventType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.HumanPasswordChangedType,
|
||||
Reduce: u.ProcessUser,
|
||||
@@ -266,14 +137,6 @@ func (u *User) Reducers() []handler.AggregateReducer {
|
||||
Event: user_repo.HumanPasswordlessInitCodeRequestedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserDomainClaimedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserUserNameChangedType,
|
||||
Reduce: u.ProcessUser,
|
||||
},
|
||||
{
|
||||
Event: user_repo.UserRemovedType,
|
||||
Reduce: u.ProcessUser,
|
||||
@@ -283,30 +146,6 @@ func (u *User) Reducers() []handler.AggregateReducer {
|
||||
{
|
||||
Aggregate: org.AggregateType,
|
||||
EventReducers: []handler.EventReducer{
|
||||
{
|
||||
Event: org.OrgDomainVerifiedEventType,
|
||||
Reduce: u.ProcessOrg,
|
||||
},
|
||||
{
|
||||
Event: org.OrgDomainRemovedEventType,
|
||||
Reduce: u.ProcessOrg,
|
||||
},
|
||||
{
|
||||
Event: org.DomainPolicyAddedEventType,
|
||||
Reduce: u.ProcessOrg,
|
||||
},
|
||||
{
|
||||
Event: org.DomainPolicyChangedEventType,
|
||||
Reduce: u.ProcessOrg,
|
||||
},
|
||||
{
|
||||
Event: org.DomainPolicyRemovedEventType,
|
||||
Reduce: u.ProcessOrg,
|
||||
},
|
||||
{
|
||||
Event: org.OrgDomainPrimarySetEventType,
|
||||
Reduce: u.ProcessOrg,
|
||||
},
|
||||
{
|
||||
Event: org.OrgRemovedEventType,
|
||||
Reduce: u.ProcessOrg,
|
||||
@@ -327,141 +166,124 @@ func (u *User) Reducers() []handler.AggregateReducer {
|
||||
|
||||
//nolint:gocognit
|
||||
func (u *User) ProcessUser(event eventstore.Event) (_ *handler.Statement, err error) {
|
||||
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
|
||||
user := new(view_model.UserView)
|
||||
switch event.Type() {
|
||||
case user_repo.UserV1AddedType,
|
||||
user_repo.MachineAddedEventType,
|
||||
user_repo.HumanAddedType,
|
||||
user_repo.UserV1RegisteredType,
|
||||
user_repo.HumanRegisteredType:
|
||||
err = user.AppendEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = u.fillLoginNames(user)
|
||||
case user_repo.UserV1ProfileChangedType,
|
||||
user_repo.UserV1EmailChangedType,
|
||||
user_repo.UserV1EmailVerifiedType,
|
||||
user_repo.UserV1PhoneChangedType,
|
||||
user_repo.UserV1PhoneVerifiedType,
|
||||
user_repo.UserV1PhoneRemovedType,
|
||||
user_repo.UserV1AddressChangedType,
|
||||
user_repo.UserDeactivatedType,
|
||||
user_repo.UserReactivatedType,
|
||||
user_repo.UserLockedType,
|
||||
user_repo.UserUnlockedType,
|
||||
user_repo.UserV1MFAOTPAddedType,
|
||||
user_repo.UserV1MFAOTPVerifiedType,
|
||||
user_repo.UserV1MFAOTPRemovedType,
|
||||
user_repo.UserV1MFAInitSkippedType,
|
||||
user_repo.UserV1PasswordChangedType,
|
||||
user_repo.HumanProfileChangedType,
|
||||
user_repo.HumanEmailChangedType,
|
||||
user_repo.HumanEmailVerifiedType,
|
||||
user_repo.HumanAvatarAddedType,
|
||||
user_repo.HumanAvatarRemovedType,
|
||||
user_repo.HumanPhoneChangedType,
|
||||
user_repo.HumanPhoneVerifiedType,
|
||||
user_repo.HumanPhoneRemovedType,
|
||||
user_repo.HumanAddressChangedType,
|
||||
user_repo.HumanMFAOTPAddedType,
|
||||
user_repo.HumanMFAOTPVerifiedType,
|
||||
user_repo.HumanMFAOTPRemovedType,
|
||||
user_repo.HumanOTPSMSAddedType,
|
||||
user_repo.HumanOTPSMSRemovedType,
|
||||
user_repo.HumanOTPEmailAddedType,
|
||||
user_repo.HumanOTPEmailRemovedType,
|
||||
user_repo.HumanU2FTokenAddedType,
|
||||
user_repo.HumanU2FTokenVerifiedType,
|
||||
user_repo.HumanU2FTokenRemovedType,
|
||||
user_repo.HumanPasswordlessTokenAddedType,
|
||||
user_repo.HumanPasswordlessTokenVerifiedType,
|
||||
user_repo.HumanPasswordlessTokenRemovedType,
|
||||
user_repo.HumanMFAInitSkippedType,
|
||||
user_repo.MachineChangedEventType,
|
||||
user_repo.HumanPasswordChangedType,
|
||||
user_repo.HumanInitialCodeAddedType,
|
||||
user_repo.UserV1InitialCodeAddedType,
|
||||
user_repo.UserV1InitializedCheckSucceededType,
|
||||
user_repo.HumanInitializedCheckSucceededType,
|
||||
user_repo.HumanPasswordlessInitCodeAddedType,
|
||||
user_repo.HumanPasswordlessInitCodeRequestedType:
|
||||
user, err = u.view.UserByID(event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
if err != nil {
|
||||
if !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
user, err = u.userFromEventstore(event.Aggregate(), user.EventTypes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = user.AppendEvent(event)
|
||||
case user_repo.UserDomainClaimedType,
|
||||
user_repo.UserUserNameChangedType:
|
||||
user, err = u.view.UserByID(event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
if err != nil {
|
||||
if !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
user, err = u.userFromEventstore(event.Aggregate(), user.EventTypes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = user.AppendEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = u.fillLoginNames(user)
|
||||
case user_repo.UserRemovedType:
|
||||
return u.view.DeleteUser(event.Aggregate().ID, event.Aggregate().InstanceID, event)
|
||||
default:
|
||||
return nil
|
||||
// in case anything needs to be change here check if appendEvent function needs the change as well
|
||||
switch event.Type() {
|
||||
case user_repo.UserV1AddedType,
|
||||
user_repo.HumanAddedType:
|
||||
e, ok := event.(*user_repo.HumanAddedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-SDAGF", "reduce.wrong.event.type %s", user_repo.HumanAddedType)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
return u.setPasswordData(event, e.Secret, e.EncodedHash), nil
|
||||
case user_repo.UserV1RegisteredType,
|
||||
user_repo.HumanRegisteredType:
|
||||
e, ok := event.(*user_repo.HumanRegisteredEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-AS1hz", "reduce.wrong.event.type %s", user_repo.HumanRegisteredType)
|
||||
}
|
||||
return u.view.PutUser(user, event)
|
||||
}), nil
|
||||
return u.setPasswordData(event, e.Secret, e.EncodedHash), nil
|
||||
case user_repo.UserV1PasswordChangedType,
|
||||
user_repo.HumanPasswordChangedType:
|
||||
e, ok := event.(*user_repo.HumanPasswordChangedEvent)
|
||||
if !ok {
|
||||
return nil, zerrors.ThrowInvalidArgumentf(nil, "MODEL-Gd31w", "reduce.wrong.event.type %s", user_repo.HumanPasswordChangedType)
|
||||
}
|
||||
return u.setPasswordData(event, e.Secret, e.EncodedHash), nil
|
||||
case user_repo.UserV1PhoneRemovedType,
|
||||
user_repo.HumanPhoneRemovedType,
|
||||
user_repo.UserV1MFAOTPVerifiedType,
|
||||
user_repo.HumanMFAOTPVerifiedType,
|
||||
user_repo.HumanOTPSMSRemovedType,
|
||||
user_repo.HumanOTPEmailRemovedType,
|
||||
user_repo.HumanU2FTokenVerifiedType:
|
||||
return handler.NewUpdateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol(view_model.UserKeyMFAInitSkipped, time.Time{}),
|
||||
handler.NewCol(view_model.UserKeyChangeDate, event.CreatedAt()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.UserKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserKeyUserID, event.Aggregate().ID),
|
||||
}), nil
|
||||
case user_repo.UserV1MFAInitSkippedType,
|
||||
user_repo.HumanMFAInitSkippedType:
|
||||
return handler.NewUpdateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol(view_model.UserKeyMFAInitSkipped, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserKeyChangeDate, event.CreatedAt()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.UserKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserKeyUserID, event.Aggregate().ID),
|
||||
}), nil
|
||||
case user_repo.UserV1InitialCodeAddedType,
|
||||
user_repo.HumanInitialCodeAddedType:
|
||||
return handler.NewUpdateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol(view_model.UserKeyInitRequired, true),
|
||||
handler.NewCol(view_model.UserKeyChangeDate, event.CreatedAt()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.UserKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserKeyUserID, event.Aggregate().ID),
|
||||
}), nil
|
||||
case user_repo.UserV1InitializedCheckSucceededType,
|
||||
user_repo.HumanInitializedCheckSucceededType:
|
||||
return handler.NewUpdateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol(view_model.UserKeyInitRequired, false),
|
||||
handler.NewCol(view_model.UserKeyChangeDate, event.CreatedAt()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.UserKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserKeyUserID, event.Aggregate().ID),
|
||||
}), nil
|
||||
case user_repo.HumanPasswordlessInitCodeAddedType,
|
||||
user_repo.HumanPasswordlessInitCodeRequestedType:
|
||||
return handler.NewUpdateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol(view_model.UserKeyPasswordlessInitRequired, true),
|
||||
handler.NewCol(view_model.UserKeyPasswordInitRequired, false),
|
||||
handler.NewCol(view_model.UserKeyChangeDate, event.CreatedAt()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.UserKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserKeyUserID, event.Aggregate().ID),
|
||||
handler.NewCond(view_model.UserKeyPasswordSet, false),
|
||||
}), nil
|
||||
case user_repo.UserRemovedType:
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.UserKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserKeyUserID, event.Aggregate().ID),
|
||||
}), nil
|
||||
default:
|
||||
return handler.NewNoOpStatement(event), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (u *User) fillLoginNames(user *view_model.UserView) (err error) {
|
||||
userLoginMustBeDomain, primaryDomain, domains, err := u.loginNameInformation(context.Background(), user.ResourceOwner, user.InstanceID)
|
||||
if err != nil {
|
||||
return err
|
||||
func (u *User) setPasswordData(event eventstore.Event, secret *crypto.CryptoValue, hash string) *handler.Statement {
|
||||
set := secret != nil || hash != ""
|
||||
columns := []handler.Column{
|
||||
handler.NewCol(view_model.UserKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCol(view_model.UserKeyUserID, event.Aggregate().ID),
|
||||
handler.NewCol(view_model.UserKeyResourceOwner, event.Aggregate().ResourceOwner),
|
||||
handler.NewCol(view_model.UserKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserKeyPasswordSet, set),
|
||||
handler.NewCol(view_model.UserKeyPasswordInitRequired, !set),
|
||||
handler.NewCol(view_model.UserKeyPasswordChange, event.CreatedAt()),
|
||||
}
|
||||
user.SetLoginNames(userLoginMustBeDomain, domains)
|
||||
user.PreferredLoginName = user.GenerateLoginName(primaryDomain, userLoginMustBeDomain)
|
||||
return nil
|
||||
return handler.NewUpsertStatement(event, columns[0:2], columns)
|
||||
}
|
||||
|
||||
func (u *User) ProcessOrg(event eventstore.Event) (_ *handler.Statement, err error) {
|
||||
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
|
||||
switch event.Type() {
|
||||
case org.OrgDomainVerifiedEventType,
|
||||
org.OrgDomainRemovedEventType,
|
||||
org.DomainPolicyAddedEventType,
|
||||
org.DomainPolicyChangedEventType,
|
||||
org.DomainPolicyRemovedEventType:
|
||||
return u.fillLoginNamesOnOrgUsers(event)
|
||||
case org.OrgDomainPrimarySetEventType:
|
||||
return u.fillPreferredLoginNamesOnOrgUsers(event)
|
||||
case org.OrgRemovedEventType:
|
||||
return u.view.UpdateOrgOwnerRemovedUsers(event)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (u *User) ProcessInstance(event eventstore.Event) (_ *handler.Statement, err error) {
|
||||
// in case anything needs to be change here check if appendEvent function needs the change as well
|
||||
switch event.Type() {
|
||||
case instance.InstanceRemovedEventType:
|
||||
return handler.NewStatement(event,
|
||||
func(ex handler.Executer, projectionName string) error {
|
||||
return u.view.DeleteInstanceUsers(event)
|
||||
case org.OrgRemovedEventType:
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.UserKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserKeyResourceOwner, event.Aggregate().ID),
|
||||
},
|
||||
), nil
|
||||
default:
|
||||
@@ -469,97 +291,16 @@ func (u *User) ProcessInstance(event eventstore.Event) (_ *handler.Statement, er
|
||||
}
|
||||
}
|
||||
|
||||
func (u *User) fillLoginNamesOnOrgUsers(event eventstore.Event) error {
|
||||
userLoginMustBeDomain, _, domains, err := u.loginNameInformation(context.Background(), event.Aggregate().ResourceOwner, event.Aggregate().InstanceID)
|
||||
if err != nil {
|
||||
return err
|
||||
func (u *User) ProcessInstance(event eventstore.Event) (_ *handler.Statement, err error) {
|
||||
// in case anything needs to be change here check if appendEvent function needs the change as well
|
||||
switch event.Type() {
|
||||
case instance.InstanceRemovedEventType:
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.UserKeyInstanceID, event.Aggregate().InstanceID),
|
||||
},
|
||||
), nil
|
||||
default:
|
||||
return handler.NewNoOpStatement(event), nil
|
||||
}
|
||||
users, err := u.view.UsersByOrgID(event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, user := range users {
|
||||
user.SetLoginNames(userLoginMustBeDomain, domains)
|
||||
}
|
||||
return u.view.PutUsers(users, event)
|
||||
}
|
||||
|
||||
func (u *User) fillPreferredLoginNamesOnOrgUsers(event eventstore.Event) error {
|
||||
userLoginMustBeDomain, primaryDomain, _, err := u.loginNameInformation(context.Background(), event.Aggregate().ResourceOwner, event.Aggregate().InstanceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !userLoginMustBeDomain {
|
||||
return nil
|
||||
}
|
||||
users, err := u.view.UsersByOrgID(event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, user := range users {
|
||||
user.PreferredLoginName = user.GenerateLoginName(primaryDomain, userLoginMustBeDomain)
|
||||
}
|
||||
return u.view.PutUsers(users, event)
|
||||
}
|
||||
|
||||
func (u *User) getOrgByID(ctx context.Context, orgID, instanceID string) (*org_model.Org, error) {
|
||||
query, err := org_view.OrgByIDQuery(orgID, instanceID, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
esOrg := &org_es_model.Org{
|
||||
ObjectRoot: es_models.ObjectRoot{
|
||||
AggregateID: orgID,
|
||||
},
|
||||
}
|
||||
events, err := u.es.Filter(ctx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = esOrg.AppendEvents(events...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if esOrg.Sequence == 0 {
|
||||
return nil, zerrors.ThrowNotFound(nil, "EVENT-3m9vs", "Errors.Org.NotFound")
|
||||
}
|
||||
|
||||
return org_es_model.OrgToModel(esOrg), nil
|
||||
}
|
||||
|
||||
func (u *User) loginNameInformation(ctx context.Context, orgID string, instanceID string) (userLoginMustBeDomain bool, primaryDomain string, domains []*org_model.OrgDomain, err error) {
|
||||
org, err := u.getOrgByID(ctx, orgID, instanceID)
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
primaryDomain, err = org.GetPrimaryDomain()
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
if org.DomainPolicy != nil {
|
||||
return org.DomainPolicy.UserLoginMustBeDomain, primaryDomain, org.Domains, nil
|
||||
}
|
||||
policy, err := u.queries.DefaultDomainPolicy(authz.WithInstanceID(ctx, org.InstanceID))
|
||||
if err != nil {
|
||||
return false, "", nil, err
|
||||
}
|
||||
return policy.UserLoginMustBeDomain, primaryDomain, org.Domains, nil
|
||||
}
|
||||
|
||||
func (u *User) userFromEventstore(agg *eventstore.Aggregate, eventTypes []eventstore.EventType) (*view_model.UserView, error) {
|
||||
query, err := usr_view.UserByIDQuery(agg.ID, agg.InstanceID, time.Time{}, eventTypes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
events, err := u.es.Filter(context.Background(), query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user := &view_model.UserView{}
|
||||
for _, e := range events {
|
||||
if err = user.AppendEvent(e); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
@@ -12,8 +12,8 @@ import (
|
||||
"github.com/zitadel/zitadel/internal/repository/instance"
|
||||
"github.com/zitadel/zitadel/internal/repository/org"
|
||||
"github.com/zitadel/zitadel/internal/repository/user"
|
||||
es_model "github.com/zitadel/zitadel/internal/user/repository/eventsourcing/model"
|
||||
view_model "github.com/zitadel/zitadel/internal/user/repository/view/model"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -187,64 +187,160 @@ func (s *UserSession) Reducers() []handler.AggregateReducer {
|
||||
}
|
||||
}
|
||||
|
||||
func sessionColumns(event eventstore.Event, columns ...handler.Column) ([]handler.Column, error) {
|
||||
userAgent, err := agentIDFromSession(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append([]handler.Column{
|
||||
handler.NewCol(view_model.UserSessionKeyUserAgentID, userAgent),
|
||||
handler.NewCol(view_model.UserSessionKeyUserID, event.Aggregate().ID),
|
||||
handler.NewCol(view_model.UserSessionKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCol(view_model.UserSessionKeyCreationDate, handler.OnlySetValueOnInsert(userSessionTable, event.CreatedAt())),
|
||||
handler.NewCol(view_model.UserSessionKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeyResourceOwner, event.Aggregate().ResourceOwner),
|
||||
handler.NewCol(view_model.UserSessionKeySequence, event.Sequence()),
|
||||
}, columns...), nil
|
||||
}
|
||||
|
||||
func (u *UserSession) Reduce(event eventstore.Event) (_ *handler.Statement, err error) {
|
||||
// in case anything needs to be change here check if appendEvent function needs the change as well
|
||||
switch event.Type() {
|
||||
case user.UserV1PasswordCheckSucceededType,
|
||||
user.UserV1PasswordCheckFailedType,
|
||||
user.UserV1MFAOTPCheckSucceededType,
|
||||
user.UserV1MFAOTPCheckFailedType,
|
||||
user.UserV1SignedOutType,
|
||||
user.HumanPasswordCheckSucceededType,
|
||||
user.HumanPasswordCheckFailedType,
|
||||
user.UserIDPLoginCheckSucceededType,
|
||||
user.HumanMFAOTPCheckSucceededType,
|
||||
user.HumanPasswordCheckSucceededType:
|
||||
columns, err := sessionColumns(event,
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordVerification, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeyState, domain.UserSessionStateActive),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return handler.NewUpsertStatement(event, columns[0:3], columns), nil
|
||||
case user.UserV1PasswordCheckFailedType,
|
||||
user.HumanPasswordCheckFailedType:
|
||||
columns, err := sessionColumns(event,
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordVerification, time.Time{}),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return handler.NewUpsertStatement(event, columns[0:3], columns), nil
|
||||
case user.UserV1MFAOTPCheckSucceededType,
|
||||
user.HumanMFAOTPCheckSucceededType:
|
||||
columns, err := sessionColumns(event,
|
||||
handler.NewCol(view_model.UserSessionKeySecondFactorVerification, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeySecondFactorVerificationType, domain.MFATypeTOTP),
|
||||
handler.NewCol(view_model.UserSessionKeyState, domain.UserSessionStateActive),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return handler.NewUpsertStatement(event, columns[0:3], columns), nil
|
||||
case user.UserV1MFAOTPCheckFailedType,
|
||||
user.HumanMFAOTPCheckFailedType,
|
||||
user.HumanU2FTokenCheckSucceededType,
|
||||
user.HumanU2FTokenCheckFailedType,
|
||||
user.HumanPasswordlessTokenCheckSucceededType,
|
||||
user.HumanPasswordlessTokenCheckFailedType,
|
||||
user.HumanU2FTokenCheckFailedType:
|
||||
columns, err := sessionColumns(event,
|
||||
handler.NewCol(view_model.UserSessionKeySecondFactorVerification, time.Time{}),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return handler.NewUpsertStatement(event, columns[0:3], columns), nil
|
||||
case user.UserV1SignedOutType,
|
||||
user.HumanSignedOutType:
|
||||
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
|
||||
var session *view_model.UserSessionView
|
||||
eventData, err := view_model.UserSessionFromEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
session, err = u.view.UserSessionByIDs(eventData.UserAgentID, event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
if err != nil {
|
||||
if !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
session = &view_model.UserSessionView{
|
||||
CreationDate: event.CreatedAt(),
|
||||
ResourceOwner: event.Aggregate().ResourceOwner,
|
||||
UserAgentID: eventData.UserAgentID,
|
||||
UserID: event.Aggregate().ID,
|
||||
State: int32(domain.UserSessionStateActive),
|
||||
InstanceID: event.Aggregate().InstanceID,
|
||||
}
|
||||
}
|
||||
return u.updateSession(session, event)
|
||||
}), nil
|
||||
columns, err := sessionColumns(event,
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordlessVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeySecondFactorVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeySecondFactorVerificationType, domain.MFALevelNotSetUp),
|
||||
handler.NewCol(view_model.UserSessionKeyMultiFactorVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeyMultiFactorVerificationType, domain.MFALevelNotSetUp),
|
||||
handler.NewCol(view_model.UserSessionKeyExternalLoginVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeyState, domain.UserSessionStateTerminated),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return handler.NewUpsertStatement(event, columns[0:3], columns), nil
|
||||
case user.UserIDPLoginCheckSucceededType:
|
||||
data := new(es_model.AuthRequest)
|
||||
err := data.SetData(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
columns, err := sessionColumns(event,
|
||||
handler.NewCol(view_model.UserSessionKeyExternalLoginVerification, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeySelectedIDPConfigID, data.SelectedIDPConfigID),
|
||||
handler.NewCol(view_model.UserSessionKeyState, domain.UserSessionStateActive),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return handler.NewUpsertStatement(event, columns[0:3], columns), nil
|
||||
case user.HumanU2FTokenCheckSucceededType:
|
||||
data := new(es_model.AuthRequest)
|
||||
err := data.SetData(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
columns, err := sessionColumns(event,
|
||||
handler.NewCol(view_model.UserSessionKeySecondFactorVerification, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeySecondFactorVerificationType, domain.MFATypeU2F),
|
||||
handler.NewCol(view_model.UserSessionKeyState, domain.UserSessionStateActive),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return handler.NewUpsertStatement(event, columns[0:3], columns), nil
|
||||
case user.HumanPasswordlessTokenCheckSucceededType:
|
||||
data := new(es_model.AuthRequest)
|
||||
err := data.SetData(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
columns, err := sessionColumns(event,
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordlessVerification, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeyMultiFactorVerification, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeyMultiFactorVerificationType, domain.MFATypeU2FUserVerification),
|
||||
handler.NewCol(view_model.UserSessionKeyState, domain.UserSessionStateActive),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return handler.NewUpsertStatement(event, columns[0:3], columns), nil
|
||||
case user.HumanPasswordlessTokenCheckFailedType:
|
||||
data := new(es_model.AuthRequest)
|
||||
err := data.SetData(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
columns, err := sessionColumns(event,
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordlessVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeyMultiFactorVerification, time.Time{}),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return handler.NewUpsertStatement(event, columns[0:3], columns), nil
|
||||
case user.UserLockedType,
|
||||
user.UserDeactivatedType:
|
||||
return handler.NewUpdateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol("passwordless_verification", time.Time{}),
|
||||
handler.NewCol("password_verification", time.Time{}),
|
||||
handler.NewCol("second_factor_verification", time.Time{}),
|
||||
handler.NewCol("second_factor_verification_type", domain.MFALevelNotSetUp),
|
||||
handler.NewCol("multi_factor_verification", time.Time{}),
|
||||
handler.NewCol("multi_factor_verification_type", domain.MFALevelNotSetUp),
|
||||
handler.NewCol("external_login_verification", time.Time{}),
|
||||
handler.NewCol("state", domain.UserSessionStateTerminated),
|
||||
handler.NewCol("change_date", event.CreatedAt()),
|
||||
handler.NewCol("sequence", event.Sequence()),
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordlessVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeySecondFactorVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeySecondFactorVerificationType, domain.MFALevelNotSetUp),
|
||||
handler.NewCol(view_model.UserSessionKeyMultiFactorVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeyMultiFactorVerificationType, domain.MFALevelNotSetUp),
|
||||
handler.NewCol(view_model.UserSessionKeyExternalLoginVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeyState, domain.UserSessionStateTerminated),
|
||||
handler.NewCol(view_model.UserSessionKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeySequence, event.Sequence()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond("instance_id", event.Aggregate().InstanceID),
|
||||
handler.NewCond("user_id", event.Aggregate().ID),
|
||||
handler.Not(handler.NewCond("state", domain.UserSessionStateTerminated)),
|
||||
handler.NewCond(view_model.UserSessionKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserSessionKeyUserID, event.Aggregate().ID),
|
||||
handler.Not(handler.NewCond(view_model.UserSessionKeyState, domain.UserSessionStateTerminated)),
|
||||
},
|
||||
), nil
|
||||
case user.UserV1PasswordChangedType,
|
||||
@@ -256,26 +352,26 @@ func (u *UserSession) Reduce(event eventstore.Event) (_ *handler.Statement, err
|
||||
return handler.NewMultiStatement(event,
|
||||
handler.AddUpdateStatement(
|
||||
[]handler.Column{
|
||||
handler.NewCol("password_verification", event.CreatedAt()),
|
||||
handler.NewCol("change_date", event.CreatedAt()),
|
||||
handler.NewCol("sequence", event.Sequence()),
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordVerification, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeySequence, event.Sequence()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond("instance_id", event.Aggregate().InstanceID),
|
||||
handler.NewCond("user_id", event.Aggregate().ID),
|
||||
handler.NewCond("user_agent_id", userAgent),
|
||||
handler.NewCond(view_model.UserSessionKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserSessionKeyUserID, event.Aggregate().ID),
|
||||
handler.NewCond(view_model.UserSessionKeyUserAgentID, userAgent),
|
||||
}),
|
||||
handler.AddUpdateStatement(
|
||||
[]handler.Column{
|
||||
handler.NewCol("password_verification", time.Time{}),
|
||||
handler.NewCol("change_date", event.CreatedAt()),
|
||||
handler.NewCol("sequence", event.Sequence()),
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeySequence, event.Sequence()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond("instance_id", event.Aggregate().InstanceID),
|
||||
handler.NewCond("user_id", event.Aggregate().ID),
|
||||
handler.Not(handler.NewCond("user_agent_id", userAgent)),
|
||||
handler.Not(handler.NewCond("state", domain.UserSessionStateTerminated)),
|
||||
handler.NewCond(view_model.UserSessionKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserSessionKeyUserID, event.Aggregate().ID),
|
||||
handler.Not(handler.NewCond(view_model.UserSessionKeyUserAgentID, userAgent)),
|
||||
handler.Not(handler.NewCond(view_model.UserSessionKeyState, domain.UserSessionStateTerminated)),
|
||||
}),
|
||||
), nil
|
||||
case user.UserV1MFAOTPRemovedType,
|
||||
@@ -283,84 +379,77 @@ func (u *UserSession) Reduce(event eventstore.Event) (_ *handler.Statement, err
|
||||
user.HumanU2FTokenRemovedType:
|
||||
return handler.NewUpdateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol("second_factor_verification", time.Time{}),
|
||||
handler.NewCol("change_date", event.CreatedAt()),
|
||||
handler.NewCol("sequence", event.Sequence()),
|
||||
handler.NewCol(view_model.UserSessionKeySecondFactorVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeySequence, event.Sequence()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond("instance_id", event.Aggregate().InstanceID),
|
||||
handler.NewCond("user_id", event.Aggregate().ID),
|
||||
handler.Not(handler.NewCond("state", domain.UserSessionStateTerminated)),
|
||||
handler.NewCond(view_model.UserSessionKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserSessionKeyUserID, event.Aggregate().ID),
|
||||
handler.Not(handler.NewCond(view_model.UserSessionKeyState, domain.UserSessionStateTerminated)),
|
||||
},
|
||||
), nil
|
||||
case user.UserIDPLinkRemovedType,
|
||||
user.UserIDPLinkCascadeRemovedType:
|
||||
return handler.NewUpdateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol("external_login_verification", time.Time{}),
|
||||
handler.NewCol("selected_idp_config_id", ""),
|
||||
handler.NewCol("change_date", event.CreatedAt()),
|
||||
handler.NewCol("sequence", event.Sequence()),
|
||||
handler.NewCol(view_model.UserSessionKeyExternalLoginVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeySelectedIDPConfigID, ""),
|
||||
handler.NewCol(view_model.UserSessionKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeySequence, event.Sequence()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond("instance_id", event.Aggregate().InstanceID),
|
||||
handler.NewCond("user_id", event.Aggregate().ID),
|
||||
handler.Not(handler.NewCond("selected_idp_config_id", "")),
|
||||
handler.NewCond(view_model.UserSessionKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserSessionKeyUserID, event.Aggregate().ID),
|
||||
handler.Not(handler.NewCond(view_model.UserSessionKeySelectedIDPConfigID, "")),
|
||||
},
|
||||
), nil
|
||||
case user.HumanPasswordlessTokenRemovedType:
|
||||
return handler.NewUpdateStatement(event,
|
||||
[]handler.Column{
|
||||
handler.NewCol("passwordless_verification", time.Time{}),
|
||||
handler.NewCol("multi_factor_verification", time.Time{}),
|
||||
handler.NewCol("change_date", event.CreatedAt()),
|
||||
handler.NewCol("sequence", event.Sequence()),
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordlessVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeyMultiFactorVerification, time.Time{}),
|
||||
handler.NewCol(view_model.UserSessionKeyChangeDate, event.CreatedAt()),
|
||||
handler.NewCol(view_model.UserSessionKeySequence, event.Sequence()),
|
||||
},
|
||||
[]handler.Condition{
|
||||
handler.NewCond("instance_id", event.Aggregate().InstanceID),
|
||||
handler.NewCond("user_id", event.Aggregate().ID),
|
||||
handler.Not(handler.NewCond("state", domain.UserSessionStateTerminated)),
|
||||
handler.NewCond(view_model.UserSessionKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserSessionKeyUserID, event.Aggregate().ID),
|
||||
handler.Not(handler.NewCond(view_model.UserSessionKeyState, domain.UserSessionStateTerminated)),
|
||||
},
|
||||
), nil
|
||||
case user.UserRemovedType:
|
||||
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
|
||||
return u.view.DeleteUserSessions(event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
}), nil
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.UserSessionKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserSessionKeyUserID, event.Aggregate().ID),
|
||||
},
|
||||
), nil
|
||||
case user.HumanRegisteredType:
|
||||
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
|
||||
eventData, err := view_model.UserSessionFromEvent(event)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
session := &view_model.UserSessionView{
|
||||
CreationDate: event.CreatedAt(),
|
||||
ResourceOwner: event.Aggregate().ResourceOwner,
|
||||
UserAgentID: eventData.UserAgentID,
|
||||
UserID: event.Aggregate().ID,
|
||||
State: int32(domain.UserSessionStateActive),
|
||||
InstanceID: event.Aggregate().InstanceID,
|
||||
PasswordVerification: event.CreatedAt(),
|
||||
}
|
||||
return u.updateSession(session, event)
|
||||
}), nil
|
||||
columns, err := sessionColumns(event,
|
||||
handler.NewCol(view_model.UserSessionKeyState, domain.UserSessionStateActive),
|
||||
handler.NewCol(view_model.UserSessionKeyPasswordVerification, event.CreatedAt()),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return handler.NewCreateStatement(event,
|
||||
columns,
|
||||
), nil
|
||||
case instance.InstanceRemovedEventType:
|
||||
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
|
||||
return u.view.DeleteInstanceUserSessions(event.Aggregate().InstanceID)
|
||||
}), nil
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.UserSessionKeyInstanceID, event.Aggregate().InstanceID),
|
||||
},
|
||||
), nil
|
||||
case org.OrgRemovedEventType:
|
||||
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
|
||||
return u.view.DeleteOrgUserSessions(event)
|
||||
}), nil
|
||||
return handler.NewDeleteStatement(event,
|
||||
[]handler.Condition{
|
||||
handler.NewCond(view_model.UserSessionKeyInstanceID, event.Aggregate().InstanceID),
|
||||
handler.NewCond(view_model.UserSessionKeyResourceOwner, event.Aggregate().ResourceOwner),
|
||||
},
|
||||
), nil
|
||||
default:
|
||||
return handler.NewStatement(event, func(ex handler.Executer, projectionName string) error {
|
||||
return nil
|
||||
}), nil
|
||||
return handler.NewNoOpStatement(event), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserSession) updateSession(session *view_model.UserSessionView, event eventstore.Event) error {
|
||||
if err := session.AppendEvent(event); err != nil {
|
||||
return err
|
||||
}
|
||||
return u.view.PutUserSession(session)
|
||||
}
|
||||
|
@@ -4,13 +4,10 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/api/authz"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
user_model "github.com/zitadel/zitadel/internal/user/model"
|
||||
usr_view "github.com/zitadel/zitadel/internal/user/repository/view"
|
||||
"github.com/zitadel/zitadel/internal/user/repository/view/model"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -29,54 +26,6 @@ func (v *View) SearchRefreshTokens(request *user_model.RefreshTokenSearchRequest
|
||||
return usr_view.SearchRefreshTokens(v.Db, refreshTokenTable, request)
|
||||
}
|
||||
|
||||
func (v *View) PutRefreshToken(token *model.RefreshTokenView) error {
|
||||
return usr_view.PutRefreshToken(v.Db, refreshTokenTable, token)
|
||||
}
|
||||
|
||||
func (v *View) PutRefreshTokens(token []*model.RefreshTokenView) error {
|
||||
return usr_view.PutRefreshTokens(v.Db, refreshTokenTable, token...)
|
||||
}
|
||||
|
||||
func (v *View) DeleteRefreshToken(tokenID, instanceID string) error {
|
||||
err := usr_view.DeleteRefreshToken(v.Db, refreshTokenTable, tokenID, instanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteUserRefreshTokens(userID, instanceID string) error {
|
||||
err := usr_view.DeleteUserRefreshTokens(v.Db, refreshTokenTable, userID, instanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteApplicationRefreshTokens(event *models.Event, ids ...string) error {
|
||||
err := usr_view.DeleteApplicationTokens(v.Db, refreshTokenTable, event.InstanceID, ids)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteInstanceRefreshTokens(instanceID string) error {
|
||||
err := usr_view.DeleteInstanceRefreshTokens(v.Db, refreshTokenTable, instanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteOrgRefreshTokens(event eventstore.Event) error {
|
||||
err := usr_view.DeleteOrgRefreshTokens(v.Db, refreshTokenTable, event.Aggregate().InstanceID, event.Aggregate().ResourceOwner)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) GetLatestRefreshTokenSequence(ctx context.Context) (_ *query.CurrentState, err error) {
|
||||
q := &query.CurrentStateSearchQueries{
|
||||
Queries: make([]query.SearchQuery, 2),
|
||||
|
@@ -3,12 +3,10 @@ package view
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/telemetry/tracing"
|
||||
usr_view "github.com/zitadel/zitadel/internal/user/repository/view"
|
||||
"github.com/zitadel/zitadel/internal/user/repository/view/model"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -23,70 +21,6 @@ func (v *View) TokensByUserID(userID, instanceID string) ([]*model.TokenView, er
|
||||
return usr_view.TokensByUserID(v.Db, tokenTable, userID, instanceID)
|
||||
}
|
||||
|
||||
func (v *View) PutToken(token *model.TokenView) error {
|
||||
return usr_view.PutToken(v.Db, tokenTable, token)
|
||||
}
|
||||
|
||||
func (v *View) PutTokens(token []*model.TokenView) error {
|
||||
return usr_view.PutTokens(v.Db, tokenTable, token...)
|
||||
}
|
||||
|
||||
func (v *View) DeleteToken(tokenID, instanceID string) error {
|
||||
err := usr_view.DeleteToken(v.Db, tokenTable, tokenID, instanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteSessionTokens(agentID string, event eventstore.Event) error {
|
||||
err := usr_view.DeleteSessionTokens(v.Db, tokenTable, agentID, event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteUserTokens(event eventstore.Event) error {
|
||||
err := usr_view.DeleteUserTokens(v.Db, tokenTable, event.Aggregate().ID, event.Aggregate().InstanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteApplicationTokens(event eventstore.Event, ids ...string) error {
|
||||
err := usr_view.DeleteApplicationTokens(v.Db, tokenTable, event.Aggregate().InstanceID, ids)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteTokensFromRefreshToken(refreshTokenID, instanceID string) error {
|
||||
err := usr_view.DeleteTokensFromRefreshToken(v.Db, tokenTable, refreshTokenID, instanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteInstanceTokens(event eventstore.Event) error {
|
||||
err := usr_view.DeleteInstanceTokens(v.Db, tokenTable, event.Aggregate().InstanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteOrgTokens(event eventstore.Event) error {
|
||||
err := usr_view.DeleteOrgTokens(v.Db, tokenTable, event.Aggregate().InstanceID, event.Aggregate().ResourceOwner)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) GetLatestTokenSequence(ctx context.Context, instanceID string) (_ *query.CurrentState, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
|
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
usr_model "github.com/zitadel/zitadel/internal/user/model"
|
||||
"github.com/zitadel/zitadel/internal/user/repository/view"
|
||||
@@ -14,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
userTable = "auth.users2"
|
||||
userTable = "auth.users3"
|
||||
)
|
||||
|
||||
func (v *View) UserByID(userID, instanceID string) (*model.UserView, error) {
|
||||
@@ -142,42 +141,6 @@ func (v *View) userByID(ctx context.Context, instanceID string, queries ...query
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (v *View) UsersByOrgID(orgID, instanceID string) ([]*model.UserView, error) {
|
||||
return view.UsersByOrgID(v.Db, userTable, orgID, instanceID)
|
||||
}
|
||||
|
||||
func (v *View) PutUser(user *model.UserView, event eventstore.Event) error {
|
||||
return view.PutUser(v.Db, userTable, user)
|
||||
}
|
||||
|
||||
func (v *View) PutUsers(users []*model.UserView, event eventstore.Event) error {
|
||||
return view.PutUsers(v.Db, userTable, users...)
|
||||
}
|
||||
|
||||
func (v *View) DeleteUser(userID, instanceID string, event eventstore.Event) error {
|
||||
err := view.DeleteUser(v.Db, userTable, userID, instanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteInstanceUsers(event eventstore.Event) error {
|
||||
err := view.DeleteInstanceUsers(v.Db, userTable, event.Aggregate().InstanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) UpdateOrgOwnerRemovedUsers(event eventstore.Event) error {
|
||||
err := view.UpdateOrgOwnerRemovedUsers(v.Db, userTable, event.Aggregate().InstanceID, event.Aggregate().ID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) GetLatestUserSequence(ctx context.Context, instanceID string) (_ *query.CurrentState, err error) {
|
||||
q := &query.CurrentStateSearchQueries{
|
||||
Queries: make([]query.SearchQuery, 2),
|
||||
|
@@ -3,11 +3,9 @@ package view
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/query"
|
||||
"github.com/zitadel/zitadel/internal/user/repository/view"
|
||||
"github.com/zitadel/zitadel/internal/user/repository/view/model"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -22,34 +20,6 @@ func (v *View) UserSessionsByAgentID(agentID, instanceID string) ([]*model.UserS
|
||||
return view.UserSessionsByAgentID(v.client, agentID, instanceID)
|
||||
}
|
||||
|
||||
func (v *View) PutUserSession(userSession *model.UserSessionView) error {
|
||||
return view.PutUserSession(v.Db, userSessionTable, userSession)
|
||||
}
|
||||
|
||||
func (v *View) DeleteUserSessions(userID, instanceID string) error {
|
||||
err := view.DeleteUserSessions(v.Db, userSessionTable, userID, instanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteInstanceUserSessions(instanceID string) error {
|
||||
err := view.DeleteInstanceUserSessions(v.Db, userSessionTable, instanceID)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) DeleteOrgUserSessions(event eventstore.Event) error {
|
||||
err := view.DeleteOrgUserSessions(v.Db, userSessionTable, event.Aggregate().InstanceID, event.Aggregate().ResourceOwner)
|
||||
if err != nil && !zerrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *View) GetLatestUserSessionSequence(ctx context.Context, instanceID string) (_ *query.CurrentState, err error) {
|
||||
q := &query.CurrentStateSearchQueries{
|
||||
Queries: make([]query.SearchQuery, 2),
|
||||
|
Reference in New Issue
Block a user