org.fao.geonet.api.users.UsersApi.java Source code

Java tutorial

Introduction

Here is the source code for org.fao.geonet.api.users.UsersApi.java

Source

/*
 * Copyright (C) 2001-2016 Food and Agriculture Organization of the
 * United Nations (FAO-UN), United Nations World Food Programme (WFP)
 * and United Nations Environment Programme (UNEP)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 *
 * Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
 * Rome - Italy. email: geonetwork@osgeo.org
 */

package org.fao.geonet.api.users;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import jeeves.server.UserSession;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.fao.geonet.ApplicationContextHolder;
import org.fao.geonet.api.API;
import org.fao.geonet.api.ApiUtils;
import org.fao.geonet.api.users.model.UserDto;
import org.fao.geonet.constants.Params;
import org.fao.geonet.domain.*;
import org.fao.geonet.exceptions.UserNotFoundEx;
import org.fao.geonet.kernel.DataManager;
import org.fao.geonet.repository.GroupRepository;
import org.fao.geonet.repository.SortUtils;
import org.fao.geonet.repository.UserGroupRepository;
import org.fao.geonet.repository.UserRepository;
import org.fao.geonet.repository.UserSavedSelectionRepository;
import org.fao.geonet.repository.specification.UserGroupSpecs;
import org.fao.geonet.repository.specification.UserSpecs;
import org.fao.geonet.util.PasswordUtil;
import org.springframework.data.jpa.domain.Specifications;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;

import static org.fao.geonet.repository.specification.UserGroupSpecs.hasProfile;
import static org.fao.geonet.repository.specification.UserGroupSpecs.hasUserId;
import static org.springframework.data.jpa.domain.Specifications.where;

@RequestMapping(value = { "/api/users", "/api/" + API.VERSION_0_1 + "/users" })
@Api(value = "users", tags = "users", description = "User operations")
@Controller("users")
public class UsersApi {

    @ApiOperation(value = "Get users", notes = "", nickname = "getUsers")
    @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
    @ResponseStatus(value = HttpStatus.OK)
    @PreAuthorize("isAuthenticated()")
    @ResponseBody
    public List<User> getUsers(@ApiIgnore HttpSession httpSession) throws Exception {
        UserSession session = ApiUtils.getUserSession(httpSession);
        Profile profile = session.getProfile();

        UserRepository userRepository = ApplicationContextHolder.get().getBean(UserRepository.class);

        if (profile == Profile.Administrator) {
            return userRepository.findAll(SortUtils.createSort(User_.name));
        } else if (profile != Profile.UserAdmin) {
            return userRepository.findAll(UserSpecs.hasUserId(session.getUserIdAsInt()));
        } else if (profile == Profile.UserAdmin) {
            int userId = session.getUserIdAsInt();
            final List<Integer> userGroupIds = getGroupIds(userId);

            List<User> allUsers = userRepository.findAll(SortUtils.createSort(User_.name));

            // Filter users which are not in current user admin groups
            allUsers.removeIf(u -> !userGroupIds.containsAll(getGroupIds(u.getId()))
                    || u.getProfile().equals(Profile.Administrator));
            //              TODO-API: Check why there was this check on profiles ?
            //                    if (!profileSet.contains(profile))
            //                        alToRemove.add(elRec);

            return allUsers;
        }

        return null;
    }

    @ApiOperation(value = "Get user", notes = "", nickname = "getUser")
    @RequestMapping(value = "/{userIdentifier}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
    @ResponseStatus(value = HttpStatus.OK)
    @PreAuthorize("isAuthenticated()")
    @ResponseBody
    public User getUser(@ApiParam(value = "User identifier.") @PathVariable Integer userIdentifier,
            @ApiIgnore HttpSession httpSession

    ) throws Exception {
        UserSession session = ApiUtils.getUserSession(httpSession);
        Profile myProfile = session.getProfile();
        String myUserId = session.getUserId();

        if (myProfile.equals(Profile.Administrator) || myProfile.equals(Profile.UserAdmin)
                || myUserId.equals(Integer.toString(userIdentifier))) {
            UserRepository userRepository = ApplicationContextHolder.get().getBean(UserRepository.class);
            UserGroupRepository userGroupRepository = ApplicationContextHolder.get()
                    .getBean(UserGroupRepository.class);

            User user = userRepository.findOne(userIdentifier);

            if (user == null) {
                throw new UserNotFoundEx(Integer.toString(userIdentifier));
            }

            if (!(myUserId.equals(Integer.toString(userIdentifier))) && myProfile == Profile.UserAdmin) {

                //--- retrieve session user groups and check to see whether this user is
                //--- allowed to get this info
                List<Integer> adminlist = userGroupRepository
                        .findGroupIds(where(hasUserId(Integer.parseInt(myUserId))).or(hasUserId(userIdentifier)));
                if (adminlist.isEmpty()) {
                    throw new IllegalArgumentException(
                            "You don't have rights to do this because the user you want to edit is not part of your group");
                }
            }

            return user;
        } else {
            throw new IllegalArgumentException("You don't have rights to do this");
        }

    }

    @ApiOperation(value = "Delete a user", notes = "Deletes a catalog user by identifier.", nickname = "deleteUser")
    @RequestMapping(value = "/{userIdentifier}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.DELETE)
    @ResponseStatus(value = HttpStatus.OK)
    @PreAuthorize("hasRole('UserAdmin') or hasRole('Administrator')")
    @ResponseBody
    public ResponseEntity<String> deleteUser(
            @ApiParam(value = "User identifier.") @PathVariable Integer userIdentifier,
            @ApiIgnore ServletRequest request, @ApiIgnore HttpSession httpSession) throws Exception {
        UserSession session = ApiUtils.getUserSession(httpSession);
        Profile myProfile = session.getProfile();
        String myUserId = session.getUserId();

        UserRepository userRepository = ApplicationContextHolder.get().getBean(UserRepository.class);
        UserGroupRepository userGroupRepository = ApplicationContextHolder.get().getBean(UserGroupRepository.class);
        UserSavedSelectionRepository userSavedSelectionRepository = ApplicationContextHolder.get()
                .getBean(UserSavedSelectionRepository.class);

        if (myUserId == null || myUserId.equals(Integer.toString(userIdentifier))) {
            throw new IllegalArgumentException("You cannot delete yourself from the user database");
        }

        if (myProfile == Profile.UserAdmin) {
            final Integer iMyUserId = Integer.parseInt(myUserId);
            final List<Integer> groupIdsSessionUser = userGroupRepository.findGroupIds(where(hasUserId(iMyUserId)));

            final List<Integer> groupIdsUserToDelete = userGroupRepository
                    .findGroupIds(where(hasUserId(userIdentifier)));

            if (CollectionUtils.intersection(groupIdsSessionUser, groupIdsUserToDelete).isEmpty()) {
                throw new IllegalArgumentException(
                        "You don't have rights to delete this user because the user is not part of your group");
            }
        }

        DataManager dataManager = ApplicationContextHolder.get().getBean(DataManager.class);

        // Before processing DELETE check that the user is not referenced
        // elsewhere in the GeoNetwork database - an exception is thrown if
        // this is the case
        if (dataManager.isUserMetadataOwner(userIdentifier)) {
            throw new IllegalArgumentException("Cannot delete a user that is also a metadata owner");
        }

        if (dataManager.isUserMetadataStatus(userIdentifier)) {
            throw new IllegalArgumentException("Cannot delete a user that has set a metadata status");
        }

        userGroupRepository.deleteAllByIdAttribute(UserGroupId_.userId, Arrays.asList(userIdentifier));

        userSavedSelectionRepository.deleteAllByUser(userIdentifier);

        try {
            userRepository.delete(userIdentifier);
        } catch (org.springframework.dao.EmptyResultDataAccessException ex) {
            throw new UserNotFoundEx(Integer.toString(userIdentifier));
        }

        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }

    @ApiOperation(value = "Creates a user", notes = "Creates a catalog user.", nickname = "createUser")
    @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.PUT)
    @ResponseStatus(value = HttpStatus.OK)
    @PreAuthorize("hasRole('UserAdmin') or hasRole('Administrator')")
    @ResponseBody
    public ResponseEntity<String> createUser(@ApiParam(name = "user") @RequestBody UserDto userDto,
            @ApiIgnore ServletRequest request, @ApiIgnore HttpSession httpSession) throws Exception {
        Profile profile = Profile.findProfileIgnoreCase(userDto.getProfile());
        UserSession session = ApiUtils.getUserSession(httpSession);
        Profile myProfile = session.getProfile();
        UserRepository userRepository = ApplicationContextHolder.get().getBean(UserRepository.class);

        if (profile == Profile.Administrator) {
            checkIfAtLeastOneAdminIsEnabled(userDto, userRepository);
        }

        // TODO: CheckAccessRights

        if (!myProfile.getAll().contains(profile)) {
            throw new IllegalArgumentException(
                    "Trying to set profile to " + profile + " max profile permitted is: " + myProfile);
        }

        if (StringUtils.isEmpty(userDto.getUsername())) {
            throw new IllegalArgumentException(Params.USERNAME + " is a required parameter for "
                    + Params.Operation.NEWUSER + " " + "operation");
        }

        List<User> existingUsers = userRepository.findByUsernameIgnoreCase(userDto.getUsername());
        if (!existingUsers.isEmpty()) {
            throw new IllegalArgumentException(
                    "Users with username " + userDto.getUsername() + " ignore case already exists");
        }

        List<GroupElem> groups = new LinkedList<>();

        groups.addAll(processGroups(userDto.getGroupsRegisteredUser(), Profile.RegisteredUser));
        groups.addAll(processGroups(userDto.getGroupsEditor(), Profile.Editor));
        groups.addAll(processGroups(userDto.getGroupsReviewer(), Profile.Reviewer));
        groups.addAll(processGroups(userDto.getGroupsUserAdmin(), Profile.UserAdmin));

        User user = new User();
        user.getSecurity()
                .setPassword(PasswordUtil.encoder(ApplicationContextHolder.get()).encode(userDto.getPassword()));

        fillUserFromParams(user, userDto);

        user = userRepository.save(user);
        setUserGroups(user, groups);

        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }

    @ApiOperation(value = "Update a user", notes = "Updates a catalog user.", nickname = "updateUser")
    @RequestMapping(value = "/{userIdentifier}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.PUT)
    @ResponseStatus(value = HttpStatus.OK)
    @PreAuthorize("isAuthenticated()")
    @ResponseBody
    public ResponseEntity<String> updateUser(
            @ApiParam(value = "User identifier.") @PathVariable Integer userIdentifier,
            @ApiParam(name = "user") @RequestBody UserDto userDto, @ApiIgnore ServletRequest request,
            @ApiIgnore HttpSession httpSession) throws Exception {

        Profile profile = Profile.findProfileIgnoreCase(userDto.getProfile());

        UserSession session = ApiUtils.getUserSession(httpSession);
        Profile myProfile = session.getProfile();
        String myUserId = session.getUserId();

        if (myProfile != Profile.Administrator && myProfile != Profile.UserAdmin
                && !myUserId.equals(Integer.toString(userIdentifier))) {
            throw new IllegalArgumentException("You don't have rights to do this");
        }

        UserRepository userRepository = ApplicationContextHolder.get().getBean(UserRepository.class);
        UserGroupRepository userGroupRepository = ApplicationContextHolder.get().getBean(UserGroupRepository.class);

        if (profile == Profile.Administrator) {
            checkIfAtLeastOneAdminIsEnabled(userDto, userRepository);
        }

        // TODO: CheckAccessRights

        User user = userRepository.findOne(userIdentifier);
        if (user == null) {
            throw new IllegalArgumentException("No user found with id: " + userDto.getId());
        }

        // Check no duplicated username and if we are adding a duplicate existing name with other case combination
        List<User> usersWithUsernameIgnoreCase = userRepository.findByUsernameIgnoreCase(userDto.getUsername());
        if (usersWithUsernameIgnoreCase.size() != 0 && (!usersWithUsernameIgnoreCase.stream()
                .anyMatch(u -> u.getId() == userIdentifier)
                || usersWithUsernameIgnoreCase.stream().anyMatch(
                        u -> u.getUsername().equals(userDto.getUsername()) && u.getId() != userIdentifier))) {
            throw new IllegalArgumentException(String
                    .format("Another user with username '%s' ignore case already exists", user.getUsername()));
        }

        if (!myProfile.getAll().contains(profile)) {
            throw new IllegalArgumentException(
                    "Trying to set profile to " + profile + " max profile permitted is: " + myProfile);
        }

        List<GroupElem> groups = new LinkedList<>();

        groups.addAll(processGroups(userDto.getGroupsRegisteredUser(), Profile.RegisteredUser));
        groups.addAll(processGroups(userDto.getGroupsEditor(), Profile.Editor));
        groups.addAll(processGroups(userDto.getGroupsReviewer(), Profile.Reviewer));
        groups.addAll(processGroups(userDto.getGroupsUserAdmin(), Profile.UserAdmin));

        //If it is a useradmin updating,
        //maybe we don't know all the groups the user is part of
        if (!myProfile.equals(Profile.Administrator)) {
            List<Integer> myUserAdminGroups = userGroupRepository.findGroupIds(
                    Specifications.where(hasProfile(myProfile)).and(hasUserId(Integer.parseInt(myUserId))));

            List<UserGroup> usergroups = userGroupRepository
                    .findAll(Specifications.where(hasUserId(Integer.parseInt(userDto.getId()))));

            //keep unknown groups as is
            for (UserGroup ug : usergroups) {
                if (!myUserAdminGroups.contains(ug.getGroup().getId())) {
                    groups.add(new GroupElem(ug.getProfile().name(), ug.getGroup().getId()));
                }
            }
        }

        fillUserFromParams(user, userDto);

        user = userRepository.save(user);
        setUserGroups(user, groups);

        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }

    @ApiOperation(value = "Resets user password", notes = "Resets the user password.", nickname = "resetUserPassword")
    @RequestMapping(value = "/{userIdentifier}/actions/forget-password", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.POST)
    @ResponseStatus(value = HttpStatus.OK)
    @PreAuthorize("isAuthenticated()")
    @ResponseBody
    public ResponseEntity<String> resetUserPassword(
            @ApiParam(value = "User identifier.") @PathVariable Integer userIdentifier,
            @ApiParam(value = "Password to change.") @RequestParam(value = Params.PASSWORD) String password,
            @ApiParam(value = "Password to change (repeat).") @RequestParam(value = Params.PASSWORD
                    + "2") String password2,
            @ApiIgnore ServletRequest request, @ApiIgnore HttpSession httpSession) throws Exception {

        if (!password.equals(password2)) {
            throw new IllegalArgumentException("Passwords should be equal");
        }

        UserSession session = ApiUtils.getUserSession(httpSession);
        Profile myProfile = session.getProfile();
        String myUserId = session.getUserId();

        if (myProfile != Profile.Administrator && myProfile != Profile.UserAdmin
                && !myUserId.equals(Integer.toString(userIdentifier))) {
            throw new IllegalArgumentException("You don't have rights to do this");
        }

        UserRepository userRepository = ApplicationContextHolder.get().getBean(UserRepository.class);

        User user = userRepository.findOne(userIdentifier);
        if (user == null) {
            throw new UserNotFoundEx(Integer.toString(userIdentifier));
        }

        String passwordHash = PasswordUtil.encoder(ApplicationContextHolder.get()).encode(password);
        user.getSecurity().setPassword(passwordHash);
        user.getSecurity().getSecurityNotifications().remove(UserSecurityNotification.UPDATE_HASH_REQUIRED);
        userRepository.save(user);

        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }

    @ApiOperation(value = "Retrieve user groups", notes = "Retrieve the user groups.", nickname = "retrieveUserGroups")
    @RequestMapping(value = "/{userIdentifier}/groups", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
    @ResponseStatus(value = HttpStatus.OK)
    @PreAuthorize("isAuthenticated()")
    @ResponseBody
    public List<UserGroup> retrieveUserGroups(
            @ApiParam(value = "User identifier.") @PathVariable Integer userIdentifier,
            @ApiIgnore ServletRequest request, @ApiIgnore HttpSession httpSession) throws Exception {
        UserSession session = ApiUtils.getUserSession(httpSession);
        Profile myProfile = session.getProfile();
        String myUserId = session.getUserId();

        final UserRepository userRepository = ApplicationContextHolder.get().getBean(UserRepository.class);
        final UserGroupRepository userGroupRepository = ApplicationContextHolder.get()
                .getBean(UserGroupRepository.class);

        if (myProfile == Profile.Administrator || myProfile == Profile.UserAdmin
                || myUserId.equals(Integer.toString(userIdentifier))) {
            // -- get the profile of the user id supplied
            User user = userRepository.findOne(userIdentifier);
            if (user == null) {
                throw new IllegalArgumentException("user " + userIdentifier + " doesn't exist");
            }

            String userProfile = user.getProfile().name();

            List<UserGroup> userGroups;

            if (myProfile == Profile.Administrator && userProfile.equals(Profile.Administrator.name())) {
                // Return all groups for administrator.
                // TODO: Check if a better option returning instead of UserGroup a customised GroupDTO
                // containing all group properties and user profile
                userGroups = new ArrayList<UserGroup>();
                final GroupRepository groupRepository = ApplicationContextHolder.get()
                        .getBean(GroupRepository.class);

                List<Group> groups = groupRepository.findAll();

                for (Group g : groups) {
                    UserGroup ug = new UserGroup();
                    UserGroupId ugId = new UserGroupId();
                    ugId.setProfile(Profile.Administrator);
                    ugId.setGroupId(g.getId());
                    ugId.setUserId(userIdentifier);

                    ug.setGroup(g);
                    ug.setUser(user);
                    ug.setProfile(Profile.Administrator);
                    ug.setId(ugId);

                    userGroups.add(ug);
                }
            } else {
                if (!(myUserId.equals(Integer.toString(userIdentifier))) && myProfile == Profile.UserAdmin) {

                    //--- retrieve session user groups and check to see whether this user is
                    //--- allowed to get this info
                    List<Integer> adminList = userGroupRepository
                            .findGroupIds(where(UserGroupSpecs.hasUserId(Integer.parseInt(myUserId)))
                                    .or(UserGroupSpecs.hasUserId(userIdentifier)));
                    if (adminList.isEmpty()) {
                        throw new SecurityException(
                                "You don't have rights to do this because the user you want is not part of your group");
                    }
                }

                //--- retrieve user groups of the user id supplied
                userGroups = userGroupRepository.findAll(UserGroupSpecs.hasUserId(userIdentifier));
            }

            return userGroups;
        } else {
            throw new SecurityException("You don't have rights to do get the groups for this user");
        }
    }

    private List<Integer> getGroupIds(int userId) {
        return ApplicationContextHolder.get().getBean(UserGroupRepository.class).findGroupIds(hasUserId(userId));
    }

    private void setUserGroups(final User user, List<GroupElem> userGroups) throws Exception {

        final GroupRepository groupRepository = ApplicationContextHolder.get().getBean(GroupRepository.class);
        final UserGroupRepository userGroupRepository = ApplicationContextHolder.get()
                .getBean(UserGroupRepository.class);

        Collection<UserGroup> all = userGroupRepository.findAll(UserGroupSpecs.hasUserId(user.getId()));

        // Have a quick reference of existing groups and profiles for this user
        Set<String> listOfAddedProfiles = new HashSet<String>();
        for (UserGroup ug : all) {
            String key = ug.getProfile().name() + ug.getGroup().getId();
            if (!listOfAddedProfiles.contains(key)) {
                listOfAddedProfiles.add(key);
            }
        }

        // We start removing all old usergroup objects. We will remove the
        // explicitly defined for this call
        Collection<UserGroup> toRemove = new ArrayList<UserGroup>();
        toRemove.addAll(all);

        // New pairs of group-profile we need to add
        Collection<UserGroup> toAdd = new ArrayList<UserGroup>();

        // For each of the parameters on the request, make sure the group is
        // updated.
        for (GroupElem element : userGroups) {
            Integer groupId = element.getId();
            Group group = groupRepository.findOne(groupId);
            String profile = element.getProfile();
            // The user has a new group and profile

            // Combine all groups editor and reviewer groups
            if (profile.equals(Profile.Reviewer.name())) {
                final UserGroup userGroup = new UserGroup().setGroup(group).setProfile(Profile.Editor)
                        .setUser(user);
                String key = Profile.Editor.toString() + group.getId();
                if (!listOfAddedProfiles.contains(key)) {
                    toAdd.add(userGroup);
                    listOfAddedProfiles.add(key);
                }

                // If the user is already part of this group with this profile,
                // leave it alone:
                for (UserGroup g : all) {
                    if (g.getGroup().getId() == groupId && g.getProfile().equals(Profile.Editor)) {
                        toRemove.remove(g);
                    }
                }
            }

            final UserGroup userGroup = new UserGroup().setGroup(group)
                    .setProfile(Profile.findProfileIgnoreCase(profile)).setUser(user);
            String key = profile + group.getId();
            if (!listOfAddedProfiles.contains(key)) {
                toAdd.add(userGroup);
                listOfAddedProfiles.add(key);

            }

            // If the user is already part of this group with this profile,
            // leave it alone:
            for (UserGroup g : all) {
                if (g.getGroup().getId() == groupId && g.getProfile().name().equalsIgnoreCase(profile)) {
                    toRemove.remove(g);
                }
            }
        }

        // Remove deprecated usergroups (if any)
        userGroupRepository.delete(toRemove);

        // Add only new usergroups (if any)
        userGroupRepository.save(toAdd);

    }

    private List<GroupElem> processGroups(List<String> groupsToProcessList, Profile profile) {
        List<GroupElem> groups = new LinkedList<GroupElem>();
        for (String g : groupsToProcessList) {
            groups.add(new GroupElem(profile.name(), Integer.parseInt(g)));
        }

        return groups;
    }

    private void fillUserFromParams(User user, UserDto userDto) {
        user.setEnabled(userDto.isEnabled());

        if (StringUtils.isNotEmpty(userDto.getUsername())) {
            user.setUsername(userDto.getUsername());
        }

        user.setProfile(Profile.valueOf(userDto.getProfile()));
        user.setName(userDto.getName());
        user.setSurname(userDto.getSurname());
        user.setOrganisation(userDto.getOrganisation());
        user.setName(userDto.getName());
        user.setKind(userDto.getKind());

        if (!userDto.getAddresses().isEmpty()) {
            //            Trigger constraint exception.
            //            Updating only the first (as only one supported on client side)
            //            user.getAddresses().clear();
            //            for (Address address : userDto.getAddresses()) {
            //                address.setZip(null);
            //                user.getAddresses().add(address);
            //            }

            // Updating only the first (as only one supported on client side)
            // TODO: Support multiple addresses
            Set<Address> userAddresses = user.getAddresses();
            Address userAddress;

            if (userAddresses.isEmpty()) {
                userAddress = new Address();
                userAddresses.add(userAddress);
            } else {
                userAddress = (Address) userAddresses.toArray()[0];
            }

            for (Address address : userDto.getAddresses()) {
                userAddress.setAddress(address.getAddress());
                userAddress.setCity(address.getCity());
                userAddress.setCountry(address.getCountry());
                userAddress.setState(address.getState());
                userAddress.setZip(address.getZip());
            }
        }

        if (!userDto.getEmailAddresses().isEmpty()) {
            user.getEmailAddresses().clear();
            for (String mail : userDto.getEmailAddresses()) {
                user.getEmailAddresses().add(mail);
            }
        }
    }

    /**
     * Check if removing userDto from the admins there are still at least one user administrator in the system. .
     *
     * @param userDto        the user to check.
     * @param userRepository user repository to retrieve users from.
     * @throws IllegalArgumentException thrown if userDto is the last administrator user in the system.
     */
    private void checkIfAtLeastOneAdminIsEnabled(UserDto userDto, UserRepository userRepository) {
        // Check at least 1 administrator is enabled
        if (StringUtils.isNotEmpty(userDto.getId()) && (!userDto.isEnabled())) {
            List<User> adminEnabledList = userRepository.findAll(Specifications
                    .where(UserSpecs.hasProfile(Profile.Administrator)).and(UserSpecs.hasEnabled(true)));
            if (adminEnabledList.size() == 1) {
                User adminUser = adminEnabledList.get(0);
                if (adminUser.getId() == Integer.parseInt(userDto.getId())) {
                    throw new IllegalArgumentException("Trying to disable all administrator users is not allowed");
                }
            }
        }
    }
}

class GroupElem {

    private String profile;
    private Integer id;

    public GroupElem(String profile, Integer id) {
        this.id = id;
        this.profile = profile;
    }

    public String getProfile() {
        return profile;
    }

    public Integer getId() {
        return id;
    }
}