All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.arbeitsagentur.opdt.keycloak.cassandra.user.CassandraUserProvider Maven / Gradle / Ivy

/*
 * Copyright 2022 IT-Systemhaus der Bundesagentur fuer Arbeit
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.arbeitsagentur.opdt.keycloak.cassandra.user;

import static de.arbeitsagentur.opdt.keycloak.cassandra.user.CassandraUserAdapter.isUsernameCaseSensitive;
import static org.keycloak.common.util.StackUtil.getShortStackTrace;

import de.arbeitsagentur.opdt.keycloak.cassandra.AttributeTypes;
import de.arbeitsagentur.opdt.keycloak.cassandra.transaction.TransactionalProvider;
import de.arbeitsagentur.opdt.keycloak.cassandra.user.persistence.UserRepository;
import de.arbeitsagentur.opdt.keycloak.cassandra.user.persistence.entities.FederatedIdentity;
import de.arbeitsagentur.opdt.keycloak.cassandra.user.persistence.entities.User;
import de.arbeitsagentur.opdt.keycloak.cassandra.user.persistence.entities.UserConsent;
import java.time.Instant;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.extern.jbosslog.JBossLog;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.*;
import org.keycloak.models.utils.KeycloakModelUtils;

@JBossLog
public class CassandraUserProvider extends TransactionalProvider
    implements UserProvider {

  private final UserRepository userRepository;

  public CassandraUserProvider(KeycloakSession session, UserRepository userRepository) {
    super(session);
    this.userRepository = userRepository;
  }

  @Override
  protected CassandraUserAdapter createNewModel(RealmModel realm, User entity) {
    return createNewModel(realm, entity, () -> {});
  }

  private CassandraUserAdapter createNewModelWithRollback(RealmModel realm, User entity) {
    return createNewModel(
        realm,
        entity,
        () -> {
          userRepository.deleteUser(realm.getId(), entity.getId());
          models.remove(entity.getId());
        });
  }

  private CassandraUserAdapter createNewModel(
      RealmModel realm, User entity, Runnable rollbackAction) {
    return new CassandraUserAdapter(session, entity, realm, userRepository) {
      @Override
      public boolean checkEmailUniqueness(RealmModel realm, String email) {
        return getUserByEmail(realm, email) != null;
      }

      @Override
      public boolean checkUsernameUniqueness(RealmModel realm, String username) {
        return getUserByUsername(realm, username) != null;
      }

      @Override
      public SubjectCredentialManager credentialManager() {
        return new CassandraCredentialManager(session, realm, userRepository, this, entity);
      }

      @Override
      public void rollback() {
        rollbackAction.run();
      }
    };
  }

  @Override
  public UserModel addUser(RealmModel realm, String username) {
    return addUser(realm, null, username, true, true);
  }

  @Override
  public UserModel addUser(
      RealmModel realm,
      String id,
      String username,
      boolean addDefaultRoles,
      boolean addDefaultRequiredActions) {
    log.debugv("addUser realm={0} id={1} username={2}", realm, id, username);

    UserModel existingUser = getUserByUsername(realm, username);

    if (existingUser != null) {
      throw new ModelDuplicateException(
          "User with username '" + username + "' in realm " + realm.getName() + " already exists");
    }

    if (usernameEqualsExistingEmail(realm, username)) {
      throw new ModelDuplicateException(
          "User using username '"
              + username
              + "' as email-address already exists in realm "
              + realm.getName());
    }

    if (id != null && userRepository.findUserById(realm.getId(), id) != null) {
      throw new ModelDuplicateException("User exists: " + id);
    }

    User user =
        User.builder()
            .id(id == null ? KeycloakModelUtils.generateId() : id)
            .realmId(realm.getId())
            .createdTimestamp(Instant.now())
            .build();

    CassandraUserAdapter userModel =
        entityToAdapterFunc(realm, this::createNewModelWithRollback).apply(user);
    userModel.setUsername(username);

    if (addDefaultRoles) {
      if (realm.getDefaultRole() != null) {
        userModel.grantRole(realm.getDefaultRole());
      }

      // No need to check if user has group as it's new user
      realm.getDefaultGroupsStream().forEach(userModel::joinGroup);
    }

    if (addDefaultRequiredActions) {
      realm
          .getRequiredActionProvidersStream()
          .filter(RequiredActionProviderModel::isEnabled)
          .filter(RequiredActionProviderModel::isDefaultAction)
          .map(RequiredActionProviderModel::getAlias)
          .forEach(userModel::addRequiredAction);
    }

    userModel.commit(); // initial save
    return userModel;
  }

  private boolean usernameEqualsExistingEmail(RealmModel realm, String username) {
    if (!CassandraUserAdapter.isCheckForDuplicatesAcrossUsernameAndEmailEnabled(realm)) {
      return false;
    }

    if (realm.isDuplicateEmailsAllowed()) {
      return false;
    }

    return getUserByEmail(realm, username) != null;
  }

  @Override
  public void setNotBeforeForUser(RealmModel realm, UserModel user, int notBefore) {
    UserModel newlyLoaded = getByIdOrThrow(realm, user);
    newlyLoaded.setSingleAttribute(CassandraUserAdapter.NOT_BEFORE, String.valueOf(notBefore));
  }

  @Override
  public int getNotBeforeOfUser(RealmModel realm, UserModel user) {
    UserModel newlyLoaded = getByIdOrThrow(realm, user);
    String notBeforeAttribute = newlyLoaded.getFirstAttribute(CassandraUserAdapter.NOT_BEFORE);
    if (notBeforeAttribute == null) {
      return 0;
    }
    return Integer.parseInt(notBeforeAttribute);
  }

  @Override
  public UserModel getServiceAccount(ClientModel client) {
    UserModel userModel =
        models.values().stream()
            .filter(model -> model.getRealm().equals(client.getRealm()))
            .filter(model -> model.getServiceAccountClientLink() != null)
            .filter(model -> model.getServiceAccountClientLink().equals(client.getId()))
            .findFirst()
            .orElse(null);

    if (userModel != null) {
      return userModel;
    } else {
      User user =
          userRepository.findUserByServiceAccountLink(client.getRealm().getId(), client.getId());
      return entityToAdapterFunc(client.getRealm()).apply(user);
    }
  }

  @Override
  public void removeImportedUsers(RealmModel realm, String storageProviderId) {
    log.tracef("removeImportedUsers(%s, %s)%s", realm, storageProviderId, getShortStackTrace());
    userRepository
        .findUsersByFederationLink(realm.getId(), storageProviderId)
        .map(entityToAdapterFunc(realm))
        .forEach(u -> removeUser(realm, u));
  }

  @Override
  public void unlinkUsers(RealmModel realm, String storageProviderId) {
    log.tracef("unlinkUsers(%s, %s)%s", realm, storageProviderId, getShortStackTrace());
    userRepository
        .findUsersByFederationLink(realm.getId(), storageProviderId)
        .forEach(u -> userRepository.deleteFederationLinkSearchIndex(realm.getId(), u));
  }

  @Override
  public void addConsent(RealmModel realm, String userId, UserConsentModel consent) {
    log.debugv("addConsent({0}, {1}, {2})", realm, userId, consent);
    userRepository.createOrUpdateUserConsent(fromModel(realm, userId, consent));
  }

  @Override
  public UserConsentModel getConsentByClient(
      RealmModel realm, String userId, String clientInternalId) {
    log.debugv("getConsentByClient({0}, {1}, {2})", realm, userId, clientInternalId);
    UserConsent userConsent =
        userRepository.findUserConsent(realm.getId(), userId, clientInternalId);

    return toModel(realm, userConsent);
  }

  @Override
  public Stream getConsentsStream(RealmModel realm, String userId) {
    log.debugv("getConsentByClientStream({0}, {1})", realm, userId);

    return userRepository.findUserConsentsByUserId(realm.getId(), userId).stream()
        .map(userConsent -> toModel(realm, userConsent));
  }

  @Override
  public void updateConsent(RealmModel realm, String userId, UserConsentModel consent) {
    log.debugv("updateConsent({0}, {1}, {2})", realm, userId, consent);

    UserConsent userConsent =
        userRepository.findUserConsent(realm.getId(), userId, consent.getClient().getId());

    userConsent.setGrantedClientScopesId(
        consent.getGrantedClientScopes().stream()
            .map(ClientScopeModel::getId)
            .collect(Collectors.toSet()));
    userConsent.setLastUpdatedTimestamp(Instant.now());

    userRepository.createOrUpdateUserConsent(userConsent);
  }

  @Override
  public boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId) {
    log.debugv("revokeConsentForClient({0}, {1}, {2})", realm, userId, clientInternalId);

    return userRepository.deleteUserConsent(realm.getId(), userId, clientInternalId);
  }

  @Override
  public void addFederatedIdentity(
      RealmModel realm, UserModel user, FederatedIdentityModel socialLink) {
    updateFederatedIdentity(realm, user, socialLink);
  }

  private FederatedIdentity toFederatedIdentity(
      RealmModel realm, UserModel user, FederatedIdentityModel model) {
    return FederatedIdentity.builder()
        .userId(user.getId())
        .brokerUserId(model.getUserId())
        .brokerUserName(model.getUserName())
        .realmId(realm.getId())
        .identityProvider(model.getIdentityProvider())
        .token(model.getToken())
        .build();
  }

  private FederatedIdentityModel toModel(FederatedIdentity federatedIdentity) {
    if (federatedIdentity == null) {
      return null;
    }

    return new FederatedIdentityModel(
        federatedIdentity.getIdentityProvider(),
        federatedIdentity.getBrokerUserId(),
        federatedIdentity.getBrokerUserName(),
        federatedIdentity.getToken());
  }

  private UserConsentModel toModel(RealmModel realm, UserConsent userConsent) {
    if (userConsent == null) {
      return null;
    }

    ClientModel client = realm.getClientById(userConsent.getClientId());
    if (client == null) {
      throw new ModelException("Client with id " + userConsent.getClientId() + " is not available");
    }

    UserConsentModel model = new UserConsentModel(client);
    model.setCreatedDate(userConsent.getCreatedTimestamp().toEpochMilli());
    model.setLastUpdatedDate(userConsent.getLastUpdatedTimestamp().toEpochMilli());

    Set grantedClientScopesIds = userConsent.getGrantedClientScopesId();

    if (grantedClientScopesIds != null && !grantedClientScopesIds.isEmpty()) {
      grantedClientScopesIds.stream()
          .map(scopeId -> KeycloakModelUtils.findClientScopeById(realm, client, scopeId))
          .filter(Objects::nonNull)
          .forEach(model::addGrantedClientScope);
    }

    return model;
  }

  private UserConsent fromModel(RealmModel realm, String userId, UserConsentModel consentModel) {

    UserConsent userConsent = new UserConsent();
    userConsent.setRealmId(realm.getId());
    userConsent.setClientId(consentModel.getClient().getId());
    userConsent.setUserId(userId);

    consentModel.getGrantedClientScopes().stream()
        .map(ClientScopeModel::getId)
        .forEach(userConsent::addGrantedClientScopesId);

    return userConsent;
  }

  @Override
  public boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider) {
    return userRepository.deleteFederatedIdentity(user.getId(), socialProvider);
  }

  @Override
  public void updateFederatedIdentity(
      RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) {
    if (federatedUser == null || federatedUser.getId() == null) {
      return;
    }

    userRepository.createOrUpdateFederatedIdentity(
        toFederatedIdentity(realm, federatedUser, federatedIdentityModel));
  }

  @Override
  public Stream getFederatedIdentitiesStream(
      RealmModel realm, UserModel user) {
    return userRepository.findFederatedIdentities(user.getId()).stream().map(this::toModel);
  }

  @Override
  public FederatedIdentityModel getFederatedIdentity(
      RealmModel realm, UserModel user, String socialProvider) {
    FederatedIdentity federatedIdentity =
        userRepository.findFederatedIdentity(user.getId(), socialProvider);
    return toModel(federatedIdentity);
  }

  @Override
  public UserModel getUserByFederatedIdentity(RealmModel realm, FederatedIdentityModel socialLink) {
    FederatedIdentity federatedIdentity =
        userRepository.findFederatedIdentityByBrokerUserId(
            socialLink.getUserId(), socialLink.getIdentityProvider());

    if (federatedIdentity == null) {
      return null;
    }

    User userById = userRepository.findUserById(realm.getId(), federatedIdentity.getUserId());
    return entityToAdapterFunc(realm).apply(userById);
  }

  @Override
  public void grantToAllUsers(RealmModel realm, RoleModel role) {
    searchForUserStream(realm, "").forEach(u -> u.grantRole(role));
  }

  @Override
  public UserModel getUserById(RealmModel realm, String id) {
    log.debugv("getUserById realm={0} id={1}", realm, id);
    CassandraUserAdapter existingUser = models.get(id);
    if (existingUser != null) {
      return existingUser;
    }

    User userById = userRepository.findUserById(realm.getId(), id);
    return entityToAdapterFunc(realm).apply(userById);
  }

  @Override
  public UserModel getUserByUsername(RealmModel realm, String username) {
    log.debugv("getUserByUsername realm={0} username={1}", realm, username);
    UserModel modelUser =
        models.values().stream()
            .filter(model -> model.getRealm().equals(realm))
            .filter(model -> model.hasUsername(username))
            .map(model -> (UserModel) model)
            .findFirst()
            .orElse(null);

    if (modelUser == null) {
      User userFromDb =
          isUsernameCaseSensitive(realm)
              ? userRepository.findUserByUsername(realm.getId(), username)
              : userRepository.findUserByUsernameCaseInsensitive(
                  realm.getId(), KeycloakModelUtils.toLowerCaseSafe(username));

      return userFromDb == null || models.containsKey(userFromDb.getId())
          ? null
          : entityToAdapterFunc(realm).apply(userFromDb);
    } else {
      return modelUser;
    }
  }

  @Override
  public UserModel getUserByEmail(RealmModel realm, String email) {
    log.debugv("getUserByEmail realm={0} email={1}", realm, email);
    UserModel modelUser =
        models.values().stream()
            .filter(model -> model.getRealm().equals(realm))
            .filter(model -> model.getEmail() != null && model.getEmail().equals(email))
            .map(model -> (UserModel) model)
            .findFirst()
            .orElse(null);

    if (modelUser == null) {
      User userFromDb = userRepository.findUserByEmail(realm.getId(), email);

      return userFromDb == null || models.containsKey(userFromDb.getId())
          ? null
          : entityToAdapterFunc(realm).apply(userFromDb);
    } else {
      return modelUser;
    }
  }

  @Override
  public Stream searchForUserStream(
      RealmModel realm, String search, Integer firstResult, Integer maxResults) {
    log.tracef(
        "searchForUserStream(%s, %s, %d, %d)%s",
        realm, search, firstResult, maxResults, getShortStackTrace());
    Map attributes = new HashMap<>();
    attributes.put(UserModel.SEARCH, search);
    return searchForUserStream(realm, attributes, firstResult, maxResults);
  }

  @Override
  public Stream searchForUserStream(
      RealmModel realm, Map params, Integer firstResult, Integer maxResults) {
    log.debugf(
        "searchForUserStream(%s, %s, %d, %d)%s",
        realm, params, firstResult, maxResults, getShortStackTrace());

    int first = firstResult == null || firstResult < 0 ? 0 : firstResult;
    int resultCount = maxResults == null || maxResults < 0 ? Integer.MAX_VALUE : maxResults;

    boolean isExactSearch = Boolean.parseBoolean(params.getOrDefault(UserModel.EXACT, "false"));

    if (params.containsKey(UserModel.USERNAME) && isExactSearch) {
      return Stream.ofNullable(getUserByUsername(realm, params.get(UserModel.USERNAME)));
    } else if (params.containsKey(UserModel.EMAIL) && isExactSearch) {
      return Stream.ofNullable(getUserByEmail(realm, params.get(UserModel.EMAIL)));
    }

    Stream userModelStream =
        userRepository
            .findAllUsers()
            .filter(u -> u.getRealmId().equals(realm.getId()))
            .map(entityToAdapterFunc(realm));

    List> filtersList =
        params.entrySet().stream()
            .filter(entry -> !Objects.equals(entry.getKey(), UserModel.EXACT))
            .map(
                entry -> {
                  if (entry.getValue() == null) {
                    return (Predicate) (UserModel u) -> true;
                  }

                  BiFunction> makeAttributeComparator =
                      (attributeName, attributeValue) ->
                          isExactSearch
                              ? (Predicate)
                                  user ->
                                      Objects.equals(
                                          user.getFirstAttribute(attributeName), attributeValue)
                              : (Predicate)
                                  user ->
                                      user.getFirstAttribute(attributeName) != null
                                          && user.getFirstAttribute(attributeName)
                                              .contains(attributeValue);

                  BiFunction>
                      makeAttributeComparatorIgnoreCase =
                          (attributeName, attributeValue) ->
                              isExactSearch
                                  ? (Predicate)
                                      (user) ->
                                          user.getFirstAttribute(attributeName) != null
                                              && user.getFirstAttribute(attributeName)
                                                  .equalsIgnoreCase(attributeValue)
                                  : (Predicate)
                                      (user) ->
                                          user.getFirstAttribute(attributeName) != null
                                              && user.getFirstAttribute(attributeName)
                                                  .toLowerCase()
                                                  .contains(attributeValue.toLowerCase());

                  BiFunction> makeUsernameComparator =
                      isUsernameCaseSensitive(realm)
                          ? makeAttributeComparatorIgnoreCase
                          : makeAttributeComparator;

                  return switch (entry.getKey()) {
                    case UserModel.SEARCH ->
                        makeUsernameComparator
                            .apply(UserModel.USERNAME, entry.getValue())
                            .or(makeAttributeComparator.apply(UserModel.EMAIL, entry.getValue()))
                            .or(
                                makeAttributeComparator.apply(
                                    UserModel.FIRST_NAME, entry.getValue()))
                            .or(
                                makeAttributeComparator.apply(
                                    UserModel.LAST_NAME, entry.getValue()));
                    case UserModel.USERNAME ->
                        makeUsernameComparator.apply(UserModel.USERNAME, entry.getValue());
                    case UserModel.IDP_ALIAS ->
                        makeAttributeComparator.apply(UserModel.IDP_ALIAS, entry.getValue());
                    case UserModel.IDP_USER_ID ->
                        makeAttributeComparator.apply(UserModel.IDP_USER_ID, entry.getValue());
                    case UserModel.INCLUDE_SERVICE_ACCOUNT ->
                        (Predicate)
                            (UserModel u) ->
                                Boolean.parseBoolean(entry.getValue())
                                    || u.getServiceAccountClientLink() == null;
                    default -> makeAttributeComparator.apply(entry.getKey(), entry.getValue());
                  };
                })
            .toList();

    return userModelStream
        .filter(user -> filtersList.stream().allMatch(predicate -> predicate.test(user)))
        .skip(first)
        .limit(resultCount);
  }

  @Override
  public Stream getGroupMembersStream(
      RealmModel realm, GroupModel group, Integer firstResult, Integer maxResults) {
    log.debugf(
        "getGroupMembersStream realmId=%s groupName=%s firstResult=%d maxResults=%d",
        realm.getId(), group.getName(), firstResult, maxResults);

    return userRepository
        .findAllUsers()
        .filter(user -> user.getRealmId().equals(realm.getId()))
        .filter(user -> user.getGroupsMembership().contains(group.getId()))
        .skip(firstResult == null || firstResult < 0 ? 0 : firstResult)
        .limit(maxResults == null || maxResults < 0 ? Long.MAX_VALUE : maxResults)
        .map(entityToAdapterFunc(realm));
  }

  @Override
  public Stream searchForUserByUserAttributeStream(
      RealmModel realm, String attrName, String attrValue) {
    log.debugf("Search with attribute %s:%s", attrName, attrValue);

    if (attrName == null || attrValue == null) {
      return Stream.empty();
    }

    if (attrName.startsWith(AttributeTypes.INDEXED_ATTRIBUTE_PREFIX)) {
      return Stream.concat(
              models.values().stream()
                  .filter(model -> model.getRealm().equals(realm))
                  .filter(
                      model ->
                          model
                              .getAttributes()
                              .getOrDefault(attrName, Collections.emptyList())
                              .contains(attrValue))
                  .filter(u -> u.getServiceAccountClientLink() == null),
              userRepository
                  .findUsersByIndexedAttribute(realm.getId(), attrName, attrValue)
                  .map(entityToAdapterFunc(realm))
                  .filter(u -> u.getServiceAccountClientLink() == null)
                  .sorted(Comparator.comparing(UserModel::getUsername)))
          .map(UserModel.class::cast)
          .distinct();
    } else {
      return Stream.concat(
              models.values().stream()
                  .filter(model -> model.getRealm().equals(realm))
                  .filter(
                      model ->
                          model
                              .getAttributes()
                              .getOrDefault(attrName, Collections.emptyList())
                              .contains(attrValue))
                  .filter(u -> u.getServiceAccountClientLink() == null),
              userRepository
                  .findAllUsers()
                  .filter(u -> u.getRealmId().equals(realm.getId()))
                  .filter(u -> u.getAttribute(attrName).contains(attrValue))
                  .filter(u -> u.getServiceAccountClientLink() == null)
                  .map(entityToAdapterFunc(realm))
                  .sorted(Comparator.comparing(UserModel::getUsername)))
          .map(UserModel.class::cast)
          .distinct();
    }
  }

  @Override
  public int getUsersCount(RealmModel realm, boolean includeServiceAccount) {
    log.debugv(
        "getUsersCount realm={0} includeServiceAccount={1}", realm.getId(), includeServiceAccount);

    return (int) userRepository.countUsersByRealmId(realm.getId(), includeServiceAccount);
  }

  @Override
  public boolean removeUser(RealmModel realm, UserModel user) {
    userRepository.deleteUserConsentsByUserId(realm.getId(), user.getId());
    models.remove(user.getId());
    return ((CassandraUserAdapter) user).delete();
  }

  @Override
  public void preRemove(RealmModel realm) {
    log.tracef("preRemove[RealmModel](%s)%s", realm, getShortStackTrace());
    searchForUserStream(realm, "").forEach(u -> removeUser(realm, u));
    models.clear();
  }

  @Override
  public void preRemove(RealmModel realm, IdentityProviderModel provider) {
    String providerAlias = provider.getAlias();
    log.tracef(
        "preRemove[RealmModel realm, IdentityProviderModel provider](%s, %s)%s",
        realm, providerAlias, getShortStackTrace());

    userRepository
        .findUsersByFederationLink(realm.getId(), providerAlias)
        .forEach(
            u -> {
              userRepository.deleteFederatedIdentity(realm.getId(), providerAlias);
            });
  }

  @Override
  public void preRemove(RealmModel realm, RoleModel role) {
    // NOOP (delete/ignore ad-hoc when read)
  }

  @Override
  public void preRemove(RealmModel realm, GroupModel group) {
    // NOOP (delete/ignore ad-hoc when read)
  }

  @Override
  public void preRemove(RealmModel realm, ClientModel client) {
    String clientId = client.getId();
    String realmId = realm.getId();
    log.debugv("preRemove[ClientModel]({0}, {1})", realmId, clientId);

    List userConsents = userRepository.findUserConsentsByRealmId(realmId);
    if (userConsents != null && !userConsents.isEmpty()) {
      userConsents.forEach(
          userConsent -> {
            if (userConsent.getClientId().equals(clientId))
              userRepository.deleteUserConsent(realmId, userConsent.getUserId(), clientId);
          });
    }
  }

  @Override
  public void preRemove(ProtocolMapperModel protocolMapper) {
    // NOOP
  }

  @Override
  public void preRemove(ClientScopeModel clientScope) {
    String clientScopeId = clientScope.getId();
    String realmId = clientScope.getRealm().getId();
    log.debugv("preRemove[ClientScopeModel]({0})", clientScopeId);

    List userConsents = userRepository.findUserConsentsByRealmId(realmId);
    if (userConsents != null && !userConsents.isEmpty()) {
      userConsents.forEach(
          userConsent -> {
            if (userConsent.removeGrantedClientScopesId(clientScopeId)) {
              userConsent.setLastUpdatedTimestamp(Instant.now());
              userRepository.createOrUpdateUserConsent(userConsent);
            }
          });
    }
  }

  @Override
  public void preRemove(RealmModel realm, ComponentModel component) {
    // NOOP
  }

  private UserModel getByIdOrThrow(RealmModel realm, UserModel user) {
    UserModel userById = getUserById(realm, user.getId());
    if (userById == null) {
      throw new ModelException("Specified user doesn't exist.");
    }

    return userById;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy