org.squashtest.tm.web.internal.controller.administration.UserAdministrationController.java Source code

Java tutorial

Introduction

Here is the source code for org.squashtest.tm.web.internal.controller.administration.UserAdministrationController.java

Source

/**
 *     This file is part of the Squashtest platform.
 *     Copyright (C) 2010 - 2016 Henix, henix.fr
 *
 *     See the NOTICE file distributed with this work for additional
 *     information regarding copyright ownership.
 *
 *     This is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     this software 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 Lesser General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with this software.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.squashtest.tm.web.internal.controller.administration;

import static org.squashtest.tm.web.internal.helper.JEditablePostParams.VALUE;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.inject.Inject;
import javax.validation.Valid;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.HtmlUtils;
import org.squashtest.tm.api.security.authentication.AuthenticationProviderFeatures;
import org.squashtest.tm.core.foundation.collection.DefaultFiltering;
import org.squashtest.tm.core.foundation.collection.DefaultPagingAndSorting;
import org.squashtest.tm.core.foundation.collection.Filtering;
import org.squashtest.tm.core.foundation.collection.PagedCollectionHolder;
import org.squashtest.tm.core.foundation.collection.PagingAndSorting;
import org.squashtest.tm.domain.audit.AuditableMixin;
import org.squashtest.tm.domain.project.ProjectPermission;
import org.squashtest.tm.domain.users.Team;
import org.squashtest.tm.domain.users.User;
import org.squashtest.tm.domain.users.UsersGroup;
import org.squashtest.tm.service.user.AdministrationService;
import org.squashtest.tm.service.user.TeamFinderService;
import org.squashtest.tm.web.internal.controller.RequestParams;
import org.squashtest.tm.web.internal.controller.project.ProjectModel;
import org.squashtest.tm.web.internal.controller.users.PartyControllerSupport;
import org.squashtest.tm.web.internal.controller.users.PermissionGroupModel;
import org.squashtest.tm.web.internal.i18n.InternationalizationHelper;
import org.squashtest.tm.web.internal.model.datatable.DataTableDrawParameters;
import org.squashtest.tm.web.internal.model.datatable.DataTableFiltering;
import org.squashtest.tm.web.internal.model.datatable.DataTableModel;
import org.squashtest.tm.web.internal.model.datatable.DataTableModelBuilder;
import org.squashtest.tm.web.internal.model.datatable.DataTableModelConstants;
import org.squashtest.tm.web.internal.model.datatable.DataTableSorting;
import org.squashtest.tm.web.internal.model.viewmapper.DatatableMapper;
import org.squashtest.tm.web.internal.model.viewmapper.NameBasedMapper;
import org.squashtest.tm.web.internal.security.authentication.AuthenticationProviderContext;

@Controller
@RequestMapping("/administration/users")
public class UserAdministrationController extends PartyControllerSupport {

    private static final String USER_ID = "userId";
    private static final Logger LOGGER = LoggerFactory.getLogger(UserAdministrationController.class);
    private static final String USER_URL = "/{userId}";
    private static final String USER_URLS = "/{userIds}";

    private static final PagingAndSorting TEAMS_DEFAULT_PAGING = new DefaultPagingAndSorting("name");
    private static final Filtering TEAMS_DEFAULT_FILTERING = DefaultFiltering.NO_FILTERING;

    @Inject
    private AdministrationService adminService;

    @Inject
    private TeamFinderService teamFinderService;

    @Inject
    private InternationalizationHelper messageSource;

    @Inject
    private AuthenticationProviderContext authenticationProviderContext;

    private DatatableMapper<String> userMapper = new NameBasedMapper(10).map("user-id", "id")
            .map("user-active", "active").map("user-login", "login").map("user-group", "group")
            .map("user-firstname", "firstName").map("user-lastname", "lastName").map("user-email", "email")
            .map("user-created-on", "audit.createdOn").map("user-created-by", "audit.createdBy")
            .map("user-modified-on", "audit.lastModifiedOn").map("user-modified-by", "audit.lastModifiedBy");

    private DatatableMapper<String> permissionMapper = new NameBasedMapper(2)
            .mapAttribute(DataTableModelConstants.PROJECT_NAME_KEY, "project.name", ProjectPermission.class)
            .mapAttribute("permission-name", "permissionGroup.qualifiedName", ProjectPermission.class);

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public ModelAndView getUserList(Locale locale) {

        ModelAndView mav = new ModelAndView("page/users/show-users");

        List<UsersGroup> list = adminService.findAllUsersGroupOrderedByQualifiedName();

        PagingAndSorting paging = new DefaultPagingAndSorting("User.login");
        Filtering filter = DefaultFiltering.NO_FILTERING;

        DataTableModel model = getTableModel(paging, filter, "noneed", locale);

        mav.addObject("usersGroupList", list);
        mav.addObject("userList", model.getAaData());

        PagedCollectionHolder<List<Team>> teams = teamFinderService.findAllFiltered(TEAMS_DEFAULT_PAGING,
                TEAMS_DEFAULT_FILTERING);
        mav.addObject("pagedTeams", teams);
        mav.addObject("teamsPageSize", TEAMS_DEFAULT_PAGING.getPageSize());
        return mav;
    }

    @ResponseBody
    @RequestMapping(value = "/table", params = RequestParams.S_ECHO_PARAM, method = RequestMethod.GET)
    public DataTableModel getTable(final DataTableDrawParameters params, final Locale locale) {
        LOGGER.trace("getTable called ");

        DataTableSorting sorting = createSorting(params, userMapper);
        Filtering filtering = new DataTableFiltering(params);

        return getTableModel(sorting, filtering, params.getsEcho(), locale);

    }

    private DataTableModel getTableModel(PagingAndSorting sorting, Filtering filtering, String sEcho,
            Locale locale) {
        PagedCollectionHolder<List<User>> holder = adminService.findAllUsersFiltered(sorting, filtering);

        return new UserDataTableModelBuilder(locale).buildDataModel(holder, sEcho);
    }

    @ResponseBody
    @RequestMapping(value = "/new", method = RequestMethod.POST, params = "password")
    public void addUser(@ModelAttribute("add-user") @Valid UserForm userForm) {
        if (!currentProviderFeatures().isManagedPassword()) {
            adminService.addUser(userForm.getUser(), userForm.getGroupId(), userForm.getPassword());

        } else {
            // If this happens, it's either a bug or a forged request
            LOGGER.warn(
                    "Received a password while passwords are managed by auth provider. This is either a bug or a forged request. User form : {}",
                    ToStringBuilder.reflectionToString(userForm));
            throw new IllegalArgumentException(
                    "Received a password while passwords are managed by auth provider. This is either a bug or a forged request.");
        }
    }

    @ResponseBody
    @RequestMapping(value = "/new", method = RequestMethod.POST, params = "noPassword")
    public void addUserWithoutCredentials(@ModelAttribute("add-user") @Valid UserForm userForm) {
        if (currentProviderFeatures().isManagedPassword()) {
            adminService.createUserWithoutCredentials(userForm.getUser(), userForm.getGroupId());

        } else {
            // If this happens, it's either a bug or a forged request
            LOGGER.warn(
                    "Received no password while passwords are managed by Squash. This is either a bug or a forged request. User form : {}",
                    ToStringBuilder.reflectionToString(userForm));
            throw new IllegalArgumentException(
                    "Received no password while passwords are managed by Squash. This is either a bug or a forged request.");
        }
    }

    @SuppressWarnings("rawtypes")
    private DataTableSorting createSorting(final DataTableDrawParameters params, final DatatableMapper mapper) {
        return new DataTableSorting(params, mapper);
    }

    @ResponseBody
    @RequestMapping(value = USER_URLS + "/deactivate", method = RequestMethod.POST)
    public void deactivateUsers(@PathVariable("userIds") List<Long> userIds) {
        adminService.deactivateUsers(userIds);
    }

    @ResponseBody
    @RequestMapping(value = USER_URLS + "/activate", method = RequestMethod.POST)
    public void activateUsers(@PathVariable("userIds") List<Long> userIds) {
        adminService.activateUsers(userIds);
    }

    @ResponseBody
    @RequestMapping(value = USER_URLS, method = RequestMethod.DELETE)
    public void deleteUsers(@PathVariable("userIds") List<Long> userIds) {
        adminService.deleteUsers(userIds);
    }

    /**
     * Will return a view for the user of the given id
     *
     * @param userId
     */
    @RequestMapping(value = USER_URL + "/info", method = RequestMethod.GET)
    public String getUserInfos(@PathVariable(USER_ID) long userId, Model model) {
        User user = adminService.findUserById(userId);
        List<UsersGroup> usersGroupList = adminService.findAllUsersGroupOrderedByQualifiedName();

        List<?> permissionModel = createPermissionTableModel(userId, new DefaultPagingAndSorting(),
                DefaultFiltering.NO_FILTERING, "").getAaData();

        List<PermissionGroupModel> pgm = getPermissionGroupModels(userId);
        List<ProjectModel> pm = getProjectModels(userId);

        model.addAttribute("usersGroupList", usersGroupList);
        model.addAttribute("user", user);
        model.addAttribute("permissionList", pgm);
        model.addAttribute("myprojectList", pm);
        model.addAttribute("permissions", permissionModel);

        return "user-modification.html";
    }

    @ResponseBody
    @RequestMapping(value = USER_URL + "/change-group", method = RequestMethod.POST)
    public void changeUserGroup(@PathVariable long userId, @RequestParam long groupId) {
        adminService.setUserGroupAuthority(userId, groupId);
    }

    @RequestMapping(value = USER_URL, method = RequestMethod.POST, params = { "id=user-login",
            VALUE }, produces = "text/plain;charset=UTF-8")
    @ResponseBody
    public String updateLogin(@ModelAttribute @Valid UserLoginForm userLoginform, @PathVariable long userId) {
        String userLogin = userLoginform.getValue();
        adminService.modifyUserLogin(userId, userLogin);
        return HtmlUtils.htmlEscape(userLogin);
    }

    @RequestMapping(value = USER_URL, method = RequestMethod.POST, params = { "id=user-first-name",
            VALUE }, produces = "text/plain;charset=UTF-8")
    @ResponseBody
    public String updateFirstName(@RequestParam(VALUE) String firstName, @PathVariable long userId) {
        adminService.modifyUserFirstName(userId, firstName);
        return HtmlUtils.htmlEscape(firstName);
    }

    @RequestMapping(value = USER_URL, method = RequestMethod.POST, params = { "id=user-last-name",
            VALUE }, produces = "text/plain;charset=UTF-8")
    @ResponseBody
    public String updateLastName(@RequestParam(VALUE) String lastName, @PathVariable long userId) {
        adminService.modifyUserLastName(userId, lastName);
        return HtmlUtils.htmlEscape(lastName);
    }

    @RequestMapping(value = USER_URL, method = RequestMethod.POST, params = { "id=user-email",
            VALUE }, produces = "text/plain;charset=UTF-8")
    @ResponseBody
    public String updateEmail(@RequestParam(VALUE) String email, @PathVariable long userId) {
        adminService.modifyUserEmail(userId, email);
        return HtmlUtils.htmlEscape(email);
    }

    @RequestMapping(value = USER_URL, method = RequestMethod.POST, params = "password")
    @ResponseBody
    public void resetPassword(@ModelAttribute @Valid PasswordResetForm form, @PathVariable long userId) {
        LOGGER.trace("Reset password for user #" + userId);
        adminService.resetUserPassword(userId, form.getPassword());
    }

    @RequestMapping(value = USER_URL + "/authentication", method = RequestMethod.PUT, params = "password")
    @ResponseBody
    public void createAuthentication(@ModelAttribute @Valid PasswordResetForm form, @PathVariable long userId) {
        LOGGER.trace("Create authentication for user #" + userId);
        if (!currentProviderFeatures().isManagedPassword()) {
            adminService.createAuthentication(userId, form.getPassword());
        }
        // when password are managed, we should not create internal
        // authentications.
    }

    // *********************************************************************************
    @ResponseBody
    @RequestMapping(value = USER_URL + "/add-permission", method = RequestMethod.POST)
    public void addNewPermission(@RequestParam("project") long projectId, @PathVariable long userId,
            @RequestParam String permission) {
        permissionService.addNewPermissionToProject(userId, projectId, permission);
    }

    @ResponseBody
    @RequestMapping(value = USER_URL + "/remove-permission", method = RequestMethod.POST)
    public void removePermission(@RequestParam("project") List<Long> projectIds,
            @PathVariable(USER_ID) long userId) {
        for (Long projectId : projectIds) {
            permissionService.removeProjectPermission(userId, projectId);
        }
    }

    @ResponseBody
    @RequestMapping(value = USER_URL + "/permission-popup", method = RequestMethod.GET)
    public Map<String, Object> getPermissionPopup(@PathVariable(USER_ID) long userId) {
        return createPermissionPopupModel(userId);
    }

    @ResponseBody
    @RequestMapping(value = USER_URL
            + "/permissions", method = RequestMethod.GET, params = RequestParams.S_ECHO_PARAM)
    public DataTableModel getPermissionTableModel(DataTableDrawParameters params,
            @PathVariable(USER_ID) long userId) {
        PagingAndSorting paging = new DataTableSorting(params, permissionMapper);
        Filtering filtering = new DataTableFiltering(params);
        return createPermissionTableModel(userId, paging, filtering, params.getsEcho());
    }

    private String formatString(String arg, Locale locale) {
        if (arg == null) {
            return formatNoData(locale);
        } else {
            return arg;
        }
    }

    private String formatDate(Date date, Locale locale) {
        return messageSource.localizeDate(date, locale);

    }

    private String formatNoData(Locale locale) {
        return messageSource.noData(locale);
    }

    /**
     * Builds datatable model for users table
     */
    private final class UserDataTableModelBuilder extends DataTableModelBuilder<User> {
        /**
         *
         */
        private final Locale locale;

        /**
         * @param locale
         */
        private UserDataTableModelBuilder(Locale locale) {
            this.locale = locale;
        }

        @Override
        public Map<?, ?> buildItemData(User item) {
            AuditableMixin newP = (AuditableMixin) item;
            String group;

            if (item.getGroup() == null) {
                // just in case there is no group, even though it should not
                // happen. otherwise, breaks user admin page.
                group = "";
            } else {
                group = messageSource.internationalize(
                        "user.account.group." + item.getGroup().getQualifiedName() + ".label", locale);
                if (group == null) {
                    group = item.getGroup().getSimpleName();
                }
            }

            Map<Object, Object> result = new HashMap<>();
            result.put("user-id", item.getId());
            result.put("user-active", item.getActive());
            result.put("user-index", getCurrentIndex());
            result.put("user-login", item.getLogin());
            result.put("user-group", group);
            result.put("user-firstname", item.getFirstName());
            result.put("user-lastname", item.getLastName());
            result.put("user-email", item.getEmail());
            // Could be done with a SimpleDateFormat but substring works very well.
            result.put("user-created-on", formatDate(newP.getCreatedOn(), locale).substring(0, 10));
            result.put("user-created-by", formatString(newP.getCreatedBy(), locale));
            result.put("user-modified-on", formatDate(newP.getLastModifiedOn(), locale));
            result.put("user-modified-by", formatString(newP.getLastModifiedBy(), locale));
            result.put("empty-delete-holder", null);

            return result;
        }
    }

    @ModelAttribute("authenticationProvider")
    public AuthenticationProviderFeatures getAuthenticationProviderModelAttribute() {
        return currentProviderFeatures();
    }

    private AuthenticationProviderFeatures currentProviderFeatures() {
        return authenticationProviderContext.getCurrentProviderFeatures();
    }

}