org.ngrinder.user.controller.UserController.java Source code

Java tutorial

Introduction

Here is the source code for org.ngrinder.user.controller.UserController.java

Source

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

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.gson.annotations.Expose;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.StringUtils;
import org.ngrinder.common.constant.ControllerConstants;
import org.ngrinder.common.controller.BaseController;
import org.ngrinder.common.controller.RestAPI;
import org.ngrinder.infra.config.Config;
import org.ngrinder.model.Permission;
import org.ngrinder.model.Role;
import org.ngrinder.model.User;
import org.ngrinder.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.web.PageableDefaults;
import org.springframework.http.HttpEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;

import static org.ngrinder.common.util.CollectionUtils.newArrayList;
import static org.ngrinder.common.util.ObjectUtils.defaultIfNull;
import static org.ngrinder.common.util.Preconditions.*;

/**
 * User management controller.
 *
 * @author JunHo Yoon
 * @author Alex Quin
 * @since 3.0
 */
@Controller
@RequestMapping("/user")
public class UserController extends BaseController {

    @Autowired
    private UserService userService;

    @Autowired
    protected Config config;

    /**
     * Get user list on the given role.
     *
     * @param model    model
     * @param role     role
     * @param pageable page info
     * @param keywords search keyword.
     * @return user/userList
     */
    @PreAuthorize("hasAnyRole('A')")
    @RequestMapping({ "", "/" })
    public String getAll(ModelMap model, @RequestParam(required = false) Role role,
            @PageableDefaults Pageable pageable, @RequestParam(required = false) String keywords) {

        pageable = new PageRequest(pageable.getPageNumber(), pageable.getPageSize(),
                defaultIfNull(pageable.getSort(), new Sort(Direction.ASC, "userName")));
        Page<User> pagedUser;
        if (StringUtils.isEmpty(keywords)) {
            pagedUser = userService.getPagedAll(role, pageable);
        } else {
            pagedUser = userService.getPagedAll(keywords, pageable);
            model.put("keywords", keywords);
        }
        model.addAttribute("users", pagedUser);
        EnumSet<Role> roleSet = EnumSet.allOf(Role.class);
        model.addAttribute("roleSet", roleSet);
        model.addAttribute("role", role);
        putPageIntoModelMap(model, pageable);
        return "user/list";
    }

    /**
     * Get user creation form page.
     *
     * @param user  current user
     * @param model mode
     * @return "user/detail"
     */
    @RequestMapping("/new")
    @PreAuthorize("hasAnyRole('A') or #user.userId == #userId")
    public String openForm(User user, final ModelMap model) {
        User one = User.createNew();
        model.addAttribute("user", one);
        model.addAttribute("allowUserIdChange", true);
        model.addAttribute("allowPasswordChange", true);
        model.addAttribute("allowRoleChange", false);
        model.addAttribute("newUser", true);
        model.addAttribute("roleSet", EnumSet.allOf(Role.class));
        model.addAttribute("showPasswordByDefault", true);
        attachCommonAttribute(one, model);
        return "user/detail";
    }

    /**
     * Get user detail page.
     *
     * @param model  mode
     * @param userId user to get
     * @return "user/detail"
     */
    @RequestMapping("/{userId}")
    @PreAuthorize("hasAnyRole('A')")
    public String getOne(@PathVariable final String userId, ModelMap model) {
        User one = userService.getOne(userId);
        model.addAttribute("user", one);
        model.addAttribute("allowPasswordChange", true);
        model.addAttribute("allowRoleChange", true);
        model.addAttribute("roleSet", EnumSet.allOf(Role.class));
        model.addAttribute("showPasswordByDefault", false);
        attachCommonAttribute(one, model);
        return "user/detail";
    }

    /**
     * Get the current user profile.
     *
     * @param user  current user
     * @param model model
     * @return "user/info"
     */
    @RequestMapping("/profile")
    public String getOne(User user, ModelMap model) {
        checkNotEmpty(user.getUserId(), "UserID should not be NULL!");
        User one = userService.getOne(user.getUserId());
        model.addAttribute("user", one);
        model.addAttribute("allowPasswordChange", !config.isDemo());
        model.addAttribute("allowRoleChange", false);
        model.addAttribute("showPasswordByDefault", false);
        attachCommonAttribute(one, model);
        return "user/info";
    }

    /**
     * Save or Update user detail info.
     *
     * @param user        current user
     * @param model       model
     * @param updatedUser user to be updated.
     * @return "redirect:/user/list" if current user change his info, otherwise return "redirect:/"
     */
    @RequestMapping("/save")
    @PreAuthorize("hasAnyRole('A') or #user.id == #updatedUser.id")
    public String save(User user, @ModelAttribute("user") User updatedUser, ModelMap model) {
        checkArgument(updatedUser.validate());
        if (user.getRole() == Role.USER) {
            // General user can not change their role.
            User updatedUserInDb = userService.getOne(updatedUser.getUserId());
            checkNotNull(updatedUserInDb);
            updatedUser.setRole(updatedUserInDb.getRole());

            // prevent user to modify with other user id
            checkArgument(updatedUserInDb.getId().equals(updatedUser.getId()), "Illegal request to update user:%s",
                    updatedUser);
        }
        save(updatedUser);
        model.clear();
        if (user.getId().equals(updatedUser.getId())) {
            return "redirect:/";
        } else {
            return "redirect:/user/";
        }
    }

    private User save(User user) {
        if (StringUtils.isBlank(user.getPassword())) {
            return userService.saveWithoutPasswordEncoding(user);
        } else {
            return userService.save(user);
        }
    }

    /**
     * Delete users.
     *
     * @param model   model
     * @param userIds comma separated user ids.
     * @return "redirect:/user/"
     */
    @PreAuthorize("hasAnyRole('A')")
    @RequestMapping("/delete")
    public String delete(User user, @RequestParam String userIds, ModelMap model) {
        String[] ids = userIds.split(",");
        for (String eachId : Arrays.asList(ids)) {
            if (!user.getUserId().equals(eachId)) {
                userService.delete(eachId);
            }
        }
        model.clear();
        return "redirect:/user/";
    }

    /**
     * Get the follower list.
     *
     * @param user     current user
     * @param keywords search keyword.
     * @return json message
     */
    @RestAPI
    @RequestMapping("/api/switch_options")
    public HttpEntity<String> switchOptions(User user, @RequestParam(required = true) final String keywords) {
        return toJsonHttpEntity(getSwitchableUsers(user, keywords));
    }

    /**
     * Get the follower list.
     *
     * @param user  current user
     * @param model model
     * @return json message
     */
    @RequestMapping("/switch_options")
    public String switchOptions(User user, ModelMap model) {
        model.addAttribute("switchableUsers", getSwitchableUsers(user, ""));
        return "user/switch_options";
    }

    private List<UserSearchResult> getSwitchableUsers(User user, String keywords) {
        List<UserSearchResult> result = newArrayList();
        if (user.getRole().hasPermission(Permission.SWITCH_TO_ANYONE)) {
            for (User each : userService.getPagedAll(keywords, new PageRequest(0, 10))) {
                result.add(new UserSearchResult(each));
            }
        } else {
            User currUser = userService.getOne(user.getUserId());
            for (User each : currUser.getOwners()) {
                result.add(new UserSearchResult(each));
            }
        }
        return result;
    }

    /**
     * Switch user identity.
     *
     * @param model    model
     * @param to       the user to whom a user will switch
     * @param response response
     * @return redirect:/perftest/
     */
    @RequestMapping("/switch")
    public String switchUser(@RequestParam(required = false, defaultValue = "") String to,
            HttpServletRequest request, HttpServletResponse response, ModelMap model) {
        Cookie cookie = new Cookie("switchUser", to);
        cookie.setPath("/");
        // Delete Cookie if empty switchUser
        if (StringUtils.isEmpty(to)) {
            cookie.setMaxAge(0);
        }

        response.addCookie(cookie);
        model.clear();
        final String referer = request.getHeader("referer");
        return "redirect:" + StringUtils.defaultIfBlank(referer, "/");
    }

    /**
     * Get user list that current user will be shared, excluding current user.
     *
     * @param user  current user
     * @param model model
     */
    protected void attachCommonAttribute(User user, ModelMap model) {
        List list = user.getFollowers() == null ? Lists.newArrayList() : user.getFollowers();
        model.addAttribute("followers", Lists.transform(list, new Function<User, UserSearchResult>() {
            public UserSearchResult apply(User user) {
                return new UserSearchResult(user);
            }
        }));
        model.addAttribute("allowShareChange", true);
        model.addAttribute("userSecurityEnabled", config.isUserSecurityEnabled());
    }

    /**
     * Check if the given user id already exists.
     *
     * @param userId userId to be checked
     * @return success json if true.
     */
    @RestAPI
    @PreAuthorize("hasAnyRole('A')")
    @RequestMapping("/api/{userId}/check_duplication")
    public HttpEntity<String> checkDuplication(@PathVariable String userId) {
        User user = userService.getOne(userId);
        return (user == null) ? successJsonHttpEntity() : errorJsonHttpEntity();
    }

    /**
     * Get users by the given role.
     *
     * @param role user role
     * @return json message
     */
    @RestAPI
    @PreAuthorize("hasAnyRole('A')")
    @RequestMapping(value = { "/api/", "/api" }, method = RequestMethod.GET)
    public HttpEntity<String> getAll(Role role) {
        return toJsonHttpEntity(userService.getAll(role));
    }

    /**
     * Get the user by the given user id.
     *
     * @param userId user id
     * @return json message
     */
    @RestAPI
    @PreAuthorize("hasAnyRole('A')")
    @RequestMapping(value = "/api/{userId}", method = RequestMethod.GET)
    public HttpEntity<String> getOne(@PathVariable("userId") String userId) {
        return toJsonHttpEntity(userService.getOne(userId));
    }

    /**
     * Create an user.
     *
     * @param newUser new user
     * @return json message
     */
    @RestAPI
    @PreAuthorize("hasAnyRole('A')")
    @RequestMapping(value = { "/api/", "/api" }, method = RequestMethod.POST)
    public HttpEntity<String> create(@ModelAttribute("user") User newUser) {
        checkNull(newUser.getId(), "User DB ID should be null");
        return toJsonHttpEntity(save(newUser));
    }

    /**
     * Update the user.
     *
     * @param userId user id
     * @param update update user
     * @return json message
     */
    @RestAPI
    @PreAuthorize("hasAnyRole('A')")
    @RequestMapping(value = "/api/{userId}", method = RequestMethod.PUT)
    public HttpEntity<String> update(@PathVariable("userId") String userId, User update) {
        update.setUserId(userId);
        checkNull(update.getId(), "User DB ID should be null");
        return toJsonHttpEntity(save(update));
    }

    /**
     * Delete the user by the given userId.
     *
     * @param userId user id
     * @return json message
     */
    @RestAPI
    @PreAuthorize("hasAnyRole('A')")
    @RequestMapping(value = "/api/{userId}", method = RequestMethod.DELETE)
    public HttpEntity<String> delete(User user, @PathVariable("userId") String userId) {
        if (!user.getUserId().equals(userId)) {
            userService.delete(userId);
        }
        return successJsonHttpEntity();
    }

    /**
     * Search user list on the given keyword.
     *
     * @param pageable page info
     * @param keywords search keyword.
     * @return json message
     */
    @RestAPI
    @RequestMapping(value = "/api/search", method = RequestMethod.GET)
    public HttpEntity<String> search(User user, @PageableDefaults Pageable pageable,
            @RequestParam(required = true) String keywords) {
        pageable = new PageRequest(pageable.getPageNumber(), pageable.getPageSize(),
                defaultIfNull(pageable.getSort(), new Sort(Direction.ASC, "userName")));
        Page<User> pagedUser = userService.getPagedAll(keywords, pageable);
        List<UserSearchResult> result = newArrayList();
        for (User each : pagedUser) {
            result.add(new UserSearchResult(each));
        }

        final String currentUserId = user.getUserId();
        CollectionUtils.filter(result, new Predicate() {
            @Override
            public boolean evaluate(Object object) {
                UserSearchResult each = (UserSearchResult) object;
                return !(each.getId().equals(currentUserId)
                        || each.getId().equals(ControllerConstants.NGRINDER_INITIAL_ADMIN_USERID));
            }
        });

        return toJsonHttpEntity(result);
    }

    public static class UserSearchResult {
        @Expose
        final private String id;

        @Expose
        final private String text;

        public UserSearchResult(User user) {
            id = user.getUserId();
            final String email = user.getEmail();
            final String userName = user.getUserName();
            if (StringUtils.isEmpty(email)) {
                this.text = userName + " (" + id + ")";
            } else {
                this.text = userName + " (" + email + " / " + id + ")";
            }
        }

        public String getText() {
            return text;
        }

        public String getId() {
            return id;
        }
    }
}