Skip to content

Commit 5bb23eb

Browse files
authored
Optimize update of user attributes (keycloak#32907)
Closes keycloak#32906 Signed-off-by: Alexander Schwartz <[email protected]>
1 parent 021a2af commit 5bb23eb

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserAdapter.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.keycloak.models.cache.infinispan;
1919

20+
import org.keycloak.common.util.CollectionUtil;
2021
import org.keycloak.credential.CredentialModel;
2122
import org.keycloak.models.ClientModel;
2223
import org.keycloak.models.GroupModel;
@@ -40,6 +41,7 @@
4041
import java.util.Set;
4142
import java.util.concurrent.ConcurrentHashMap;
4243
import java.util.function.Supplier;
44+
import java.util.stream.Collectors;
4345
import java.util.stream.Stream;
4446

4547
/**
@@ -174,20 +176,39 @@ public void setEnabled(boolean enabled) {
174176

175177
@Override
176178
public void setSingleAttribute(String name, String value) {
177-
getDelegateForUpdate();
178179
if (UserModel.USERNAME.equals(name) || UserModel.EMAIL.equals(name)) {
179180
value = KeycloakModelUtils.toLowerCaseSafe(value);
180181
}
182+
if (updated == null) {
183+
Set<String> oldEntries = getAttributeStream(name).collect(Collectors.toSet());
184+
Set<String> newEntries = value != null ? Set.of(value) : Collections.emptySet();
185+
if (CollectionUtil.collectionEquals(oldEntries, newEntries)) {
186+
return;
187+
}
188+
}
189+
getDelegateForUpdate();
181190
updated.setSingleAttribute(name, value);
182191
}
183192

184193
@Override
185194
public void setAttribute(String name, List<String> values) {
186-
getDelegateForUpdate();
187195
if (UserModel.USERNAME.equals(name) || UserModel.EMAIL.equals(name)) {
188196
String lowerCasedFirstValue = KeycloakModelUtils.toLowerCaseSafe((values != null && values.size() > 0) ? values.get(0) : null);
189197
if (lowerCasedFirstValue != null) values = Collections.singletonList(lowerCasedFirstValue);
190198
}
199+
if (updated == null) {
200+
Set<String> oldEntries = getAttributeStream(name).collect(Collectors.toSet());
201+
Set<String> newEntries;
202+
if (values == null) {
203+
newEntries = new HashSet<>();
204+
} else {
205+
newEntries = new HashSet<>(values);
206+
}
207+
if (CollectionUtil.collectionEquals(oldEntries, newEntries)) {
208+
return;
209+
}
210+
}
211+
getDelegateForUpdate();
191212
updated.setAttribute(name, values);
192213
}
193214

model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import org.keycloak.common.Profile;
2121
import org.keycloak.common.Profile.Feature;
22+
import org.keycloak.common.util.CollectionUtil;
2223
import org.keycloak.common.util.MultivaluedHashMap;
2324
import org.keycloak.common.util.ObjectUtil;
2425
import org.keycloak.credential.UserCredentialManager;
@@ -51,10 +52,13 @@
5152
import org.keycloak.organization.OrganizationProvider;
5253

5354
import java.util.ArrayList;
55+
import java.util.HashSet;
5456
import java.util.Iterator;
5557
import java.util.List;
5658
import java.util.Map;
5759
import java.util.Objects;
60+
import java.util.Set;
61+
import java.util.stream.Collectors;
5862
import java.util.stream.Stream;
5963
import org.keycloak.representations.idm.MembershipType;
6064

@@ -138,6 +142,11 @@ public void setSingleAttribute(String name, String value) {
138142
if (value == null) {
139143
user.getAttributes().removeIf(a -> a.getName().equals(name));
140144
} else {
145+
Set<String> oldEntries = getAttributeStream(name).collect(Collectors.toSet());
146+
Set<String> newEntries = Set.of(value);
147+
if (CollectionUtil.collectionEquals(oldEntries, newEntries)) {
148+
return;
149+
}
141150
String firstExistingAttrId = null;
142151
List<UserAttributeEntity> toRemove = new ArrayList<>();
143152
for (UserAttributeEntity attr : user.getAttributes()) {
@@ -183,6 +192,18 @@ public void setAttribute(String name, List<String> values) {
183192
setUsername(valueToSet);
184193
return;
185194
}
195+
196+
Set<String> oldEntries = getAttributeStream(name).collect(Collectors.toSet());
197+
Set<String> newEntries;
198+
if (values == null) {
199+
newEntries = new HashSet<>();
200+
} else {
201+
newEntries = new HashSet<>(values);
202+
}
203+
if (CollectionUtil.collectionEquals(oldEntries, newEntries)) {
204+
return;
205+
}
206+
186207
// Remove all existing
187208
removeAttribute(name);
188209
if (values != null) {

0 commit comments

Comments
 (0)