From ee1ddfe7a5ffb380f8cd6a2437ae60104096cb18 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Wed, 18 Jul 2018 12:38:56 +0200
Subject: [PATCH] rest api provides information about ldap connection with user
 account

---
 .../mapviewer/api/users/UserRestImpl.java     | 1237 +++++++++--------
 .../mapviewer/services/impl/UserService.java  |   25 +
 .../services/interfaces/IUserService.java     |  375 ++---
 3 files changed, 842 insertions(+), 795 deletions(-)

diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
index de838df959..51792ae019 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/users/UserRestImpl.java
@@ -1,609 +1,628 @@
-package lcsb.mapviewer.api.users;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.apache.log4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.MultiValueMap;
-
-import lcsb.mapviewer.api.BaseRestImpl;
-import lcsb.mapviewer.api.ObjectNotFoundException;
-import lcsb.mapviewer.api.QueryException;
-import lcsb.mapviewer.common.exception.InvalidArgumentException;
-import lcsb.mapviewer.model.Project;
-import lcsb.mapviewer.model.map.MiriamType;
-import lcsb.mapviewer.model.user.BasicPrivilege;
-import lcsb.mapviewer.model.user.ConfigurationOption;
-import lcsb.mapviewer.model.user.ObjectPrivilege;
-import lcsb.mapviewer.model.user.PrivilegeType;
-import lcsb.mapviewer.model.user.User;
-import lcsb.mapviewer.model.user.UserAnnotationSchema;
-import lcsb.mapviewer.model.user.UserAnnotatorsParam;
-import lcsb.mapviewer.model.user.UserClassAnnotators;
-import lcsb.mapviewer.model.user.UserClassRequiredAnnotations;
-import lcsb.mapviewer.model.user.UserClassValidAnnotations;
-import lcsb.mapviewer.model.user.UserGuiPreference;
-import lcsb.mapviewer.services.SecurityException;
-import lcsb.mapviewer.services.interfaces.IConfigurationService;
-import lcsb.mapviewer.services.interfaces.ILayoutService;
-
-@Transactional(value = "txManager")
-public class UserRestImpl extends BaseRestImpl {
-
-  /**
-   * Default class logger.
-   */
-  @SuppressWarnings("unused")
-  private Logger logger = Logger.getLogger(UserRestImpl.class);
-
-  @Autowired
-  private ILayoutService layoutService;
-
-  @Autowired
-  private IConfigurationService configurationService;
-
-  public Map<String, Object> getUser(String token, String login, String columns)
-      throws SecurityException, ObjectNotFoundException {
-    User ownUserData = getUserService().getUserByToken(token);
-
-    Set<String> columnSet = createUserColumnSet(columns);
-
-    boolean isAdmin = getUserService().userHasPrivilege(ownUserData, PrivilegeType.USER_MANAGEMENT);
-
-    if (ownUserData.getLogin().equals(login) || isAdmin) {
-      User user = getUserService().getUserByLogin(login);
-      if (user == null) {
-        throw new ObjectNotFoundException("User doesn't exist");
-      }
-      return prepareUse(user, columnSet, isAdmin);
-    } else {
-      throw new SecurityException("You cannot access data of the user with given id");
-    }
-  }
-
-  private Set<String> createUserColumnSet(String columns) {
-    Set<String> columnsSet = new HashSet<>();
-    if (columns.equals("")) {
-      columnsSet.add("id");
-      columnsSet.add("login");
-      columnsSet.add("name");
-      columnsSet.add("surname");
-      columnsSet.add("email");
-      columnsSet.add("minColor");
-      columnsSet.add("maxColor");
-      columnsSet.add("neutralColor");
-      columnsSet.add("simpleColor");
-      columnsSet.add("removed");
-      columnsSet.add("privileges");
-      columnsSet.add("termsOfUseConsent");
-    } else {
-      for (String str : columns.split(",")) {
-        columnsSet.add(str);
-      }
-    }
-    return columnsSet;
-  }
-
-  private Map<String, Object> prepareUse(User user, Set<String> columnsSet, boolean admin) {
-    Map<String, Object> result = new TreeMap<>();
-    for (String string : columnsSet) {
-      String column = string.toLowerCase();
-      Object value = null;
-      if (column.equals("id") || column.equals("idobject")) {
-        value = user.getId();
-      } else if (column.equals("name")) {
-        value = user.getName();
-      } else if (column.equals("surname")) {
-        value = user.getSurname();
-      } else if (column.equals("login")) {
-        value = user.getLogin();
-      } else if (column.equals("email")) {
-        value = user.getEmail();
-      } else if (column.equals("mincolor")) {
-        value = user.getMinColor();
-      } else if (column.equals("maxcolor")) {
-        value = user.getMaxColor();
-      } else if (column.equals("neutralcolor")) {
-        value = user.getNeutralColor();
-      } else if (column.equals("simplecolor")) {
-        value = user.getSimpleColor();
-      } else if (column.equals("removed")) {
-        value = user.isRemoved();
-      } else if (column.equals("termsofuseconsent")) {
-        value = user.isTermsOfUseConsent();
-      } else if (column.equals("privileges") && admin) {
-        value = preparePrivileges(user);
-      } else if (column.equals("preferences")) {
-        value = preparePreferences(user);
-      } else {
-        value = "Unknown column";
-      }
-      result.put(string, value);
-    }
-    return result;
-  }
-
-  private Map<String, Object> preparePreferences(User user) {
-    Map<String, Object> result = new TreeMap<>();
-    UserAnnotationSchema schema = getProjectService().prepareUserAnnotationSchema(user);
-    result.put("project-upload", prepareProjectUploadPreferences(schema));
-    result.put("element-annotators", prepareElementAnnotators(schema.getClassAnnotators()));
-    result.put("element-required-annotations", prepareRequiredAnnotations(schema.getClassRequiredAnnotators()));
-    result.put("element-valid-annotations", prepareValidAnnotations(schema.getClassValidAnnotators()));
-    result.put("annotators-parameters", prepareAnnotatorsParams(schema.getAnnotatorsParams()));
-    result.put("gui-preferences", prepareGuiPreferences(schema.getGuiPreferences()));
-    return result;
-  }
-
-  Map<String, Object> prepareGuiPreferences(Set<UserGuiPreference> guiPreferences) {
-    Map<String, Object> result = new TreeMap<>();
-    for (UserGuiPreference userGuiPreference : guiPreferences) {
-      result.put(userGuiPreference.getKey(), userGuiPreference.getValue());
-    }
-    return result;
-  }
-
-  /**
-   * Prepares annotator parameters in the form of a map having annotators class
-   * names as keys and map of name:value pairs of given annotator as values.
-   *
-   * @param annotatorsParams
-   * @return
-   */
-  private Map<String, Object> prepareAnnotatorsParams(List<UserAnnotatorsParam> annotatorsParams) {
-    Map<String, Object> result = new TreeMap<>();
-    for (UserAnnotatorsParam param : annotatorsParams) {
-      String className = param.getAnnotatorClassName().getName();
-      Map<String, String> annotatorParams = (Map<String, String>) result.get(className);
-      if (annotatorParams == null) {
-        annotatorParams = new TreeMap<>();
-        result.put(className, annotatorParams);
-      }
-      annotatorParams.put(param.getParamName(), param.getParamValue());
-    }
-    return result;
-  }
-
-  private Map<String, Object> prepareValidAnnotations(List<UserClassValidAnnotations> classValidAnnotators) {
-    Map<String, Object> result = new TreeMap<>();
-    for (UserClassValidAnnotations userClassAnnotators : classValidAnnotators) {
-      result.put(userClassAnnotators.getClassName(), new ArrayList<>(userClassAnnotators.getValidMiriamTypes()));
-    }
-    return result;
-  }
-
-  private void updateValidAnnotations(UserAnnotationSchema schema, Map<String, Object> data) {
-    for (String key : data.keySet()) {
-      UserClassValidAnnotations annotator = null;
-      for (UserClassValidAnnotations userClassAnnotators : schema.getClassValidAnnotators()) {
-        if (userClassAnnotators.getClassName().equals(key)) {
-          annotator = userClassAnnotators;
-        }
-      }
-      if (annotator == null) {
-        annotator = new UserClassValidAnnotations();
-        annotator.setClassName(key);
-        schema.addClassValidAnnotations(annotator);
-      }
-      annotator.getValidMiriamTypes().clear();
-      for (Object row : (List<?>) data.get(key)) {
-        annotator.getValidMiriamTypes().add(MiriamType.valueOf((String) row));
-      }
-    }
-  }
-
-  private void updateAnnotatorsParams(UserAnnotationSchema schema, Map<String, Object> data) throws QueryException {
-    for (String annotatorClassname : data.keySet()) {
-      Map<String, Object> nameValueS = (Map<String, Object>) data.get(annotatorClassname);
-      for (String name : nameValueS.keySet()) {
-        String value = (String) nameValueS.get(name);
-        try {
-          UserAnnotatorsParam param = new UserAnnotatorsParam(Class.forName(annotatorClassname), name, value);
-          schema.addAnnotatorParam(param);
-        } catch (ClassNotFoundException e) {
-          throw new QueryException("Unknown annotator class name: " + annotatorClassname);
-        }
-      }
-    }
-  }
-
-  private void updateGuiPreferences(UserAnnotationSchema schema, Map<String, Object> data) throws QueryException {
-    for (String key : data.keySet()) {
-      Object object = data.get(key);
-      String value = "";
-      if (object instanceof Integer) {
-        value = object + "";
-      } else if (object instanceof String) {
-        value = (String) data.get(key);
-      } else {
-        throw new InvalidArgumentException("Invalid value class: " + value);
-      }
-      schema.setGuiPreference(key, value);
-    }
-  }
-
-  private Map<String, Object> prepareRequiredAnnotations(List<UserClassRequiredAnnotations> classRequiredAnnotators) {
-    Map<String, Object> result = new TreeMap<>();
-    for (UserClassRequiredAnnotations requiredAnnotations : classRequiredAnnotators) {
-      Map<String, Object> row = new TreeMap<>();
-      row.put("require-at-least-one", requiredAnnotations.getRequireAtLeastOneAnnotation());
-      List<String> miriamTypes = new ArrayList<>();
-
-      for (MiriamType mt : requiredAnnotations.getRequiredMiriamTypes()) {
-        miriamTypes.add(mt.name());
-      }
-      row.put("annotation-list", miriamTypes);
-      result.put(requiredAnnotations.getClassName(), row);
-    }
-    return result;
-  }
-
-  private void updateRequiredAnnotations(UserAnnotationSchema schema, Map<String, Object> data) throws QueryException {
-    for (String key : data.keySet()) {
-      UserClassRequiredAnnotations annotator = null;
-      for (UserClassRequiredAnnotations userClassAnnotators : schema.getClassRequiredAnnotators()) {
-        if (userClassAnnotators.getClassName().equals(key)) {
-          annotator = userClassAnnotators;
-        }
-      }
-      if (annotator == null) {
-        annotator = new UserClassRequiredAnnotations();
-        annotator.setClassName(key);
-        schema.addClassRequiredAnnotations(annotator);
-      }
-      updateAnnotator(annotator, (Map<String, Object>) data.get(key));
-    }
-  }
-
-  private void updateAnnotator(UserClassRequiredAnnotations annotator, Map<String, Object> data) throws QueryException {
-    for (String key : data.keySet()) {
-      if (key.equals("require-at-least-one")) {
-        annotator.setRequireAtLeastOneAnnotation((Boolean) data.get("require-at-least-one"));
-      } else if (key.equals("annotation-list")) {
-        annotator.getRequiredMiriamTypes().clear();
-        for (Object row : (List<?>) data.get(key)) {
-          annotator.getRequiredMiriamTypes().add(MiriamType.valueOf((String) row));
-        }
-      } else {
-        throw new QueryException("Unknown field: " + key);
-      }
-    }
-
-  }
-
-  private Map<String, Object> prepareElementAnnotators(List<UserClassAnnotators> classAnnotators) {
-    Map<String, Object> result = new TreeMap<>();
-    for (UserClassAnnotators userClassAnnotators : classAnnotators) {
-      result.put(userClassAnnotators.getClassName(), new ArrayList<>(userClassAnnotators.getAnnotators()));
-    }
-    return result;
-  }
-
-  private void updateElementAnnotators(UserAnnotationSchema schema, Map<String, Object> data) {
-    for (String key : data.keySet()) {
-      UserClassAnnotators annotator = null;
-      for (UserClassAnnotators userClassAnnotators : schema.getClassAnnotators()) {
-        if (userClassAnnotators.getClassName().equals(key)) {
-          annotator = userClassAnnotators;
-        }
-      }
-      if (annotator == null) {
-        annotator = new UserClassAnnotators();
-        annotator.setClassName(key);
-        schema.addClassAnnotator(annotator);
-      }
-      annotator.getAnnotators().clear();
-      annotator.getAnnotators().addAll((List<String>) data.get(key));
-    }
-  }
-
-  private Map<String, Object> prepareProjectUploadPreferences(UserAnnotationSchema schema) {
-    Map<String, Object> result = new TreeMap<>();
-    result.put("validate-miriam", schema.getValidateMiriamTypes());
-    result.put("annotate-model", schema.getAnnotateModel());
-    result.put("cache-data", schema.getCacheData());
-    result.put("auto-resize", schema.getAutoResizeMap());
-    result.put("semantic-zooming", schema.getSemanticZooming());
-    result.put("sbgn", schema.getSbgnFormat());
-    return result;
-  }
-
-  private List<Map<String, Object>> preparePrivileges(User user) {
-    List<Map<String, Object>> result = new ArrayList<>();
-    Set<PrivilegeType> definedDefaultProjectPrivilegeTypes = new HashSet<>();
-    List<BasicPrivilege> privileges = new ArrayList<>();
-    privileges.addAll(user.getPrivileges());
-    privileges.sort(BasicPrivilege.ID_COMPARATOR);
-    for (BasicPrivilege privilege : privileges) {
-      if (privilege instanceof ObjectPrivilege) {
-        if (Project.class.equals(privilege.getType().getPrivilegeObjectType())
-            && ((ObjectPrivilege) privilege).getIdObject() == null) {
-          definedDefaultProjectPrivilegeTypes.add(privilege.getType());
-        }
-        result.add(prepareObjectPrivilege((ObjectPrivilege) privilege));
-      } else {
-        result.add(prepareBasicPrivilege(privilege));
-      }
-    }
-    for (PrivilegeType privilegeType : PrivilegeType.values()) {
-      if (Project.class.equals(privilegeType.getPrivilegeObjectType())
-          && !definedDefaultProjectPrivilegeTypes.contains(privilegeType)) {
-        result.add(prepareDefaultObjectPrivilege(privilegeType));
-      }
-    }
-    Map<String, Object> customLayouts = new TreeMap<>();
-    customLayouts.put("type", "CUSTOM_LAYOUTS_AVAILABLE");
-    customLayouts.put("value", layoutService.getAvailableCustomLayoutsNumber(user));
-    result.add(customLayouts);
-    return result;
-  }
-
-  private Map<String, Object> prepareDefaultObjectPrivilege(PrivilegeType privilegeType) {
-    Map<String, Object> result = new TreeMap<>();
-    result.put("type", privilegeType);
-    ConfigurationOption value = configurationService.getValue(privilegeType);
-    if (value == null) {
-      result.put("value", 0);
-    } else if (value.getValue().equalsIgnoreCase("true")) {
-      result.put("value", 1);
-    } else if (value.getValue().equalsIgnoreCase("false")) {
-      result.put("value", 0);
-    } else {
-      result.put("value", value.getValue());
-    }
-    result.put("objectId", null);
-    return result;
-  }
-
-  private Map<String, Object> prepareObjectPrivilege(ObjectPrivilege privilege) {
-    Map<String, Object> result = new TreeMap<>();
-    result.put("type", privilege.getType());
-    result.put("value", privilege.getLevel());
-    result.put("objectId", privilege.getIdObject());
-    return result;
-  }
-
-  private Map<String, Object> prepareBasicPrivilege(BasicPrivilege privilege) {
-    Map<String, Object> result = new TreeMap<>();
-    if (privilege.getClass().equals(BasicPrivilege.class)) {
-      result.put("type", privilege.getType());
-      result.put("value", privilege.getLevel());
-      return result;
-    } else {
-      throw new InvalidArgumentException("Don't know how to handle class: " + privilege.getClass());
-    }
-  }
-
-  /**
-   * @return the layoutService
-   * @see #layoutService
-   */
-  public ILayoutService getLayoutService() {
-    return layoutService;
-  }
-
-  /**
-   * @param layoutService
-   *          the layoutService to set
-   * @see #layoutService
-   */
-  public void setLayoutService(ILayoutService layoutService) {
-    this.layoutService = layoutService;
-  }
-
-  public List<Map<String, Object>> getUsers(String token, String columns) throws SecurityException {
-    User ownUserData = getUserService().getUserByToken(token);
-    boolean isAdmin = getUserService().userHasPrivilege(ownUserData, PrivilegeType.USER_MANAGEMENT);
-
-    Set<String> columnSet = createUserColumnSet(columns);
-
-    List<Map<String, Object>> result = new ArrayList<>();
-    List<User> users = getUserService().getUsers(token);
-    users.sort(User.LOGIN_COMPARATOR);
-    for (User user : users) {
-      result.add(prepareUse(user, columnSet, isAdmin));
-    }
-    return result;
-  }
-
-  public Map<String, Object> updatePrivileges(String token, String login, Map<String, Object> privilegesData)
-      throws SecurityException, QueryException {
-    if (privilegesData == null) {
-      throw new QueryException("Privileges not defined");
-    }
-    try {
-      User modifiedUser = getUserService().getUserByLogin(login);
-
-      for (String key : privilegesData.keySet()) {
-        Object value = privilegesData.get(key);
-
-        PrivilegeType type = PrivilegeType.valueOf(key);
-
-        if (type.getPrivilegeClassType().equals(BasicPrivilege.class)) {
-          getUserService().setUserPrivilege(modifiedUser, type, value, token);
-        } else if (type.getPrivilegeClassType().equals(ObjectPrivilege.class)) {
-          if (value instanceof Map) {
-            Map<?, ?> objects = (Map<?, ?>) value;
-            for (Object objectId : objects.keySet()) {
-              Integer objectIdAsInteger = null;
-              if (!objectId.equals("null")) {
-                objectIdAsInteger = Integer.valueOf((String) objectId);
-              }
-              getUserService().setUserPrivilege(modifiedUser, type, objects.get(objectId), objectIdAsInteger, token);
-            }
-          } else {
-            throw new QueryException("Invalid value for privilege: " + key);
-          }
-        } else {
-          throw new QueryException("Unknown privilege type: " + key);
-        }
-
-      }
-      return getUser(token, login, "");
-    } catch (IllegalArgumentException e) {
-      throw new QueryException("Invalid input", e);
-    }
-  }
-
-  public Map<String, Object> updatePreferences(String token, String login, Map<String, Object> preferencesData)
-      throws SecurityException, QueryException {
-    if (preferencesData == null) {
-      throw new QueryException("Preferences not defined");
-    }
-    try {
-      User modifiedUser = getUserService().getUserByLogin(login);
-      if (modifiedUser == null) {
-        throw new ObjectNotFoundException("User doesn't exist");
-      }
-
-      UserAnnotationSchema schema = getProjectService().prepareUserAnnotationSchema(modifiedUser);
-
-      for (String key : preferencesData.keySet()) {
-        Map<String, Object> value = (Map<String, Object>) preferencesData.get(key);
-
-        if (key.equals("project-upload")) {
-          updateUploadPreferences(schema, value);
-        } else if (key.equals("element-annotators")) {
-          updateElementAnnotators(schema, value);
-        } else if (key.equals("element-required-annotations")) {
-          updateRequiredAnnotations(schema, value);
-        } else if (key.equals("element-valid-annotations")) {
-          updateValidAnnotations(schema, value);
-        } else if (key.equals("annotators-parameters")) {
-          updateAnnotatorsParams(schema, value);
-        } else if (key.equals("gui-preferences")) {
-          updateGuiPreferences(schema, value);
-        } else {
-          throw new QueryException("Unknown preferences field: " + key);
-        }
-      }
-      modifiedUser.setAnnotationSchema(schema);
-      getUserService().updateUser(modifiedUser, token);
-      return getUser(token, login, "preferences");
-    } catch (IllegalArgumentException e) {
-      throw new QueryException("Invalid input", e);
-    }
-  }
-
-  private void updateUploadPreferences(UserAnnotationSchema schema, Map<String, Object> data) throws QueryException {
-    for (String key : data.keySet()) {
-      Boolean value = (Boolean) data.get(key);
-      if (value != null) {
-        if (key.equals("validate-miriam")) {
-          schema.setValidateMiriamTypes(value);
-        } else if (key.equals("annotate-model")) {
-          schema.setAnnotateModel(value);
-        } else if (key.equals("cache-data")) {
-          schema.setCacheData(value);
-        } else if (key.equals("auto-resize")) {
-          schema.setAutoResizeMap(value);
-        } else if (key.equals("semantic-zooming")) {
-          schema.setSemanticZooming(value);
-        } else if (key.equals("sbgn")) {
-          schema.setSbgnFormat(value);
-        } else {
-          throw new QueryException("Unknown upload preference field: " + key);
-        }
-      }
-    }
-
-  }
-
-  public Map<String, Object> updateUser(String token, String login, Map<String, Object> userData)
-      throws QueryException, SecurityException {
-    if (userData == null) {
-      throw new QueryException("user field cannot be undefined");
-    }
-    User user = getUserService().getUserByLogin(login);
-    if (user == null) {
-      throw new ObjectNotFoundException("user doesn't exist");
-    }
-    boolean isAdmin = getUserService().userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT);
-    if (!isAdmin && !login.equalsIgnoreCase(getUserService().getUserByToken(token).getLogin())) {
-      throw new SecurityException("Access denied");
-    }
-    for (String key : userData.keySet()) {
-      Object value = userData.get(key);
-      String stringValue = null;
-      if (value instanceof String) {
-        stringValue = (String) value;
-      }
-      if (key.equalsIgnoreCase("name")) {
-        user.setName(stringValue);
-      } else if (key.equalsIgnoreCase("surname")) {
-        user.setSurname(stringValue);
-      } else if (key.equalsIgnoreCase("email")) {
-        user.setEmail(stringValue);
-      } else if (key.equalsIgnoreCase("termsofuseconsent")) {
-        user.setTermsOfUseConsent((Boolean) value);
-      } else if (key.equalsIgnoreCase("password")) {
-        if (stringValue != null && !stringValue.trim().isEmpty()) {
-          user.setCryptedPassword(getUserService().encodePassword(stringValue));
-        }
-      } else if (key.equalsIgnoreCase("login")) {
-        if (!user.getLogin().equals((String) value)) {
-          throw new QueryException("login cannot be modified");
-        }
-      } else {
-        throw new QueryException("Unknown parameter: " + key);
-      }
-    }
-    getUserService().updateUser(user);
-    return getUser(token, login, "");
-  }
-
-  public Map<String, Object> addProject(String token, String login, MultiValueMap<String, Object> userData)
-      throws QueryException, SecurityException {
-    if (!getUserService().userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT)) {
-      throw new SecurityException("Access denied");
-    }
-
-    User user = getUserService().getUserByLogin(login);
-    if (user != null) {
-      throw new QueryException("user exists");
-    }
-    user = new User();
-    user.setLogin(login);
-    for (String key : userData.keySet()) {
-      String stringValue = getFirstValue((List<Object>) userData.get(key));
-      if (key.equalsIgnoreCase("name")) {
-        user.setName(stringValue);
-      } else if (key.equalsIgnoreCase("surname")) {
-        user.setSurname(stringValue);
-      } else if (key.equalsIgnoreCase("email")) {
-        user.setEmail(stringValue);
-      } else if (key.equalsIgnoreCase("password")) {
-        if (stringValue != null && !stringValue.trim().isEmpty()) {
-          user.setCryptedPassword(getUserService().encodePassword(stringValue));
-        }
-      } else if (key.equalsIgnoreCase("login")) {
-        if (!user.getLogin().equals(stringValue)) {
-          throw new QueryException("login must match url");
-        }
-      } else {
-        throw new QueryException("Unknown parameter: " + key);
-      }
-    }
-    getUserService().addUser(user);
-    return getUser(token, login, "");
-  }
-
-  public Map<String, Object> removeUser(String token, String login) throws SecurityException, QueryException {
-    User user = getUserService().getUserByLogin(login);
-    if (!getUserService().userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT)) {
-      throw new SecurityException("Access denied");
-    }
-    if (user == null) {
-      throw new QueryException("user doesn't exists");
-    }
-    getUserService().deleteUser(user);
-    return okStatus();
-  }
-
-}
+package lcsb.mapviewer.api.users;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.MultiValueMap;
+
+import lcsb.mapviewer.api.BaseRestImpl;
+import lcsb.mapviewer.api.ObjectNotFoundException;
+import lcsb.mapviewer.api.QueryException;
+import lcsb.mapviewer.common.exception.InvalidArgumentException;
+import lcsb.mapviewer.model.Project;
+import lcsb.mapviewer.model.map.MiriamType;
+import lcsb.mapviewer.model.user.BasicPrivilege;
+import lcsb.mapviewer.model.user.ConfigurationOption;
+import lcsb.mapviewer.model.user.ObjectPrivilege;
+import lcsb.mapviewer.model.user.PrivilegeType;
+import lcsb.mapviewer.model.user.User;
+import lcsb.mapviewer.model.user.UserAnnotationSchema;
+import lcsb.mapviewer.model.user.UserAnnotatorsParam;
+import lcsb.mapviewer.model.user.UserClassAnnotators;
+import lcsb.mapviewer.model.user.UserClassRequiredAnnotations;
+import lcsb.mapviewer.model.user.UserClassValidAnnotations;
+import lcsb.mapviewer.model.user.UserGuiPreference;
+import lcsb.mapviewer.services.SecurityException;
+import lcsb.mapviewer.services.interfaces.IConfigurationService;
+import lcsb.mapviewer.services.interfaces.ILayoutService;
+
+@Transactional(value = "txManager")
+public class UserRestImpl extends BaseRestImpl {
+
+  /**
+   * Default class logger.
+   */
+  @SuppressWarnings("unused")
+  private Logger logger = Logger.getLogger(UserRestImpl.class);
+
+  @Autowired
+  private ILayoutService layoutService;
+
+  @Autowired
+  private IConfigurationService configurationService;
+
+  public Map<String, Object> getUser(String token, String login, String columns)
+      throws SecurityException, ObjectNotFoundException {
+    User ownUserData = getUserService().getUserByToken(token);
+
+    Set<String> columnSet = createUserColumnSet(columns);
+
+    boolean isAdmin = getUserService().userHasPrivilege(ownUserData, PrivilegeType.USER_MANAGEMENT);
+
+    if (ownUserData.getLogin().equals(login) || isAdmin) {
+      User user = getUserService().getUserByLogin(login);
+      if (user == null) {
+        throw new ObjectNotFoundException("User doesn't exist");
+      }
+      Boolean ldapAvailable = false;
+      if (columnSet.contains("ldapAccaountAvailable")) {
+        List<User> userList = new ArrayList<>();
+        userList.add(ownUserData);
+        ldapAvailable = getUserService().ldapAccountExistsForLogin(userList).get(login);
+      }
+      return prepareUse(user, columnSet, isAdmin, ldapAvailable);
+    } else {
+      throw new SecurityException("You cannot access data of the user with given id");
+    }
+  }
+
+  private Set<String> createUserColumnSet(String columns) {
+    Set<String> columnsSet = new HashSet<>();
+    if (columns.equals("")) {
+      columnsSet.add("id");
+      columnsSet.add("login");
+      columnsSet.add("name");
+      columnsSet.add("surname");
+      columnsSet.add("email");
+      columnsSet.add("minColor");
+      columnsSet.add("maxColor");
+      columnsSet.add("neutralColor");
+      columnsSet.add("simpleColor");
+      columnsSet.add("removed");
+      columnsSet.add("privileges");
+      columnsSet.add("termsOfUseConsent");
+      columnsSet.add("connectedToLdap");
+      columnsSet.add("ldapAccaountAvailable");
+    } else {
+      for (String str : columns.split(",")) {
+        columnsSet.add(str);
+      }
+    }
+    return columnsSet;
+  }
+
+  private Map<String, Object> prepareUse(User user, Set<String> columnsSet, boolean admin, Boolean ldapAvailable) {
+    Map<String, Object> result = new TreeMap<>();
+    for (String string : columnsSet) {
+      String column = string.toLowerCase();
+      Object value = null;
+      if (column.equals("id") || column.equals("idobject")) {
+        value = user.getId();
+      } else if (column.equals("name")) {
+        value = user.getName();
+      } else if (column.equals("surname")) {
+        value = user.getSurname();
+      } else if (column.equals("login")) {
+        value = user.getLogin();
+      } else if (column.equals("email")) {
+        value = user.getEmail();
+      } else if (column.equals("mincolor")) {
+        value = user.getMinColor();
+      } else if (column.equals("maxcolor")) {
+        value = user.getMaxColor();
+      } else if (column.equals("neutralcolor")) {
+        value = user.getNeutralColor();
+      } else if (column.equals("simplecolor")) {
+        value = user.getSimpleColor();
+      } else if (column.equals("removed")) {
+        value = user.isRemoved();
+      } else if (column.equals("termsofuseconsent")) {
+        value = user.isTermsOfUseConsent();
+      } else if (column.equals("connectedtoldap") && admin) {
+        value = user.isConnectedToLdap();
+      } else if (column.equals("ldapaccaountavailable") && admin) {
+        if (ldapAvailable == null) {
+          ldapAvailable = false;
+        }
+        value = ldapAvailable;
+      } else if (column.equals("privileges") && admin) {
+        value = preparePrivileges(user);
+      } else if (column.equals("preferences")) {
+        value = preparePreferences(user);
+      } else {
+        value = "Unknown column";
+      }
+      result.put(string, value);
+    }
+    return result;
+  }
+
+  private Map<String, Object> preparePreferences(User user) {
+    Map<String, Object> result = new TreeMap<>();
+    UserAnnotationSchema schema = getProjectService().prepareUserAnnotationSchema(user);
+    result.put("project-upload", prepareProjectUploadPreferences(schema));
+    result.put("element-annotators", prepareElementAnnotators(schema.getClassAnnotators()));
+    result.put("element-required-annotations", prepareRequiredAnnotations(schema.getClassRequiredAnnotators()));
+    result.put("element-valid-annotations", prepareValidAnnotations(schema.getClassValidAnnotators()));
+    result.put("annotators-parameters", prepareAnnotatorsParams(schema.getAnnotatorsParams()));
+    result.put("gui-preferences", prepareGuiPreferences(schema.getGuiPreferences()));
+    return result;
+  }
+
+  Map<String, Object> prepareGuiPreferences(Set<UserGuiPreference> guiPreferences) {
+    Map<String, Object> result = new TreeMap<>();
+    for (UserGuiPreference userGuiPreference : guiPreferences) {
+      result.put(userGuiPreference.getKey(), userGuiPreference.getValue());
+    }
+    return result;
+  }
+
+  /**
+   * Prepares annotator parameters in the form of a map having annotators class
+   * names as keys and map of name:value pairs of given annotator as values.
+   *
+   * @param annotatorsParams
+   * @return
+   */
+  private Map<String, Object> prepareAnnotatorsParams(List<UserAnnotatorsParam> annotatorsParams) {
+    Map<String, Object> result = new TreeMap<>();
+    for (UserAnnotatorsParam param : annotatorsParams) {
+      String className = param.getAnnotatorClassName().getName();
+      Map<String, String> annotatorParams = (Map<String, String>) result.get(className);
+      if (annotatorParams == null) {
+        annotatorParams = new TreeMap<>();
+        result.put(className, annotatorParams);
+      }
+      annotatorParams.put(param.getParamName(), param.getParamValue());
+    }
+    return result;
+  }
+
+  private Map<String, Object> prepareValidAnnotations(List<UserClassValidAnnotations> classValidAnnotators) {
+    Map<String, Object> result = new TreeMap<>();
+    for (UserClassValidAnnotations userClassAnnotators : classValidAnnotators) {
+      result.put(userClassAnnotators.getClassName(), new ArrayList<>(userClassAnnotators.getValidMiriamTypes()));
+    }
+    return result;
+  }
+
+  private void updateValidAnnotations(UserAnnotationSchema schema, Map<String, Object> data) {
+    for (String key : data.keySet()) {
+      UserClassValidAnnotations annotator = null;
+      for (UserClassValidAnnotations userClassAnnotators : schema.getClassValidAnnotators()) {
+        if (userClassAnnotators.getClassName().equals(key)) {
+          annotator = userClassAnnotators;
+        }
+      }
+      if (annotator == null) {
+        annotator = new UserClassValidAnnotations();
+        annotator.setClassName(key);
+        schema.addClassValidAnnotations(annotator);
+      }
+      annotator.getValidMiriamTypes().clear();
+      for (Object row : (List<?>) data.get(key)) {
+        annotator.getValidMiriamTypes().add(MiriamType.valueOf((String) row));
+      }
+    }
+  }
+
+  private void updateAnnotatorsParams(UserAnnotationSchema schema, Map<String, Object> data) throws QueryException {
+    for (String annotatorClassname : data.keySet()) {
+      Map<String, Object> nameValueS = (Map<String, Object>) data.get(annotatorClassname);
+      for (String name : nameValueS.keySet()) {
+        String value = (String) nameValueS.get(name);
+        try {
+          UserAnnotatorsParam param = new UserAnnotatorsParam(Class.forName(annotatorClassname), name, value);
+          schema.addAnnotatorParam(param);
+        } catch (ClassNotFoundException e) {
+          throw new QueryException("Unknown annotator class name: " + annotatorClassname);
+        }
+      }
+    }
+  }
+
+  private void updateGuiPreferences(UserAnnotationSchema schema, Map<String, Object> data) throws QueryException {
+    for (String key : data.keySet()) {
+      Object object = data.get(key);
+      String value = "";
+      if (object instanceof Integer) {
+        value = object + "";
+      } else if (object instanceof String) {
+        value = (String) data.get(key);
+      } else {
+        throw new InvalidArgumentException("Invalid value class: " + value);
+      }
+      schema.setGuiPreference(key, value);
+    }
+  }
+
+  private Map<String, Object> prepareRequiredAnnotations(List<UserClassRequiredAnnotations> classRequiredAnnotators) {
+    Map<String, Object> result = new TreeMap<>();
+    for (UserClassRequiredAnnotations requiredAnnotations : classRequiredAnnotators) {
+      Map<String, Object> row = new TreeMap<>();
+      row.put("require-at-least-one", requiredAnnotations.getRequireAtLeastOneAnnotation());
+      List<String> miriamTypes = new ArrayList<>();
+
+      for (MiriamType mt : requiredAnnotations.getRequiredMiriamTypes()) {
+        miriamTypes.add(mt.name());
+      }
+      row.put("annotation-list", miriamTypes);
+      result.put(requiredAnnotations.getClassName(), row);
+    }
+    return result;
+  }
+
+  private void updateRequiredAnnotations(UserAnnotationSchema schema, Map<String, Object> data) throws QueryException {
+    for (String key : data.keySet()) {
+      UserClassRequiredAnnotations annotator = null;
+      for (UserClassRequiredAnnotations userClassAnnotators : schema.getClassRequiredAnnotators()) {
+        if (userClassAnnotators.getClassName().equals(key)) {
+          annotator = userClassAnnotators;
+        }
+      }
+      if (annotator == null) {
+        annotator = new UserClassRequiredAnnotations();
+        annotator.setClassName(key);
+        schema.addClassRequiredAnnotations(annotator);
+      }
+      updateAnnotator(annotator, (Map<String, Object>) data.get(key));
+    }
+  }
+
+  private void updateAnnotator(UserClassRequiredAnnotations annotator, Map<String, Object> data) throws QueryException {
+    for (String key : data.keySet()) {
+      if (key.equals("require-at-least-one")) {
+        annotator.setRequireAtLeastOneAnnotation((Boolean) data.get("require-at-least-one"));
+      } else if (key.equals("annotation-list")) {
+        annotator.getRequiredMiriamTypes().clear();
+        for (Object row : (List<?>) data.get(key)) {
+          annotator.getRequiredMiriamTypes().add(MiriamType.valueOf((String) row));
+        }
+      } else {
+        throw new QueryException("Unknown field: " + key);
+      }
+    }
+
+  }
+
+  private Map<String, Object> prepareElementAnnotators(List<UserClassAnnotators> classAnnotators) {
+    Map<String, Object> result = new TreeMap<>();
+    for (UserClassAnnotators userClassAnnotators : classAnnotators) {
+      result.put(userClassAnnotators.getClassName(), new ArrayList<>(userClassAnnotators.getAnnotators()));
+    }
+    return result;
+  }
+
+  private void updateElementAnnotators(UserAnnotationSchema schema, Map<String, Object> data) {
+    for (String key : data.keySet()) {
+      UserClassAnnotators annotator = null;
+      for (UserClassAnnotators userClassAnnotators : schema.getClassAnnotators()) {
+        if (userClassAnnotators.getClassName().equals(key)) {
+          annotator = userClassAnnotators;
+        }
+      }
+      if (annotator == null) {
+        annotator = new UserClassAnnotators();
+        annotator.setClassName(key);
+        schema.addClassAnnotator(annotator);
+      }
+      annotator.getAnnotators().clear();
+      annotator.getAnnotators().addAll((List<String>) data.get(key));
+    }
+  }
+
+  private Map<String, Object> prepareProjectUploadPreferences(UserAnnotationSchema schema) {
+    Map<String, Object> result = new TreeMap<>();
+    result.put("validate-miriam", schema.getValidateMiriamTypes());
+    result.put("annotate-model", schema.getAnnotateModel());
+    result.put("cache-data", schema.getCacheData());
+    result.put("auto-resize", schema.getAutoResizeMap());
+    result.put("semantic-zooming", schema.getSemanticZooming());
+    result.put("sbgn", schema.getSbgnFormat());
+    return result;
+  }
+
+  private List<Map<String, Object>> preparePrivileges(User user) {
+    List<Map<String, Object>> result = new ArrayList<>();
+    Set<PrivilegeType> definedDefaultProjectPrivilegeTypes = new HashSet<>();
+    List<BasicPrivilege> privileges = new ArrayList<>();
+    privileges.addAll(user.getPrivileges());
+    privileges.sort(BasicPrivilege.ID_COMPARATOR);
+    for (BasicPrivilege privilege : privileges) {
+      if (privilege instanceof ObjectPrivilege) {
+        if (Project.class.equals(privilege.getType().getPrivilegeObjectType())
+            && ((ObjectPrivilege) privilege).getIdObject() == null) {
+          definedDefaultProjectPrivilegeTypes.add(privilege.getType());
+        }
+        result.add(prepareObjectPrivilege((ObjectPrivilege) privilege));
+      } else {
+        result.add(prepareBasicPrivilege(privilege));
+      }
+    }
+    for (PrivilegeType privilegeType : PrivilegeType.values()) {
+      if (Project.class.equals(privilegeType.getPrivilegeObjectType())
+          && !definedDefaultProjectPrivilegeTypes.contains(privilegeType)) {
+        result.add(prepareDefaultObjectPrivilege(privilegeType));
+      }
+    }
+    Map<String, Object> customLayouts = new TreeMap<>();
+    customLayouts.put("type", "CUSTOM_LAYOUTS_AVAILABLE");
+    customLayouts.put("value", layoutService.getAvailableCustomLayoutsNumber(user));
+    result.add(customLayouts);
+    return result;
+  }
+
+  private Map<String, Object> prepareDefaultObjectPrivilege(PrivilegeType privilegeType) {
+    Map<String, Object> result = new TreeMap<>();
+    result.put("type", privilegeType);
+    ConfigurationOption value = configurationService.getValue(privilegeType);
+    if (value == null) {
+      result.put("value", 0);
+    } else if (value.getValue().equalsIgnoreCase("true")) {
+      result.put("value", 1);
+    } else if (value.getValue().equalsIgnoreCase("false")) {
+      result.put("value", 0);
+    } else {
+      result.put("value", value.getValue());
+    }
+    result.put("objectId", null);
+    return result;
+  }
+
+  private Map<String, Object> prepareObjectPrivilege(ObjectPrivilege privilege) {
+    Map<String, Object> result = new TreeMap<>();
+    result.put("type", privilege.getType());
+    result.put("value", privilege.getLevel());
+    result.put("objectId", privilege.getIdObject());
+    return result;
+  }
+
+  private Map<String, Object> prepareBasicPrivilege(BasicPrivilege privilege) {
+    Map<String, Object> result = new TreeMap<>();
+    if (privilege.getClass().equals(BasicPrivilege.class)) {
+      result.put("type", privilege.getType());
+      result.put("value", privilege.getLevel());
+      return result;
+    } else {
+      throw new InvalidArgumentException("Don't know how to handle class: " + privilege.getClass());
+    }
+  }
+
+  /**
+   * @return the layoutService
+   * @see #layoutService
+   */
+  public ILayoutService getLayoutService() {
+    return layoutService;
+  }
+
+  /**
+   * @param layoutService
+   *          the layoutService to set
+   * @see #layoutService
+   */
+  public void setLayoutService(ILayoutService layoutService) {
+    this.layoutService = layoutService;
+  }
+
+  public List<Map<String, Object>> getUsers(String token, String columns) throws SecurityException {
+    User ownUserData = getUserService().getUserByToken(token);
+    boolean isAdmin = getUserService().userHasPrivilege(ownUserData, PrivilegeType.USER_MANAGEMENT);
+
+    Set<String> columnSet = createUserColumnSet(columns);
+
+    List<Map<String, Object>> result = new ArrayList<>();
+    List<User> users = getUserService().getUsers(token);
+    users.sort(User.LOGIN_COMPARATOR);
+    Map<String, Boolean> ldapAvailability = getUserService().ldapAccountExistsForLogin(users);
+
+    for (User user : users) {
+      result.add(prepareUse(user, columnSet, isAdmin, ldapAvailability.get(user.getLogin())));
+    }
+    return result;
+  }
+
+  public Map<String, Object> updatePrivileges(String token, String login, Map<String, Object> privilegesData)
+      throws SecurityException, QueryException {
+    if (privilegesData == null) {
+      throw new QueryException("Privileges not defined");
+    }
+    try {
+      User modifiedUser = getUserService().getUserByLogin(login);
+
+      for (String key : privilegesData.keySet()) {
+        Object value = privilegesData.get(key);
+
+        PrivilegeType type = PrivilegeType.valueOf(key);
+
+        if (type.getPrivilegeClassType().equals(BasicPrivilege.class)) {
+          getUserService().setUserPrivilege(modifiedUser, type, value, token);
+        } else if (type.getPrivilegeClassType().equals(ObjectPrivilege.class)) {
+          if (value instanceof Map) {
+            Map<?, ?> objects = (Map<?, ?>) value;
+            for (Object objectId : objects.keySet()) {
+              Integer objectIdAsInteger = null;
+              if (!objectId.equals("null")) {
+                objectIdAsInteger = Integer.valueOf((String) objectId);
+              }
+              getUserService().setUserPrivilege(modifiedUser, type, objects.get(objectId), objectIdAsInteger, token);
+            }
+          } else {
+            throw new QueryException("Invalid value for privilege: " + key);
+          }
+        } else {
+          throw new QueryException("Unknown privilege type: " + key);
+        }
+
+      }
+      return getUser(token, login, "");
+    } catch (IllegalArgumentException e) {
+      throw new QueryException("Invalid input", e);
+    }
+  }
+
+  public Map<String, Object> updatePreferences(String token, String login, Map<String, Object> preferencesData)
+      throws SecurityException, QueryException {
+    if (preferencesData == null) {
+      throw new QueryException("Preferences not defined");
+    }
+    try {
+      User modifiedUser = getUserService().getUserByLogin(login);
+      if (modifiedUser == null) {
+        throw new ObjectNotFoundException("User doesn't exist");
+      }
+
+      UserAnnotationSchema schema = getProjectService().prepareUserAnnotationSchema(modifiedUser);
+
+      for (String key : preferencesData.keySet()) {
+        Map<String, Object> value = (Map<String, Object>) preferencesData.get(key);
+
+        if (key.equals("project-upload")) {
+          updateUploadPreferences(schema, value);
+        } else if (key.equals("element-annotators")) {
+          updateElementAnnotators(schema, value);
+        } else if (key.equals("element-required-annotations")) {
+          updateRequiredAnnotations(schema, value);
+        } else if (key.equals("element-valid-annotations")) {
+          updateValidAnnotations(schema, value);
+        } else if (key.equals("annotators-parameters")) {
+          updateAnnotatorsParams(schema, value);
+        } else if (key.equals("gui-preferences")) {
+          updateGuiPreferences(schema, value);
+        } else {
+          throw new QueryException("Unknown preferences field: " + key);
+        }
+      }
+      modifiedUser.setAnnotationSchema(schema);
+      getUserService().updateUser(modifiedUser, token);
+      return getUser(token, login, "preferences");
+    } catch (IllegalArgumentException e) {
+      throw new QueryException("Invalid input", e);
+    }
+  }
+
+  private void updateUploadPreferences(UserAnnotationSchema schema, Map<String, Object> data) throws QueryException {
+    for (String key : data.keySet()) {
+      Boolean value = (Boolean) data.get(key);
+      if (value != null) {
+        if (key.equals("validate-miriam")) {
+          schema.setValidateMiriamTypes(value);
+        } else if (key.equals("annotate-model")) {
+          schema.setAnnotateModel(value);
+        } else if (key.equals("cache-data")) {
+          schema.setCacheData(value);
+        } else if (key.equals("auto-resize")) {
+          schema.setAutoResizeMap(value);
+        } else if (key.equals("semantic-zooming")) {
+          schema.setSemanticZooming(value);
+        } else if (key.equals("sbgn")) {
+          schema.setSbgnFormat(value);
+        } else {
+          throw new QueryException("Unknown upload preference field: " + key);
+        }
+      }
+    }
+
+  }
+
+  public Map<String, Object> updateUser(String token, String login, Map<String, Object> userData)
+      throws QueryException, SecurityException {
+    if (userData == null) {
+      throw new QueryException("user field cannot be undefined");
+    }
+    User user = getUserService().getUserByLogin(login);
+    if (user == null) {
+      throw new ObjectNotFoundException("user doesn't exist");
+    }
+    boolean isAdmin = getUserService().userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT);
+    if (!isAdmin && !login.equalsIgnoreCase(getUserService().getUserByToken(token).getLogin())) {
+      throw new SecurityException("Access denied");
+    }
+    for (String key : userData.keySet()) {
+      Object value = userData.get(key);
+      String stringValue = null;
+      if (value instanceof String) {
+        stringValue = (String) value;
+      }
+      if (key.equalsIgnoreCase("name")) {
+        user.setName(stringValue);
+      } else if (key.equalsIgnoreCase("surname")) {
+        user.setSurname(stringValue);
+      } else if (key.equalsIgnoreCase("email")) {
+        user.setEmail(stringValue);
+      } else if (key.equalsIgnoreCase("termsofuseconsent")) {
+        user.setTermsOfUseConsent((Boolean) value);
+      } else if (key.equalsIgnoreCase("connectedtoldap")) {
+        user.setConnectedToLdap((Boolean) value);
+      } else if (key.equalsIgnoreCase("password")) {
+        if (stringValue != null && !stringValue.trim().isEmpty()) {
+          user.setCryptedPassword(getUserService().encodePassword(stringValue));
+        }
+      } else if (key.equalsIgnoreCase("login")) {
+        if (!user.getLogin().equals((String) value)) {
+          throw new QueryException("login cannot be modified");
+        }
+      } else {
+        throw new QueryException("Unknown parameter: " + key);
+      }
+    }
+    getUserService().updateUser(user);
+    return getUser(token, login, "");
+  }
+
+  public Map<String, Object> addProject(String token, String login, MultiValueMap<String, Object> userData)
+      throws QueryException, SecurityException {
+    if (!getUserService().userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT)) {
+      throw new SecurityException("Access denied");
+    }
+
+    User user = getUserService().getUserByLogin(login);
+    if (user != null) {
+      throw new QueryException("user exists");
+    }
+    user = new User();
+    user.setLogin(login);
+    for (String key : userData.keySet()) {
+      String stringValue = getFirstValue((List<Object>) userData.get(key));
+      if (key.equalsIgnoreCase("name")) {
+        user.setName(stringValue);
+      } else if (key.equalsIgnoreCase("surname")) {
+        user.setSurname(stringValue);
+      } else if (key.equalsIgnoreCase("email")) {
+        user.setEmail(stringValue);
+      } else if (key.equalsIgnoreCase("password")) {
+        if (stringValue != null && !stringValue.trim().isEmpty()) {
+          user.setCryptedPassword(getUserService().encodePassword(stringValue));
+        }
+      } else if (key.equalsIgnoreCase("login")) {
+        if (!user.getLogin().equals(stringValue)) {
+          throw new QueryException("login must match url");
+        }
+      } else {
+        throw new QueryException("Unknown parameter: " + key);
+      }
+    }
+    getUserService().addUser(user);
+    return getUser(token, login, "");
+  }
+
+  public Map<String, Object> removeUser(String token, String login) throws SecurityException, QueryException {
+    User user = getUserService().getUserByLogin(login);
+    if (!getUserService().userHasPrivilege(token, PrivilegeType.USER_MANAGEMENT)) {
+      throw new SecurityException("Access denied");
+    }
+    if (user == null) {
+      throw new QueryException("user doesn't exists");
+    }
+    getUserService().deleteUser(user);
+    return okStatus();
+  }
+
+}
diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/UserService.java b/service/src/main/java/lcsb/mapviewer/services/impl/UserService.java
index 65029b62f3..cfabf12b2a 100644
--- a/service/src/main/java/lcsb/mapviewer/services/impl/UserService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/impl/UserService.java
@@ -4,7 +4,10 @@ import java.awt.Color;
 import java.math.BigInteger;
 import java.security.SecureRandom;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;
 
 import org.apache.log4j.Logger;
@@ -574,4 +577,26 @@ public class UserService implements IUserService {
     }
   }
 
+  @Override
+  public Map<String, Boolean> ldapAccountExistsForLogin(Collection<User> logins) {
+    Map<String, Boolean> result = new HashMap<>();
+    for (User user : logins) {
+      result.put(user.getLogin(), false);
+    }
+
+    if (ldapService.isValidConfiguration()) {
+      try {
+        List<String> ldapUserNames = getLdapService().getUsernames();
+        for (String string : ldapUserNames) {
+          if (result.keySet().contains(string)) {
+            result.put(string, true);
+          }
+        }
+      } catch (LDAPException e) {
+        logger.error("Problem with accessing LDAP directory", e);
+      }
+    }
+    return result;
+  }
+
 }
diff --git a/service/src/main/java/lcsb/mapviewer/services/interfaces/IUserService.java b/service/src/main/java/lcsb/mapviewer/services/interfaces/IUserService.java
index 5db386f3f5..66bc88d312 100644
--- a/service/src/main/java/lcsb/mapviewer/services/interfaces/IUserService.java
+++ b/service/src/main/java/lcsb/mapviewer/services/interfaces/IUserService.java
@@ -1,186 +1,189 @@
-package lcsb.mapviewer.services.interfaces;
-
-import java.util.List;
-
-import lcsb.mapviewer.commands.ColorExtractor;
-import lcsb.mapviewer.model.Project;
-import lcsb.mapviewer.model.user.BasicPrivilege;
-import lcsb.mapviewer.model.user.PrivilegeType;
-import lcsb.mapviewer.model.user.User;
-import lcsb.mapviewer.services.SecurityException;
-
-/**
- * Service that manages users.
- * 
- * @author Piotr Gawron
- * 
- */
-public interface IUserService {
-  /**
-   * Check if its possible to login using given login and password.
-   * 
-   * @param login
-   *          user login
-   * @param password
-   *          plan password
-   * @return {@link String} containing session id if credentials are valid,
-   *         <code>null</code> otherwise
-   */
-  String login(String login, String password);
-
-  /**
-   * Returns user by login.
-   * 
-   * @param login
-   *          user login
-   * @return user if the login is valid, <code>null</code> otherwise
-   */
-  User getUserByLogin(String login);
-
-  /**
-   * Checks if user has a given privilege.
-   * 
-   * @param user
-   *          user for which the check is performed
-   * @param type
-   *          type of the privilege
-   * @return <code>true</code> if user has privilege, <code>false</code> otherwise
-   */
-  boolean userHasPrivilege(User user, PrivilegeType type);
-
-  /**
-   * Returns level of the user privilege.
-   * 
-   * @param user
-   *          user for which the check is performed
-   * @param type
-   *          type of the privilege
-   * @return level of the privilege
-   */
-  int getUserPrivilegeLevel(User user, PrivilegeType type);
-
-  /**
-   * Checks if user has a given privilege on the object.
-   * 
-   * @param user
-   *          user for which the check is performed
-   * @param type
-   *          type of the privilege
-   * @param object
-   *          object of the privilege
-   * @return <code>true</code> if user has privilege, <code>false</code> otherwise
-   */
-  boolean userHasPrivilege(User user, PrivilegeType type, Object object);
-
-  /**
-   * Returns level of the user privilege.
-   * 
-   * @param object
-   *          object of the privilege
-   * @param user
-   *          user for which the check is performed
-   * @param type
-   *          type of the privilege
-   * @return level of the privilege
-   */
-  int getUserPrivilegeLevel(User user, PrivilegeType type, Object object);
-
-  /**
-   * Sets the user privilege.
-   * 
-   * @param user
-   *          user for whom the privilege should be granted/dropped
-   * @param privilege
-   *          user privilege
-   */
-  void setUserPrivilege(User user, BasicPrivilege privilege);
-
-  /**
-   * Adds user to the system.
-   * 
-   * @param user
-   *          user to be added
-   */
-  void addUser(User user);
-
-  /**
-   * Updates user in the system.
-   * 
-   * @param user
-   *          user to be updated
-   */
-  void updateUser(User user);
-
-  /**
-   * Removes user from the system.
-   * 
-   * @param user
-   *          user to be removed
-   */
-  void deleteUser(User user);
-
-  /**
-   * Drops privileges for every user on the given object and type.
-   * 
-   * @param type
-   *          type of privilege that should be dropped
-   * @param objectId
-   *          identifier of the object to which privileges should be dropped
-   */
-  void dropPrivilegesForObjectType(PrivilegeType type, int objectId);
-
-  /**
-   * Adds privilege to the user.
-   * 
-   * @param user
-   *          user to which privilege should be added
-   * @param type
-   *          type of the privilege
-   */
-  void setUserPrivilege(User user, PrivilegeType type, Integer value);
-
-  /**
-   * @param password
-   *          input password
-   * @return encoded password
-   */
-  String encodePassword(String password);
-
-  /**
-   * Returns {@link ColorExtractor} that transform overlay values into colors for
-   * given user.
-   * 
-   * @param user
-   *          {@link User} for which {@link ColorExtractor} will be obtained
-   * @return {@link ColorExtractor} that transform overlay values into colors for
-   *         given user
-   */
-  ColorExtractor getColorExtractorForUser(User user);
-
-  User getUserByToken(String token) throws SecurityException;
-
-  boolean userHasPrivilege(String token, PrivilegeType type, Object object) throws SecurityException;
-
-  void logout(String tokenString) throws SecurityException;
-
-  boolean userHasPrivilege(String token, PrivilegeType addMap) throws SecurityException;
-
-  List<User> getUsers(String token) throws SecurityException;
-
-  void setUserPrivilege(User modifiedUser, PrivilegeType type, Object privilegeToSet, String authenticationToken)
-      throws SecurityException;
-
-  void setUserPrivilege(User modifiedUser, PrivilegeType type, Object privilegeToSet, Integer objectId,
-      String authenticationToken) throws SecurityException;
-
-  void updateUser(User modifiedUser, String authenticationToken) throws SecurityException;
-
-  String login(String login, String password, String id);
-
-  ILdapService getLdapService();
-
-  void setLdapService(ILdapService ldapService);
-
-  void createDefaultProjectPrivilegesForUser(Project project, User user);
-
-}
+package lcsb.mapviewer.services.interfaces;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import lcsb.mapviewer.commands.ColorExtractor;
+import lcsb.mapviewer.model.Project;
+import lcsb.mapviewer.model.user.BasicPrivilege;
+import lcsb.mapviewer.model.user.PrivilegeType;
+import lcsb.mapviewer.model.user.User;
+import lcsb.mapviewer.services.SecurityException;
+
+/**
+ * Service that manages users.
+ * 
+ * @author Piotr Gawron
+ * 
+ */
+public interface IUserService {
+  /**
+   * Check if its possible to login using given login and password.
+   * 
+   * @param login
+   *          user login
+   * @param password
+   *          plan password
+   * @return {@link String} containing session id if credentials are valid,
+   *         <code>null</code> otherwise
+   */
+  String login(String login, String password);
+
+  /**
+   * Returns user by login.
+   * 
+   * @param login
+   *          user login
+   * @return user if the login is valid, <code>null</code> otherwise
+   */
+  User getUserByLogin(String login);
+
+  /**
+   * Checks if user has a given privilege.
+   * 
+   * @param user
+   *          user for which the check is performed
+   * @param type
+   *          type of the privilege
+   * @return <code>true</code> if user has privilege, <code>false</code> otherwise
+   */
+  boolean userHasPrivilege(User user, PrivilegeType type);
+
+  /**
+   * Returns level of the user privilege.
+   * 
+   * @param user
+   *          user for which the check is performed
+   * @param type
+   *          type of the privilege
+   * @return level of the privilege
+   */
+  int getUserPrivilegeLevel(User user, PrivilegeType type);
+
+  /**
+   * Checks if user has a given privilege on the object.
+   * 
+   * @param user
+   *          user for which the check is performed
+   * @param type
+   *          type of the privilege
+   * @param object
+   *          object of the privilege
+   * @return <code>true</code> if user has privilege, <code>false</code> otherwise
+   */
+  boolean userHasPrivilege(User user, PrivilegeType type, Object object);
+
+  /**
+   * Returns level of the user privilege.
+   * 
+   * @param object
+   *          object of the privilege
+   * @param user
+   *          user for which the check is performed
+   * @param type
+   *          type of the privilege
+   * @return level of the privilege
+   */
+  int getUserPrivilegeLevel(User user, PrivilegeType type, Object object);
+
+  /**
+   * Sets the user privilege.
+   * 
+   * @param user
+   *          user for whom the privilege should be granted/dropped
+   * @param privilege
+   *          user privilege
+   */
+  void setUserPrivilege(User user, BasicPrivilege privilege);
+
+  /**
+   * Adds user to the system.
+   * 
+   * @param user
+   *          user to be added
+   */
+  void addUser(User user);
+
+  /**
+   * Updates user in the system.
+   * 
+   * @param user
+   *          user to be updated
+   */
+  void updateUser(User user);
+
+  /**
+   * Removes user from the system.
+   * 
+   * @param user
+   *          user to be removed
+   */
+  void deleteUser(User user);
+
+  /**
+   * Drops privileges for every user on the given object and type.
+   * 
+   * @param type
+   *          type of privilege that should be dropped
+   * @param objectId
+   *          identifier of the object to which privileges should be dropped
+   */
+  void dropPrivilegesForObjectType(PrivilegeType type, int objectId);
+
+  /**
+   * Adds privilege to the user.
+   * 
+   * @param user
+   *          user to which privilege should be added
+   * @param type
+   *          type of the privilege
+   */
+  void setUserPrivilege(User user, PrivilegeType type, Integer value);
+
+  /**
+   * @param password
+   *          input password
+   * @return encoded password
+   */
+  String encodePassword(String password);
+
+  /**
+   * Returns {@link ColorExtractor} that transform overlay values into colors for
+   * given user.
+   * 
+   * @param user
+   *          {@link User} for which {@link ColorExtractor} will be obtained
+   * @return {@link ColorExtractor} that transform overlay values into colors for
+   *         given user
+   */
+  ColorExtractor getColorExtractorForUser(User user);
+
+  User getUserByToken(String token) throws SecurityException;
+
+  boolean userHasPrivilege(String token, PrivilegeType type, Object object) throws SecurityException;
+
+  void logout(String tokenString) throws SecurityException;
+
+  boolean userHasPrivilege(String token, PrivilegeType addMap) throws SecurityException;
+
+  List<User> getUsers(String token) throws SecurityException;
+
+  void setUserPrivilege(User modifiedUser, PrivilegeType type, Object privilegeToSet, String authenticationToken)
+      throws SecurityException;
+
+  void setUserPrivilege(User modifiedUser, PrivilegeType type, Object privilegeToSet, Integer objectId,
+      String authenticationToken) throws SecurityException;
+
+  void updateUser(User modifiedUser, String authenticationToken) throws SecurityException;
+
+  String login(String login, String password, String id);
+
+  ILdapService getLdapService();
+
+  void setLdapService(ILdapService ldapService);
+
+  void createDefaultProjectPrivilegesForUser(Project project, User user);
+
+  Map<String, Boolean> ldapAccountExistsForLogin(Collection<User> logins);
+}
-- 
GitLab