/** Get configuration descriptions for all clients */
  @Path("per-client-config-description")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  @NoCache
  public Map<String, List<ConfigPropertyRepresentation>> getPerClientConfigDescription() {
    auth.requireAny();

    List<ProviderFactory> factories =
        session.getKeycloakSessionFactory().getProviderFactories(ClientAuthenticator.class);

    Map<String, List<ConfigPropertyRepresentation>> toReturn = new HashMap<>();
    for (ProviderFactory clientAuthenticatorFactory : factories) {
      String providerId = clientAuthenticatorFactory.getId();
      ConfigurableAuthenticatorFactory factory =
          CredentialHelper.getConfigurableAuthenticatorFactory(session, providerId);
      ClientAuthenticatorFactory clientAuthFactory = (ClientAuthenticatorFactory) factory;
      List<ProviderConfigProperty> perClientConfigProps =
          clientAuthFactory.getConfigPropertiesPerClient();
      List<ConfigPropertyRepresentation> result = new LinkedList<>();
      for (ProviderConfigProperty prop : perClientConfigProps) {
        ConfigPropertyRepresentation propRep = getConfigPropertyRep(prop);
        result.add(propRep);
      }

      toReturn.put(providerId, result);
    }

    return toReturn;
  }
  /**
   * Get unregistered required actions
   *
   * <p>Returns a list of unregistered required actions.
   */
  @Path("unregistered-required-actions")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  @NoCache
  public List<Map<String, String>> getUnregisteredRequiredActions() {
    auth.requireView();

    List<ProviderFactory> factories =
        session.getKeycloakSessionFactory().getProviderFactories(RequiredActionProvider.class);
    List<Map<String, String>> unregisteredList = new LinkedList<>();
    for (ProviderFactory factory : factories) {
      RequiredActionFactory requiredActionFactory = (RequiredActionFactory) factory;
      boolean found = false;
      for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
        if (model.getProviderId().equals(factory.getId())) {
          found = true;
          break;
        }
      }
      if (!found) {
        Map<String, String> data = new HashMap<>();
        data.put("name", requiredActionFactory.getDisplayText());
        data.put("providerId", requiredActionFactory.getId());
        unregisteredList.add(data);
      }
    }
    return unregisteredList;
  }
 protected <T> List<T> getCredentialProviders(RealmModel realm, Class<T> type) {
   List<T> list = new LinkedList<T>();
   for (ProviderFactory f :
       session.getKeycloakSessionFactory().getProviderFactories(CredentialProvider.class)) {
     if (!Types.supports(CredentialInputUpdater.class, f, CredentialProviderFactory.class))
       continue;
     list.add((T) session.getProvider(CredentialProvider.class, f.getId()));
   }
   return list;
 }
  public List<Map<String, Object>> buildProviderMetadata(List<ProviderFactory> factories) {
    List<Map<String, Object>> providers = new LinkedList<>();
    for (ProviderFactory factory : factories) {
      Map<String, Object> data = new HashMap<>();
      data.put("id", factory.getId());
      ConfigurableAuthenticatorFactory configured = (ConfigurableAuthenticatorFactory) factory;
      data.put("description", configured.getHelpText());
      data.put("displayName", configured.getDisplayType());

      providers.add(data);
    }
    return providers;
  }
  /**
   * Base path for importing clients under this realm.
   *
   * @return
   */
  @Path("client-description-converter")
  @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  public ClientRepresentation convertClientDescription(String description) {
    for (ProviderFactory<ClientDescriptionConverter> factory :
        session
            .getKeycloakSessionFactory()
            .getProviderFactories(ClientDescriptionConverter.class)) {
      if (((ClientDescriptionConverterFactory) factory).isSupported(description)) {
        return factory.create(session).convertToInternal(description);
      }
    }

    throw new BadRequestException("Unsupported format");
  }
  public static void updateUserFromRep(
      UserModel user,
      UserRepresentation rep,
      Set<String> attrsToRemove,
      RealmModel realm,
      KeycloakSession session) {
    if (realm.isEditUsernameAllowed()) {
      user.setUsername(rep.getUsername());
    }
    user.setEmail(rep.getEmail());
    user.setFirstName(rep.getFirstName());
    user.setLastName(rep.getLastName());

    if (rep.isEnabled() != null) user.setEnabled(rep.isEnabled());
    if (rep.isTotp() != null) user.setOtpEnabled(rep.isTotp());
    if (rep.isEmailVerified() != null) user.setEmailVerified(rep.isEmailVerified());

    List<String> reqActions = rep.getRequiredActions();

    if (reqActions != null) {
      Set<String> allActions = new HashSet<>();
      for (ProviderFactory factory :
          session.getKeycloakSessionFactory().getProviderFactories(RequiredActionProvider.class)) {
        allActions.add(factory.getId());
      }
      for (String action : allActions) {
        if (reqActions.contains(action)) {
          user.addRequiredAction(action);
        } else {
          user.removeRequiredAction(action);
        }
      }
    }

    if (rep.getAttributesAsListValues() != null) {
      for (Map.Entry<String, List<String>> attr : rep.getAttributesAsListValues().entrySet()) {
        user.setAttribute(attr.getKey(), attr.getValue());
      }

      for (String attr : attrsToRemove) {
        user.removeAttribute(attr);
      }
    }
  }
  /**
   * Base path for importing clients under this realm.
   *
   * @return
   */
  @Path("client-description-converter")
  @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  public ClientRepresentation convertClientDescription(String description) {
    auth.init(Resource.CLIENT).requireManage();

    if (realm == null) {
      throw new NotFoundException("Realm not found.");
    }

    for (ProviderFactory<ClientDescriptionConverter> factory :
        session
            .getKeycloakSessionFactory()
            .getProviderFactories(ClientDescriptionConverter.class)) {
      if (((ClientDescriptionConverterFactory) factory).isSupported(description)) {
        return factory.create(session).convertToInternal(description);
      }
    }

    throw new BadRequestException("Unsupported format");
  }