Commit d25e9c9a authored by Piotr Gawron's avatar Piotr Gawron
Browse files

API for reseting password with token implemented

parent 8a812cdb
......@@ -20,7 +20,7 @@ import lcsb.mapviewer.common.Configuration;
import lcsb.mapviewer.services.interfaces.IUserService;
@RestController
@RequestMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping( produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController extends BaseController {
Logger logger = LogManager.getLogger();
......@@ -39,7 +39,7 @@ public class UserController extends BaseController {
* not authenticated. Therefore simply calling this action can be used to detect
* whether the current session is still valid.
*/
@GetMapping(value = "/isSessionValid")
@GetMapping(value = "/users/isSessionValid")
@PreAuthorize("isAuthenticated() and authentication.name != '" + Configuration.ANONYMOUS_LOGIN + "'")
public Object isSessionValid(Authentication authentication) {
Map<String, Object> result = new TreeMap<>();
......@@ -48,7 +48,7 @@ public class UserController extends BaseController {
}
@PreAuthorize("hasAnyAuthority('IS_ADMIN', 'IS_CURATOR') or #login == authentication.name")
@GetMapping(value = "/{login:.+}")
@GetMapping(value = "/users/{login:.+}")
public Map<String, Object> getUser(
@PathVariable(value = "login") String login,
@RequestParam(value = "columns", defaultValue = "") String columns) throws ObjectNotFoundException {
......@@ -56,7 +56,7 @@ public class UserController extends BaseController {
}
@PreAuthorize("hasAuthority('IS_ADMIN')")
@PatchMapping(value = "/{login}:updatePrivileges")
@PatchMapping(value = "/users/{login}:updatePrivileges")
public Map<String, Object> updatePrivileges(
@RequestBody String body,
@PathVariable(value = "login") String login) throws IOException, QueryException {
......@@ -66,7 +66,7 @@ public class UserController extends BaseController {
}
@PreAuthorize("hasAuthority('IS_ADMIN') or #login == authentication.name")
@PatchMapping(value = "/{login}:updatePreferences")
@PatchMapping(value = "/users/{login}:updatePreferences")
public Map<String, Object> updatePreferences(
@RequestBody String body,
@PathVariable(value = "login") String login) throws IOException, QueryException {
......@@ -76,7 +76,7 @@ public class UserController extends BaseController {
}
@PreAuthorize("hasAnyAuthority('IS_ADMIN', 'IS_CURATOR')")
@GetMapping(value = "/")
@GetMapping(value = "/users/")
public List<Map<String, Object>> getUsers(@RequestParam(value = "columns", defaultValue = "") String columns) {
return userRest.getUsers(columns).stream()
.sorted(Comparator.comparing(user -> (String) user.get("login"), Comparator.reverseOrder()))
......@@ -84,7 +84,7 @@ public class UserController extends BaseController {
}
@PreAuthorize("hasAuthority('IS_ADMIN') or #login == authentication.name")
@PatchMapping(value = "/{login:.+}")
@PatchMapping(value = "/users/{login:.+}")
public Map<String, Object> updateUser(
@RequestBody String body,
@PathVariable(value = "login") String login,
......@@ -95,7 +95,7 @@ public class UserController extends BaseController {
}
@PreAuthorize("hasAuthority('IS_ADMIN')")
@PostMapping(value = "/{login:.+}")
@PostMapping(value = "/users/{login:.+}")
public Map<String, Object> addUser(
@RequestBody MultiValueMap<String, Object> formData,
@PathVariable(value = "login") String login) throws QueryException {
......@@ -104,26 +104,28 @@ public class UserController extends BaseController {
}
@PreAuthorize("hasAuthority('IS_ADMIN')")
@DeleteMapping(value = "/{login:.+}")
@DeleteMapping(value = "/users/{login:.+}")
public Map<String, Object> removeUser(@PathVariable(value = "login") String login) throws QueryException {
return userRest.removeUser(login);
}
@PostMapping(value = "/{login}:requestResetPassword")
@PostMapping(value = "/users/{login}:requestResetPassword")
public Map<String, Object> requestResetPasswordToken(
@PathVariable(value = "login") String login) throws QueryException, MessagingException {
userRest.requestResetPassword(login);
Map<String, Object> result= new HashMap<>();
Map<String, Object> result = new HashMap<>();
result.put("status", "OK");
return result;
}
@PostMapping(value = ":resetPassword")
@PostMapping(value = "/users:resetPassword")
public Map<String, Object> resetPassword(
@PathVariable(value = "token") String token, String password) throws IOException, QueryException {
@RequestParam(value = "token") String token,
@RequestParam(value = "password") String password)
throws IOException, QueryException {
userRest.resetPassword(token, password);
Map<String, Object> result= new HashMap<>();
Map<String, Object> result = new HashMap<>();
result.put("status", "OK");
return result;
}
......
......@@ -17,7 +17,8 @@ import org.springframework.util.MultiValueMap;
import lcsb.mapviewer.api.*;
import lcsb.mapviewer.common.Configuration;
import lcsb.mapviewer.common.exception.*;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
import lcsb.mapviewer.common.exception.InvalidStateException;
import lcsb.mapviewer.model.map.MiriamType;
import lcsb.mapviewer.model.security.Privilege;
import lcsb.mapviewer.model.security.PrivilegeType;
......@@ -757,8 +758,12 @@ public class UserRestImpl extends BaseRestImpl {
getUserService().createResetPasswordToken(user);
}
public void resetPassword(String token, String password) {
throw new NotImplementedException();
public void resetPassword(String token, String password) throws ObjectNotFoundException {
try {
getUserService().resetPassword(token, passwordEncoder.encode(password));
} catch (InvalidArgumentException e) {
throw new ObjectNotFoundException("Invalid token", e);
}
}
}
......@@ -14,6 +14,7 @@ import org.springframework.transaction.annotation.Transactional;
import com.unboundid.ldap.sdk.LDAPException;
import lcsb.mapviewer.commands.ColorExtractor;
import lcsb.mapviewer.common.exception.InvalidArgumentException;
import lcsb.mapviewer.common.geometry.ColorParser;
import lcsb.mapviewer.model.security.Privilege;
import lcsb.mapviewer.model.security.PrivilegeType;
......@@ -29,7 +30,7 @@ import lcsb.mapviewer.services.utils.EmailSender;
public class UserService implements IUserService {
private static Logger logger = LogManager.getLogger(UserService.class);
private UserDao userDao;
private ILdapService ldapService;
private IConfigurationService configurationService;
......@@ -223,4 +224,18 @@ public class UserService implements IUserService {
}
@Override
public void resetPassword(String token, String cryptedPassword) {
ResetPasswordToken resetToken = resetPasswordTokenDao.getByToken(token);
if (resetToken != null && resetToken.getExpires().before(Calendar.getInstance())) {
resetPasswordTokenDao.delete(resetToken);
resetToken = null;
}
if (resetToken == null) {
throw new InvalidArgumentException();
}
resetToken.getUser().setCryptedPassword(cryptedPassword);
userDao.update(resetToken.getUser());
}
}
......@@ -59,4 +59,6 @@ public interface IUserService {
Map<String, Boolean> ldapAccountExistsForLogin(Collection<User> logins);
void createResetPasswordToken(User user) throws MessagingException;
void resetPassword(String token, String cryptedPassword);
}
\ No newline at end of file
......@@ -29,8 +29,7 @@ import com.google.gson.*;
import lcsb.mapviewer.model.Project;
import lcsb.mapviewer.model.security.Privilege;
import lcsb.mapviewer.model.security.PrivilegeType;
import lcsb.mapviewer.model.user.ConfigurationElementType;
import lcsb.mapviewer.model.user.User;
import lcsb.mapviewer.model.user.*;
import lcsb.mapviewer.persist.dao.ProjectDao;
import lcsb.mapviewer.persist.dao.user.ResetPasswordTokenDao;
import lcsb.mapviewer.services.interfaces.IConfigurationService;
......@@ -516,6 +515,71 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest {
}
@Test
public void resetPassword() throws Exception {
configureServerForResetPasswordRequest();
RequestBuilder request = post("/users/" + BUILT_IN_TEST_ADMIN_LOGIN + ":requestResetPassword");
mockMvc.perform(request)
.andExpect(status().is2xxSuccessful());
String newPassword = "pass2";
ResetPasswordToken token = resetPasswordTokenDao.getAll().iterator().next();
String content = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList(
new BasicNameValuePair("token", token.getToken()),
new BasicNameValuePair("password", newPassword))));
RequestBuilder resetRequest = post("/users:resetPassword")
.content(content)
.contentType(MediaType.APPLICATION_FORM_URLENCODED);
mockMvc.perform(resetRequest)
.andExpect(status().is2xxSuccessful());
createSession(BUILT_IN_TEST_ADMIN_LOGIN, newPassword);
}
@Test
public void resetPasswordWithExpredToken() throws Exception {
configureServerForResetPasswordRequest();
Calendar expires = Calendar.getInstance();
expires.add(Calendar.DATE, -1);
ResetPasswordToken token = new ResetPasswordToken(userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN),
"bla", expires);
resetPasswordTokenDao.add(token);
String content = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList(
new BasicNameValuePair("token", token.getToken()),
new BasicNameValuePair("password", "blah"))));
RequestBuilder resetRequest = post("/users:resetPassword")
.content(content)
.contentType(MediaType.APPLICATION_FORM_URLENCODED);
mockMvc.perform(resetRequest)
.andExpect(status().isNotFound());
}
@Test
public void resetPasswordWithInvalidToken() throws Exception {
configureServerForResetPasswordRequest();
String content = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList(
new BasicNameValuePair("token", "blah"),
new BasicNameValuePair("password", "???"))));
RequestBuilder resetRequest = post("/users:resetPassword")
.content(content)
.contentType(MediaType.APPLICATION_FORM_URLENCODED);
mockMvc.perform(resetRequest)
.andExpect(status().isNotFound());
}
private void configureServerForResetPasswordRequest() {
User user = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN);
user.setEmail("test@test.xyz");
......
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