Add MapKeycloakTransaction.exists methods

This commit is contained in:
Martin Kanis 2023-01-30 11:48:31 +01:00 committed by Michal Hajas
parent 88a249ea0d
commit a912558d29
17 changed files with 88 additions and 18 deletions

View file

@ -205,6 +205,14 @@ public class HotRodMapStorage<K, E extends AbstractHotRodEntity, V extends Abstr
return query.executeStatement();
}
@Override
public boolean exists(String key) {
Objects.requireNonNull(key, "Key must be non-null");
K k = keyConverter.fromStringSafe(key);
return remoteCache.containsKey(k);
}
public IckleQueryMapModelCriteriaBuilder<E, M> createCriteriaBuilder() {
return new IckleQueryMapModelCriteriaBuilder<>(storedEntityDescriptor.getEntityTypeClass());
}

View file

@ -105,7 +105,7 @@ public class MapRootAuthenticationSessionProvider implements AuthenticationSessi
int authSessionLifespanSeconds = getAuthSessionLifespan(realm);
entity.setExpiration(timestamp + TimeAdapter.fromSecondsToMilliseconds(authSessionLifespanSeconds));
if (id != null && tx.read(id) != null) {
if (id != null && tx.exists(id)) {
throw new ModelDuplicateException("Root authentication session exists: " + entity.getId());
}

View file

@ -110,7 +110,7 @@ public class MapPermissionTicketStore implements PermissionTicketStore {
mcb = mcb.compare(SearchableFields.SCOPE_ID, Operator.EQ, scope.getId());
}
if (tx.getCount(withCriteria(mcb)) > 0) {
if (tx.exists(withCriteria(mcb))) {
throw new ModelDuplicateException("Permission ticket for resource server: '" + resourceServer.getId()
+ ", Resource: " + resource + ", owner: " + owner + ", scopeId: " + scope + " already exists.");
}

View file

@ -84,7 +84,7 @@ public class MapPolicyStore implements PolicyStore {
DefaultModelCriteria<Policy> mcb = forRealmAndResourceServer(realm, resourceServer)
.compare(SearchableFields.NAME, Operator.EQ, representation.getName());
if (tx.getCount(withCriteria(mcb)) > 0) {
if (tx.exists(withCriteria(mcb))) {
throw new ModelDuplicateException("Policy with name '" + representation.getName() + "' for " + resourceServer.getId() + " already exists");
}

View file

@ -85,7 +85,7 @@ public class MapResourceStore implements ResourceStore {
.compare(SearchableFields.NAME, Operator.EQ, name)
.compare(SearchableFields.OWNER, Operator.EQ, owner);
if (tx.getCount(withCriteria(mcb)) > 0) {
if (tx.exists(withCriteria(mcb))) {
throw new ModelDuplicateException("Resource with name '" + name + "' for " + resourceServer.getId() + " already exists for request owner " + owner);
}

View file

@ -81,7 +81,7 @@ public class MapScopeStore implements ScopeStore {
DefaultModelCriteria<Scope> mcb = forRealmAndResourceServer(realm, resourceServer)
.compare(SearchableFields.NAME, Operator.EQ, name);
if (tx.getCount(withCriteria(mcb)) > 0) {
if (tx.exists(withCriteria(mcb))) {
throw new ModelDuplicateException("Scope with name '" + name + "' for " + resourceServer.getId() + " already exists");
}

View file

@ -148,7 +148,7 @@ public class MapClientProvider implements ClientProvider {
public ClientModel addClient(RealmModel realm, String id, String clientId) {
LOG.tracef("addClient(%s, %s, %s)%s", realm, id, clientId, getShortStackTrace());
if (id != null && tx.read(id) != null) {
if (id != null && tx.exists(id)) {
throw new ModelDuplicateException("Client with same id exists: " + id);
}
if (clientId != null && getClientByClientId(realm, clientId) != null) {

View file

@ -84,11 +84,11 @@ public class MapClientScopeProvider implements ClientScopeProvider {
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
.compare(SearchableFields.NAME, Operator.EQ, name);
if (tx.getCount(withCriteria(mcb)) > 0) {
if (tx.exists(withCriteria(mcb))) {
throw new ModelDuplicateException("Client scope with name '" + name + "' in realm " + realm.getName());
}
if (id != null && tx.read(id) != null) {
if (id != null && tx.exists(id)) {
throw new ModelDuplicateException("Client scope exists: " + id);
}

View file

@ -63,7 +63,7 @@ public class MapEventStoreProvider implements EventStoreProvider {
LOG.tracef("onEvent(%s)%s", event, getShortStackTrace());
String id = event.getId();
if (id != null && authEventsTX.read(id) != null) {
if (id != null && authEventsTX.exists(id)) {
throw new ModelDuplicateException("Event already exists: " + id);
}
@ -132,7 +132,7 @@ public class MapEventStoreProvider implements EventStoreProvider {
public void onEvent(AdminEvent event, boolean includeRepresentation) {
LOG.tracef("clear(%s, %s)%s", event, includeRepresentation, getShortStackTrace());
String id = event.getId();
if (id != null && authEventsTX.read(id) != null) {
if (id != null && authEventsTX.exists(id)) {
throw new ModelDuplicateException("Event already exists: " + id);
}
String realmId = event.getRealmId();

View file

@ -218,7 +218,7 @@ public class MapGroupProvider implements GroupProvider {
mcb.compare(SearchableFields.PARENT_ID, Operator.NOT_EXISTS) :
mcb.compare(SearchableFields.PARENT_ID, Operator.EQ, toParent.getId());
if (tx.getCount(withCriteria(mcb)) > 0) {
if (tx.exists(withCriteria(mcb))) {
throw new ModelDuplicateException("Group with name '" + name + "' in realm " + realm.getName() + " already exists for requested parent" );
}
@ -227,7 +227,7 @@ public class MapGroupProvider implements GroupProvider {
entity.setRealmId(realm.getId());
entity.setName(name);
entity.setParentId(toParent == null ? null : toParent.getId());
if (id != null && tx.read(id) != null) {
if (id != null && tx.exists(id)) {
throw new ModelDuplicateException("Group exists: " + id);
}
entity = tx.create(entity);

View file

@ -72,7 +72,7 @@ public class MapRealmProvider implements RealmProvider {
throw new ModelDuplicateException("Realm with given name exists: " + name);
}
if (id != null && tx.read(id) != null) {
if (id != null && tx.exists(id)) {
throw new ModelDuplicateException("Realm exists: " + id);
}

View file

@ -71,7 +71,7 @@ public class MapRoleProvider implements RoleProvider {
entity.setRealmId(realm.getId());
entity.setName(name);
entity.setClientRole(false);
if (entity.getId() != null && tx.read(entity.getId()) != null) {
if (entity.getId() != null && tx.exists(entity.getId())) {
throw new ModelDuplicateException("Role exists: " + id);
}
entity = tx.create(entity);
@ -129,7 +129,7 @@ public class MapRoleProvider implements RoleProvider {
entity.setName(name);
entity.setClientRole(true);
entity.setClientId(client.getId());
if (entity.getId() != null && tx.read(entity.getId()) != null) {
if (entity.getId() != null && tx.exists(entity.getId())) {
throw new ModelDuplicateException("Role exists: " + id);
}
entity = tx.create(entity);

View file

@ -94,4 +94,27 @@ public interface MapKeycloakTransaction<V extends AbstractEntity, M> extends Key
*/
long delete(QueryParameters<M> queryParameters);
/**
* Returns {@code true} if the object with the given {@code key} exists in the underlying storage with respect to changes done
* in current transaction. {@code false} otherwise.
*
* @param key Key of the object. Must not be {@code null}.
* @return See description
* @throws NullPointerException if the {@code key} is {@code null}
*/
default boolean exists(String key) {
return read(key) != null;
}
/**
* Returns {@code true} if at least one object is satisfying given {@code criteria} from the underlying storage with respect to changes done
* in current transaction. {@code false} otherwise.
* The criteria are specified in the given criteria builder based on model properties.
*
* @param queryParameters parameters for the query
* @return See description
*/
default boolean exists(QueryParameters<M> queryParameters) {
return getCount(queryParameters) > 0;
}
}

View file

@ -79,4 +79,26 @@ public interface ConcurrentHashMapCrudOperations<V extends AbstractEntity & Upda
* @return Number of objects. Never returns {@code null}.
*/
long getCount(QueryParameters<M> queryParameters);
/**
* Returns {@code true} if the object with the given {@code key} exists in the storage. {@code false} otherwise.
*
* @param key Key of the object. Must not be {@code null}.
* @return See description
* @throws NullPointerException if the {@code key} is {@code null}
*/
default boolean exists(String key) {
return read(key) != null;
}
/**
* Returns {@code true} if at least one object is satisfying given {@code criteria} from the storage. {@code false} otherwise.
* The criteria are specified in the given criteria builder based on model properties.
*
* @param queryParameters parameters for the query
* @return See description
*/
default boolean exists(QueryParameters<M> queryParameters) {
return getCount(queryParameters) > 0;
}
}

View file

@ -277,6 +277,23 @@ public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity &
return res + bdo.getCount();
}
@Override
public boolean exists(String key) {
if (tasks.containsKey(key)) {
MapTaskWithValue o = tasks.get(key);
return o.getValue() != null;
}
// Check if there is a bulk delete operation in which case read the full entity
for (MapTaskWithValue val : tasks.values()) {
if (val instanceof ConcurrentHashMapKeycloakTransaction.BulkDeleteOperation) {
return read(key) != null;
}
}
return map.exists(key);
}
private Stream<V> createdValuesStream(Predicate<? super K> keyFilter, Predicate<? super V> entityFilter) {
return this.tasks.entrySet().stream()
.filter(me -> keyFilter.test(keyConverter.fromStringSafe(me.getKey())))

View file

@ -336,11 +336,11 @@ public class MapUserProvider implements UserProvider {
SearchableFields.USERNAME :
SearchableFields.USERNAME_CASE_INSENSITIVE, Operator.EQ, username);
if (tx.getCount(withCriteria(mcb)) > 0) {
if (tx.exists(withCriteria(mcb))) {
throw new ModelDuplicateException("User with username '" + username + "' in realm " + realm.getName() + " already exists" );
}
if (id != null && tx.read(id) != null) {
if (id != null && tx.exists(id)) {
throw new ModelDuplicateException("User exists: " + id);
}

View file

@ -158,7 +158,7 @@ public class MapUserSessionProvider implements UserSessionProvider {
}
transientUserSessions.put(entity.getId(), entity);
} else {
if (id != null && userSessionTx.read(id) != null) {
if (id != null && userSessionTx.exists(id)) {
throw new ModelDuplicateException("User session exists: " + id);
}
entity = userSessionTx.create(entity);