mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 07:57: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:
@@ -1,98 +1,42 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/gorm"
|
||||
"context"
|
||||
"database/sql"
|
||||
_ "embed"
|
||||
"errors"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/zitadel/logging"
|
||||
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
usr_model "github.com/zitadel/zitadel/internal/user/model"
|
||||
"github.com/zitadel/zitadel/internal/user/repository/view/model"
|
||||
"github.com/zitadel/zitadel/internal/view/repository"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
|
||||
//go:embed user_by_id.sql
|
||||
var userByIDQuery string
|
||||
|
||||
func UserByID(db *gorm.DB, table, userID, instanceID string) (*model.UserView, error) {
|
||||
user := new(model.UserView)
|
||||
userIDQuery := &model.UserSearchQuery{
|
||||
Key: usr_model.UserSearchKeyUserID,
|
||||
Method: domain.SearchMethodEquals,
|
||||
Value: userID,
|
||||
}
|
||||
instanceIDQuery := &model.UserSearchQuery{
|
||||
Key: usr_model.UserSearchKeyInstanceID,
|
||||
Method: domain.SearchMethodEquals,
|
||||
Value: instanceID,
|
||||
}
|
||||
ownerRemovedQuery := &model.UserSearchQuery{
|
||||
Key: usr_model.UserSearchOwnerRemoved,
|
||||
Method: domain.SearchMethodEquals,
|
||||
Value: false,
|
||||
}
|
||||
query := repository.PrepareGetByQuery(table, userIDQuery, instanceIDQuery, ownerRemovedQuery)
|
||||
err := query(db, user)
|
||||
if zerrors.IsNotFound(err) {
|
||||
return nil, zerrors.ThrowNotFound(nil, "VIEW-sj8Sw", "Errors.User.NotFound")
|
||||
}
|
||||
user.SetEmptyUserType()
|
||||
return user, err
|
||||
}
|
||||
|
||||
func UsersByOrgID(db *gorm.DB, table, orgID, instanceID string) ([]*model.UserView, error) {
|
||||
users := make([]*model.UserView, 0)
|
||||
orgIDQuery := &usr_model.UserSearchQuery{
|
||||
Key: usr_model.UserSearchKeyResourceOwner,
|
||||
Method: domain.SearchMethodEquals,
|
||||
Value: orgID,
|
||||
query := db.Raw(userByIDQuery, instanceID, userID)
|
||||
|
||||
tx := query.BeginTx(context.Background(), &sql.TxOptions{ReadOnly: true})
|
||||
defer func() {
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
logging.OnError(err).Info("commit failed")
|
||||
}
|
||||
tx.RollbackUnlessCommitted()
|
||||
}()
|
||||
|
||||
err := tx.Scan(user).Error
|
||||
if err == nil {
|
||||
user.SetEmptyUserType()
|
||||
return user, nil
|
||||
}
|
||||
instanceIDQuery := &usr_model.UserSearchQuery{
|
||||
Key: usr_model.UserSearchKeyInstanceID,
|
||||
Method: domain.SearchMethodEquals,
|
||||
Value: instanceID,
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, zerrors.ThrowNotFound(err, "VIEW-hodc6", "object not found")
|
||||
}
|
||||
ownerRemovedQuery := &usr_model.UserSearchQuery{
|
||||
Key: usr_model.UserSearchOwnerRemoved,
|
||||
Method: domain.SearchMethodEquals,
|
||||
Value: false,
|
||||
}
|
||||
query := repository.PrepareSearchQuery(table, model.UserSearchRequest{
|
||||
Queries: []*usr_model.UserSearchQuery{orgIDQuery, instanceIDQuery, ownerRemovedQuery},
|
||||
})
|
||||
_, err := query(db, &users)
|
||||
return users, err
|
||||
}
|
||||
|
||||
func PutUsers(db *gorm.DB, table string, users ...*model.UserView) error {
|
||||
save := repository.PrepareBulkSave(table)
|
||||
u := make([]interface{}, len(users))
|
||||
for i, user := range users {
|
||||
u[i] = user
|
||||
}
|
||||
return save(db, u...)
|
||||
}
|
||||
|
||||
func PutUser(db *gorm.DB, table string, user *model.UserView) error {
|
||||
save := repository.PrepareSave(table)
|
||||
return save(db, user)
|
||||
}
|
||||
|
||||
func DeleteUser(db *gorm.DB, table, userID, instanceID string) error {
|
||||
delete := repository.PrepareDeleteByKeys(table,
|
||||
repository.Key{model.UserSearchKey(usr_model.UserSearchKeyUserID), userID},
|
||||
repository.Key{model.UserSearchKey(usr_model.UserSearchKeyInstanceID), instanceID},
|
||||
)
|
||||
return delete(db)
|
||||
}
|
||||
|
||||
func DeleteInstanceUsers(db *gorm.DB, table, instanceID string) error {
|
||||
delete := repository.PrepareDeleteByKey(table, model.UserSearchKey(usr_model.UserSearchKeyInstanceID), instanceID)
|
||||
return delete(db)
|
||||
}
|
||||
|
||||
func UpdateOrgOwnerRemovedUsers(db *gorm.DB, table, instanceID, aggID string) error {
|
||||
update := repository.PrepareUpdateByKeys(table,
|
||||
model.UserSearchKey(usr_model.UserSearchOwnerRemoved),
|
||||
true,
|
||||
repository.Key{Key: model.UserSearchKey(usr_model.UserSearchKeyInstanceID), Value: instanceID},
|
||||
repository.Key{Key: model.UserSearchKey(usr_model.UserSearchKeyResourceOwner), Value: aggID},
|
||||
)
|
||||
return update(db)
|
||||
logging.WithFields("table ", table).WithError(err).Warn("get from cache error")
|
||||
return nil, zerrors.ThrowInternal(err, "VIEW-qJBg9", "cache error")
|
||||
}
|
||||
|
Reference in New Issue
Block a user