Commit 36b2f66b authored by Aleksandr Sharaban's avatar Aleksandr Sharaban Committed by Matija Obreza

Bug #32973: XSS User profile.

E-mail address validation added.
parent 2c8578fa
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
<commons.io.version>2.4</commons.io.version> <commons.io.version>2.4</commons.io.version>
<commons.lang.version>2.6</commons.lang.version> <commons.lang.version>2.6</commons.lang.version>
<commons.logging.version>1.2</commons.logging.version> <commons.logging.version>1.2</commons.logging.version>
<commons.validator.version>1.4.0</commons.validator.version>
<jstl.version>1.2</jstl.version> <jstl.version>1.2</jstl.version>
<servlet-api.version>2.5</servlet-api.version> <servlet-api.version>2.5</servlet-api.version>
...@@ -169,6 +170,12 @@ ...@@ -169,6 +170,12 @@
<version>1.10</version> <version>1.10</version>
</dependency> </dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>${commons.validator.version}</version>
</dependency>
<!-- Logging dependencies --> <!-- Logging dependencies -->
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
......
...@@ -64,7 +64,7 @@ public interface UserService { ...@@ -64,7 +64,7 @@ public interface UserService {
UserWrapper getWrappedById(long userId) throws UserException; UserWrapper getWrappedById(long userId) throws UserException;
@PreAuthorize("hasRole('ADMINISTRATOR') || principal.user.id == #userId") @PreAuthorize("hasRole('ADMINISTRATOR') || principal.user.id == #userId")
User updateData(long userId, String name, String email); User updateData(long userId, String name, String email) throws UserException;
User getSystemUser(String string); User getSystemUser(String string);
......
...@@ -29,6 +29,7 @@ import org.apache.commons.collections4.ListUtils; ...@@ -29,6 +29,7 @@ import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.commons.validator.routines.EmailValidator;
import org.genesys2.server.exception.NoUserFoundException; import org.genesys2.server.exception.NoUserFoundException;
import org.genesys2.server.exception.NotUniqueUserException; import org.genesys2.server.exception.NotUniqueUserException;
import org.genesys2.server.exception.UserException; import org.genesys2.server.exception.UserException;
...@@ -75,6 +76,8 @@ public class UserServiceImpl implements UserService { ...@@ -75,6 +76,8 @@ public class UserServiceImpl implements UserService {
private final List<UserRole> availableRoles = ListUtils.unmodifiableList(Arrays.asList(UserRole.values())); private final List<UserRole> availableRoles = ListUtils.unmodifiableList(Arrays.asList(UserRole.values()));
private EmailValidator emailValidator = EmailValidator.getInstance();
/** /**
* Set number of milliseconds for user account lockout * Set number of milliseconds for user account lockout
*/ */
...@@ -250,8 +253,15 @@ public class UserServiceImpl implements UserService { ...@@ -250,8 +253,15 @@ public class UserServiceImpl implements UserService {
@Override @Override
@PreAuthorize("hasRole('ADMINISTRATOR') || principal.user.id == #userId") @PreAuthorize("hasRole('ADMINISTRATOR') || principal.user.id == #userId")
@Transactional(readOnly = false) @Transactional(readOnly = false, rollbackFor = NotUniqueUserException.class)
public User updateData(long userId, String name, String email) { public User updateData(long userId, String name, String email) throws UserException {
if (!emailValidator.isValid(email)) {
throw new UserException();
}
if (userPersistence.findByEmail(email) != null) {
throw new NotUniqueUserException(new Throwable(), email);
}
final User user = userPersistence.findOne(userId); final User user = userPersistence.findOne(userId);
user.setName(name); user.setName(name);
user.setEmail(email); user.setEmail(email);
......
...@@ -19,6 +19,7 @@ package org.genesys2.server.servlet.controller; ...@@ -19,6 +19,7 @@ package org.genesys2.server.servlet.controller;
import java.util.List; import java.util.List;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.genesys2.server.exception.NotUniqueUserException;
import org.genesys2.server.exception.UserException; import org.genesys2.server.exception.UserException;
import org.genesys2.server.model.impl.User; import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.EMailVerificationService; import org.genesys2.server.service.EMailVerificationService;
...@@ -36,6 +37,7 @@ import org.springframework.web.bind.annotation.PathVariable; ...@@ -36,6 +37,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller @Controller
@RequestMapping("/profile") @RequestMapping("/profile")
...@@ -163,13 +165,21 @@ public class UserProfileController extends BaseController { ...@@ -163,13 +165,21 @@ public class UserProfileController extends BaseController {
@RequestMapping(value = "/{uuid:.+}/update", method = { RequestMethod.POST }) @RequestMapping(value = "/{uuid:.+}/update", method = { RequestMethod.POST })
@PreAuthorize("hasRole('ADMINISTRATOR') || principal.user.uuid == #uuid") @PreAuthorize("hasRole('ADMINISTRATOR') || principal.user.uuid == #uuid")
public String update(ModelMap model, @PathVariable("uuid") String uuid, @RequestParam("name") String name, @RequestParam("email") String email, public String update(ModelMap model, @PathVariable("uuid") String uuid, @RequestParam("name") String name, @RequestParam("email") String email,
@RequestParam("pwd1") String pwd1, @RequestParam("pwd2") String pwd2) { @RequestParam("pwd1") String pwd1, @RequestParam("pwd2") String pwd2, RedirectAttributes redirectAttributes) {
final User user = userService.getUserByUuid(uuid); final User user = userService.getUserByUuid(uuid);
if (user == null) { if (user == null) {
throw new ResourceNotFoundException(); throw new ResourceNotFoundException();
} }
userService.updateData(user.getId(), name, email); try {
userService.updateData(user.getId(), name, email);
} catch (NotUniqueUserException e) {
redirectAttributes.addFlashAttribute("emailError", "User with e-mail address " + e.getEmail() + " already exists");
return "redirect:/profile/" + user.getUuid() + "/edit";
} catch (UserException e) {
redirectAttributes.addFlashAttribute("emailError", "E-mail address is incorrect");
return "redirect:/profile/" + user.getUuid() + "/edit";
}
if (StringUtils.isNotBlank(pwd1)) { if (StringUtils.isNotBlank(pwd1)) {
if (pwd1.equals(pwd2)) { if (pwd1.equals(pwd2)) {
......
...@@ -19,6 +19,7 @@ package org.genesys2.server.servlet.controller.admin; ...@@ -19,6 +19,7 @@ package org.genesys2.server.servlet.controller.admin;
import java.util.List; import java.util.List;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.genesys2.server.exception.NotUniqueUserException;
import org.genesys2.server.exception.UserException; import org.genesys2.server.exception.UserException;
import org.genesys2.server.model.impl.User; import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.EMailVerificationService; import org.genesys2.server.service.EMailVerificationService;
...@@ -36,6 +37,7 @@ import org.springframework.web.bind.annotation.PathVariable; ...@@ -36,6 +37,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller("adminUsersController") @Controller("adminUsersController")
@RequestMapping(UserProfileController.URLBASE) @RequestMapping(UserProfileController.URLBASE)
...@@ -153,13 +155,21 @@ public class UserProfileController extends BaseController { ...@@ -153,13 +155,21 @@ public class UserProfileController extends BaseController {
@RequestMapping(value = "/{uuid:.+}/update", method = { RequestMethod.POST }) @RequestMapping(value = "/{uuid:.+}/update", method = { RequestMethod.POST })
public String update(ModelMap model, @PathVariable("uuid") String uuid, @RequestParam("name") String name, @RequestParam("email") String email, public String update(ModelMap model, @PathVariable("uuid") String uuid, @RequestParam("name") String name, @RequestParam("email") String email,
@RequestParam("pwd1") String pwd1, @RequestParam("pwd2") String pwd2) { @RequestParam("pwd1") String pwd1, @RequestParam("pwd2") String pwd2, RedirectAttributes redirectAttributes) {
final User user = userService.getUserByUuid(uuid); final User user = userService.getUserByUuid(uuid);
if (user == null) { if (user == null) {
throw new ResourceNotFoundException(); throw new ResourceNotFoundException();
} }
userService.updateData(user.getId(), name, email); try {
userService.updateData(user.getId(), name, email);
} catch (NotUniqueUserException e) {
redirectAttributes.addFlashAttribute("emailError", "User with e-mail address " + e.getEmail() + " already exists");
return "redirect:" + URLBASE + user.getUuid() + "/edit";
} catch (UserException e) {
redirectAttributes.addFlashAttribute("emailError", "E-mail address is incorrect");
return "redirect:" + URLBASE + user.getUuid() + "/edit";
}
if (StringUtils.isNotBlank(pwd1)) { if (StringUtils.isNotBlank(pwd1)) {
if (pwd1.equals(pwd2)) { if (pwd1.equals(pwd2)) {
......
...@@ -115,7 +115,13 @@ public class UsersController extends RestController { ...@@ -115,7 +115,13 @@ public class UsersController extends RestController {
throw new ResourceNotFoundException(); throw new ResourceNotFoundException();
} }
userService.updateData(user.getId(), userData.getName(), userData.getEmail()); try {
userService.updateData(user.getId(), userData.getName(), userData.getEmail());
} catch (NotUniqueUserException e) {
LOG.warn("User with e-mail address " + e.getEmail() + " already exists");
} catch (UserException e) {
LOG.warn("E-mail address is incorrect");
}
if (StringUtils.isNotBlank(userData.getPwd1())) { if (StringUtils.isNotBlank(userData.getPwd1())) {
if (userData.getPwd1().equals(userData.getPwd2())) { if (userData.getPwd1().equals(userData.getPwd2())) {
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
<title><spring:message code="userprofile.update.title" /></title> <title><spring:message code="userprofile.update.title" /></title>
</head> </head>
<body> <body>
<c:if test="${not empty emailError}">
<div class="alert alert-danger">${emailError}</div>
</c:if>
<form role="form" class="form-horizontal validate" action="<c:url value="/admin/users/${user.uuid}/update" />" method="post"> <form role="form" class="form-horizontal validate" action="<c:url value="/admin/users/${user.uuid}/update" />" method="post">
<div class="form-group"> <div class="form-group">
<label for="name" class="col-lg-2 control-label"><spring:message code="registration.full-name" /></label> <label for="name" class="col-lg-2 control-label"><spring:message code="registration.full-name" /></label>
......
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
<spring:message code="userprofile.update.title" /> <spring:message code="userprofile.update.title" />
</h1> </h1>
<c:if test="${not empty emailError}">
<div class="alert alert-danger">${emailError}</div>
</c:if>
<form role="form" class="form-horizontal validate" action="<c:url value="/profile/${user.uuid}/update" />" method="post"> <form role="form" class="form-horizontal validate" action="<c:url value="/profile/${user.uuid}/update" />" method="post">
<div class="form-group"> <div class="form-group">
<label for="name" class="col-lg-2 control-label"><spring:message code="registration.full-name" /></label> <label for="name" class="col-lg-2 control-label"><spring:message code="registration.full-name" /></label>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment