fix: user metadata check if already existing (#10430)

# Which Problems Are Solved

If metadata is set, there is no check if it even has to be changed.

# How the Problems Are Solved

Check if metadata already exists, and push no event if nothing changed.

# Additional Changes

Original changes under #10246 amendet for v3.3.x, removed permission
check
Fixes #10434

# Additional Context

none

---------

Co-authored-by: Gayathri Vijayan <66356931+grvijayan@users.noreply.github.com>
Co-authored-by: Marco A. <marco@zitadel.com>
Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
This commit is contained in:
Stefan Benz
2025-08-11 14:38:32 +02:00
committed by GitHub
parent 0c5dbe1d2f
commit c22b5aa8e8
28 changed files with 921 additions and 594 deletions

View File

@@ -1,6 +1,7 @@
package command
import (
"bytes"
"context"
"github.com/zitadel/zitadel/internal/domain"
@@ -14,12 +15,21 @@ func (c *Commands) SetUserMetadata(ctx context.Context, metadata *domain.Metadat
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
err = c.checkUserExists(ctx, userID, resourceOwner)
userResourceOwner, err := c.checkUserExists(ctx, userID, resourceOwner)
if err != nil {
return nil, err
}
setMetadata, err := c.getUserMetadataModelByID(ctx, userID, userResourceOwner, metadata.Key)
if err != nil {
return nil, err
}
setMetadata := NewUserMetadataWriteModel(userID, resourceOwner, metadata.Key)
userAgg := UserAggregateFromWriteModel(&setMetadata.WriteModel)
// return if no change in the metadata
if bytes.Equal(setMetadata.Value, metadata.Value) {
return writeModelToUserMetadata(setMetadata), nil
}
event, err := c.setUserMetadata(ctx, userAgg, metadata)
if err != nil {
return nil, err
@@ -40,20 +50,31 @@ func (c *Commands) BulkSetUserMetadata(ctx context.Context, userID, resourceOwne
if len(metadatas) == 0 {
return nil, zerrors.ThrowPreconditionFailed(nil, "META-9mm2d", "Errors.Metadata.NoData")
}
err = c.checkUserExists(ctx, userID, resourceOwner)
userResourceOwner, err := c.checkUserExists(ctx, userID, resourceOwner)
if err != nil {
return nil, err
}
events := make([]eventstore.Command, len(metadatas))
setMetadata := NewUserMetadataListWriteModel(userID, resourceOwner)
events := make([]eventstore.Command, 0)
setMetadata, err := c.getUserMetadataListModelByID(ctx, userID, userResourceOwner)
if err != nil {
return nil, err
}
userAgg := UserAggregateFromWriteModel(&setMetadata.WriteModel)
for i, data := range metadatas {
for _, data := range metadatas {
// if no change to metadata no event has to be pushed
if existingValue, ok := setMetadata.metadataList[data.Key]; ok && bytes.Equal(existingValue, data.Value) {
continue
}
event, err := c.setUserMetadata(ctx, userAgg, data)
if err != nil {
return nil, err
}
events[i] = event
events = append(events, event)
}
// no changes for the metadata
if len(events) == 0 {
return writeModelToObjectDetails(&setMetadata.WriteModel), nil
}
pushedEvents, err := c.eventstore.Push(ctx, events...)
@@ -84,11 +105,12 @@ func (c *Commands) RemoveUserMetadata(ctx context.Context, metadataKey, userID,
if metadataKey == "" {
return nil, zerrors.ThrowInvalidArgument(nil, "META-2n0fs", "Errors.Metadata.Invalid")
}
err = c.checkUserExists(ctx, userID, resourceOwner)
userResourceOwner, err := c.checkUserExists(ctx, userID, resourceOwner)
if err != nil {
return nil, err
}
removeMetadata, err := c.getUserMetadataModelByID(ctx, userID, resourceOwner, metadataKey)
removeMetadata, err := c.getUserMetadataModelByID(ctx, userID, userResourceOwner, metadataKey)
if err != nil {
return nil, err
}
@@ -116,13 +138,13 @@ func (c *Commands) BulkRemoveUserMetadata(ctx context.Context, userID, resourceO
if len(metadataKeys) == 0 {
return nil, zerrors.ThrowPreconditionFailed(nil, "META-9mm2d", "Errors.Metadata.NoData")
}
err = c.checkUserExists(ctx, userID, resourceOwner)
userResourceOwner, err := c.checkUserExists(ctx, userID, resourceOwner)
if err != nil {
return nil, err
}
events := make([]eventstore.Command, len(metadataKeys))
removeMetadata, err := c.getUserMetadataListModelByID(ctx, userID, resourceOwner)
removeMetadata, err := c.getUserMetadataListModelByID(ctx, userID, userResourceOwner)
if err != nil {
return nil, err
}
@@ -153,24 +175,6 @@ func (c *Commands) BulkRemoveUserMetadata(ctx context.Context, userID, resourceO
return writeModelToObjectDetails(&removeMetadata.WriteModel), nil
}
func (c *Commands) removeUserMetadataFromOrg(ctx context.Context, resourceOwner string) ([]eventstore.Command, error) {
existingUserMetadata, err := c.getUserMetadataByOrgListModelByID(ctx, resourceOwner)
if err != nil {
return nil, err
}
if len(existingUserMetadata.UserMetadata) == 0 {
return nil, nil
}
events := make([]eventstore.Command, 0)
for key, value := range existingUserMetadata.UserMetadata {
if len(value) == 0 {
continue
}
events = append(events, user.NewMetadataRemovedAllEvent(ctx, &user.NewAggregate(key, resourceOwner).Aggregate))
}
return events, nil
}
func (c *Commands) removeUserMetadata(ctx context.Context, userAgg *eventstore.Aggregate, metadataKey string) (command eventstore.Command, err error) {
command = user.NewMetadataRemovedEvent(
ctx,
@@ -197,12 +201,3 @@ func (c *Commands) getUserMetadataListModelByID(ctx context.Context, userID, res
}
return userMetadataWriteModel, nil
}
func (c *Commands) getUserMetadataByOrgListModelByID(ctx context.Context, resourceOwner string) (*UserMetadataByOrgListWriteModel, error) {
userMetadataWriteModel := NewUserMetadataByOrgListWriteModel(resourceOwner)
err := c.eventstore.FilterToQueryReducer(ctx, userMetadataWriteModel)
if err != nil {
return nil, err
}
return userMetadataWriteModel, nil
}