package com.aperture_software.glados_wiki.webmvc.controllers;
import com.aperture_software.glados_wiki.entities.Group;
import com.aperture_software.glados_wiki.entities.User;
import com.aperture_software.glados_wiki.services.GroupService;
import com.aperture_software.glados_wiki.services.TimeZoneService;
import com.aperture_software.glados_wiki.services.UserService;
import com.aperture_software.glados_wiki.support.InvocationResult;
import com.aperture_software.glados_wiki.support.Pagination;
import com.aperture_software.glados_wiki.webmvc.controllers.user_admin.UserAdminListParam;
import com.aperture_software.glados_wiki.webmvc.controllers.user_admin.UserListPaginationToLinkFunction;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by jhyun on 14. 1. 4.
*/
@RequestMapping(value = "/admin/user")
@Controller
public class UserAdminController {
private static Logger LOG = LoggerFactory.getLogger(UserAdminController.class);
@Autowired
private UserService userService;
@Autowired
private TimeZoneService timeZoneService;
@Autowired
private GroupService groupService;
@RequiresRoles(GroupService.ADMIN_ROLE)
@RequestMapping(value = "list")
public ModelAndView list(ModelMap m,
@ModelAttribute("userAdminListParam") UserAdminListParam listParam) {
//
List<User> l = userService.list(
Optional.<String>absent(), Optional.<String>absent(),
listParam.getOffset(), listParam.getLimit());
m.put("users", l);
//
long c = userService.count(Optional.<String>absent(), Optional.<String>absent());
Pagination p = new Pagination(c, listParam.getOffset(), listParam.getLimit());
m.put("usersPagination", p);
//
UserListPaginationToLinkFunction pf = new UserListPaginationToLinkFunction();
pf.setSearchTerm(listParam.getSearchTermAsOptional());
pf.setGroupName(listParam.getGroupNameAsOptional());
pf.setPagination(p);
m.put("usersPaginationToLinkFunction", pf);
//
return new ModelAndView("admin/user/list", m);
}
@RequiresRoles(GroupService.ADMIN_ROLE)
@RequestMapping(value = "form")
public ModelAndView form(ModelMap m,
@RequestParam(value = "username", required = false, defaultValue = "") final String username) {
//
if (false == Strings.isNullOrEmpty(username)) {
Optional<User> u = userService.getByUsername(username);
if (u.isPresent()) {
m.put("user", u.get());
}
} else {
m.put("user", new User());
}
//
m.put("TIMEZONE_IDS", timeZoneService.sortedTimeZoneIds());
m.put("EVERYONE_GROUP", GroupService.EVERYONE_ROLE);
//
m.put("groups", groupService.list(Optional.<String>absent(), 0, Integer.MAX_VALUE));
//
return new ModelAndView("admin/user/form", m);
}
@ResponseBody
@RequiresRoles(GroupService.ADMIN_ROLE)
@RequestMapping(value = "insert", produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.POST})
public InvocationResult insert(@RequestParam(value = "username", required = true) final String username,
@RequestParam(value = "email", required = true) final String email,
@RequestParam(value = "password", required = false, defaultValue = "*") final String password,
@RequestParam(value = "description", required = true) final String description,
@RequestParam(value = "timezone", required = true) final String timezone,
@RequestParam(value = "groups", required = false) final List<String> groups) {
//
InvocationResult invocationResult = new InvocationResult();
invocationResult.setOk(true);
if (checkBeforeInsert(username, email, password, timezone, invocationResult)) return invocationResult;
//
Optional<User> u = userService.create(username, email);
User u2 = u.get();
// set password
userService.setPassword(u2, password);
// description, timezone.
u2.setDescription(description);
u2.setTimezone(timezone);
u2.setEnabled(false);
userService.update(u2);
// groups.
addGroups(groups, u2);
userService.update(u2);
//
return invocationResult;
}
private void addGroups(List<String> groups, User u2) {
if (groups != null) {
for (String groupName : groups) {
Optional<Group> g = groupService.getByName(groupName);
if (g.isPresent()) {
u2.getGroups().add(g.get());
} else {
LOG.warn(String.format("SPECIFIED GROUP [%s] NOT FOUND!!! (SKIP)", groupName));
}
}
}
}
private boolean checkBeforeInsert(String username, String email, String password, String timezone, InvocationResult invocationResult) {
// check username uniqueness.
if (Strings.isNullOrEmpty(username)) {
invocationResult.setOk(false);
invocationResult.setErrorMessage("Please specify username.");
return true;
}
if (userService.getByUsername(username).isPresent()) {
invocationResult.setOk(false);
invocationResult.setErrorMessage("Username is already taken.");
return true;
}
// check email uniqueness.
if (Strings.isNullOrEmpty(email)) {
invocationResult.setOk(false);
invocationResult.setErrorMessage("Please specify email.");
return true;
}
if (userService.countByEmail(email) > 0) {
invocationResult.setOk(false);
invocationResult.setErrorMessage("Already used email.");
return true;
}
// timezone check.
if (false == timeZoneService.sortedTimeZoneIds().contains(timezone)) {
invocationResult.setOk(false);
invocationResult.setErrorMessage("Invalid timezone.");
return true;
}
return false;
}
private boolean checkBeforeUpdate(String username, String timezone, InvocationResult invocationResult) {
// timezone check.
if (false == timeZoneService.sortedTimeZoneIds().contains(timezone)) {
invocationResult.setOk(false);
invocationResult.setErrorMessage("Invalid timezone.");
return true;
}
return false;
}
@ResponseBody
@RequiresRoles(GroupService.ADMIN_ROLE)
@RequestMapping(value = "update", produces = {MediaType.APPLICATION_JSON_VALUE}, method = {RequestMethod.POST})
public InvocationResult update(@RequestParam(value = "username", required = true) final String username,
@RequestParam(value = "description", required = true) final String description,
@RequestParam(value = "timezone", required = true) final String timezone,
@RequestParam(value = "groups", required = false) final List<String> groups) {
//
InvocationResult invocationResult = new InvocationResult();
invocationResult.setOk(true);
if (checkBeforeUpdate(username, timezone, invocationResult)) return invocationResult;
//
Optional<User> u = userService.getByUsername(username);
User u2 = u.get();
//
u2.setDescription(description);
u2.setTimezone(timezone);
//
Optional<Group> gEveryone = groupService.getByName(GroupService.EVERYONE_ROLE);
u2.setGroups(new ArrayList<Group>());
if (gEveryone.isPresent()) {
u2.getGroups().add(gEveryone.get());
} else {
LOG.warn(String.format("GROUP [%s] NOT FOUND, SKIP.", GroupService.EVERYONE_ROLE));
}
addGroups(groups, u2);
userService.update(u2);
//
return invocationResult;
}
@RequiresRoles(GroupService.ADMIN_ROLE)
@ResponseBody
@RequestMapping(value = "delete/{username}", produces = {MediaType.TEXT_PLAIN_VALUE})
public String delete(@PathVariable("username") final String username) throws Exception {
Optional<User> u = userService.getByUsername(username);
if (u.isPresent()) {
userService.delete(u.get());
return "DELETED.";
} else {
throw new Exception(String.format("USER NOT FOUND [%s]", username));
}
}
@RequiresRoles(GroupService.ADMIN_ROLE)
@ResponseBody
@RequestMapping(value = "changePassword/{username}", produces = {MediaType.TEXT_PLAIN_VALUE})
public String changePassword(@PathVariable("username") final String username,
@RequestParam(value = "newPassword", required = true) final String newPassword) throws Exception {
//
Optional<User> u = userService.getByUsername(username);
if (false == u.isPresent()) {
throw new Exception(String.format("USER NOT FOUND [%s]", username));
}
//
User u2 = u.get();
userService.setPassword(u2, newPassword);
//
return "OK. CHANGED.";
}
@RequiresRoles(GroupService.ADMIN_ROLE)
@ResponseBody
@RequestMapping(value = "toggleEnabled/{username}", produces = {MediaType.TEXT_PLAIN_VALUE})
public String toggleEnbaled(@PathVariable("username") final String username,
@RequestParam(value = "enabled", required = true) final boolean enabled) throws Exception {
//
Optional<User> u = userService.getByUsername(username);
if (false == u.isPresent()) {
throw new Exception(String.format("USER NOT FOUND [%s]", username));
}
//
User u2 = u.get();
u2.setEnabled(enabled);
userService.update(u2);
//
return "OK. CHANGED.";
}
}