/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* https://github.com/keeps/roda
*/
package org.roda.wui.api.controllers;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.roda.core.RodaCoreFactory;
import org.roda.core.common.Messages;
import org.roda.core.common.notifications.EmailNotificationProcessor;
import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.exceptions.AlreadyExistsException;
import org.roda.core.data.exceptions.AuthorizationDeniedException;
import org.roda.core.data.exceptions.EmailAlreadyExistsException;
import org.roda.core.data.exceptions.GenericException;
import org.roda.core.data.exceptions.IllegalOperationException;
import org.roda.core.data.exceptions.InvalidTokenException;
import org.roda.core.data.exceptions.NotFoundException;
import org.roda.core.data.exceptions.UserAlreadyExistsException;
import org.roda.core.data.v2.log.LogEntry.LOG_ENTRY_STATE;
import org.roda.core.data.v2.notifications.Notification;
import org.roda.core.data.v2.user.Group;
import org.roda.core.data.v2.user.User;
import org.roda.wui.client.browse.bundle.UserExtraBundle;
import org.roda.wui.common.ControllerAssistant;
import org.roda.wui.common.RodaWuiController;
import org.roda.wui.common.server.ServerTools;
import org.w3c.util.DateParser;
public class UserManagement extends RodaWuiController {
private UserManagement() {
super();
}
public static User retrieveUser(User user, String username)
throws AuthorizationDeniedException, GenericException, NotFoundException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// check user permissions
controllerAssistant.checkRoles(user);
// delegate
User ret = UserManagementHelper.retrieveUser(username);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_USERNAME_PARAM,
username);
return ret;
}
public static Group retrieveGroup(User user, String groupname)
throws AuthorizationDeniedException, GenericException, NotFoundException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// check user permissions
controllerAssistant.checkRoles(user);
// delegate
Group ret = UserManagementHelper.retrieveGroup(groupname);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_GROUPNAME_PARAM,
groupname);
return ret;
}
public static List<Group> listAllGroups(User user) throws AuthorizationDeniedException, GenericException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// check user permissions
controllerAssistant.checkRoles(user);
// delegate
List<Group> ret = UserManagementHelper.listAllGroups();
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS);
return ret;
}
public static User registerUser(User user, String password, UserExtraBundle extra, String localeString,
String servletPath) throws GenericException, UserAlreadyExistsException, EmailAlreadyExistsException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// delegate
User ret = UserManagementHelper.registerUser(user, password, extra, localeString, servletPath);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_USER_PARAM, user);
return ret;
}
public static User createUser(User user, User newUser, String password, UserExtraBundle extra)
throws AuthorizationDeniedException, NotFoundException, GenericException, EmailAlreadyExistsException,
UserAlreadyExistsException, IllegalOperationException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// check user permissions
controllerAssistant.checkRoles(user);
// delegate
User ret = UserManagementHelper.createUser(newUser, password, extra);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_USER_PARAM, newUser);
return ret;
}
public static void updateMyUser(User user, User modifiedUser, String password, UserExtraBundle extra)
throws AuthorizationDeniedException, NotFoundException, AlreadyExistsException, GenericException,
IllegalOperationException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
if (!user.getId().equals(modifiedUser.getId())) {
throw new IllegalOperationException("Trying to modify user information for another user");
}
// check user permissions
controllerAssistant.checkRoles(user);
// delegate
UserManagementHelper.updateMyUser(modifiedUser, password, extra);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_USER_PARAM,
modifiedUser);
}
public static void updateUser(User user, User modifiedUser, String password, UserExtraBundle extra)
throws AuthorizationDeniedException, NotFoundException, AlreadyExistsException, GenericException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// check user permissions
controllerAssistant.checkRoles(user);
// delegate
UserManagementHelper.updateUser(modifiedUser, password, extra);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_USER_PARAM,
modifiedUser);
}
public static void deleteUser(User user, String username) throws AuthorizationDeniedException, GenericException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// check user permissions
controllerAssistant.checkRoles(user);
UserManagementHelper.deleteUser(username);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_USERNAME_PARAM,
username);
}
public static void createGroup(User user, Group group)
throws AuthorizationDeniedException, GenericException, AlreadyExistsException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// check user permissions
controllerAssistant.checkRoles(user);
// delegate
UserManagementHelper.createGroup(group);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_GROUP_PARAM, group);
}
public static void updateGroup(User user, Group group)
throws AuthorizationDeniedException, GenericException, NotFoundException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// check user permissions
controllerAssistant.checkRoles(user);
// delegate
UserManagementHelper.updateGroup(group);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_GROUP_PARAM, group);
}
public static void deleteGroup(User user, String groupname) throws AuthorizationDeniedException, GenericException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// check user permissions
controllerAssistant.checkRoles(user);
UserManagementHelper.deleteGroup(groupname);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_GROUPNAME_PARAM,
groupname);
}
// TODO: Methods bellow this line should also checkRoles? If so, a User is
// needed.
// TODO: The methods that call these methods don't have a User either.
// TODO: From where should the User come from?
// return true if notification was sent, false if the mail cannot be sent and
// the user was activated...
public static Notification sendEmailVerification(final String servletPath, final String username,
final boolean generateNewToken, String localeString) throws GenericException, NotFoundException {
final ControllerAssistant controllerAssistant = new ControllerAssistant() {};
User user = UserManagementHelper.retrieveUser(username);
if (generateNewToken) {
final UUID uuidToken = UUID.randomUUID();
final Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, 1);
final String isoDateNoMillis = DateParser.getIsoDateNoMillis(calendar.getTime());
user.setEmailConfirmationToken(uuidToken.toString());
user.setEmailConfirmationTokenExpirationDate(isoDateNoMillis);
try {
user = UserManagementHelper.updateUser(user, null, null);
} catch (final AlreadyExistsException | AuthorizationDeniedException e) {
throw new GenericException("Error updating email confirmation token - " + e.getMessage(), e);
}
}
if (user.isActive() || user.getEmailConfirmationToken() == null) {
throw new GenericException("User " + username + " is already active or email confirmation token doesn't exist.");
}
final Notification notification = sendEmailVerification(servletPath, user, localeString);
// register action
controllerAssistant.registerAction(user, getLogEntryState(notification), RodaConstants.CONTROLLER_USER_PARAM, user);
return notification;
}
private static LOG_ENTRY_STATE getLogEntryState(final Notification notification) {
final LOG_ENTRY_STATE logEntryState;
switch (notification.getState()) {
case COMPLETED:
logEntryState = LOG_ENTRY_STATE.SUCCESS;
break;
case FAILED:
logEntryState = LOG_ENTRY_STATE.FAILURE;
break;
default:
logEntryState = LOG_ENTRY_STATE.UNKNOWN;
break;
}
return logEntryState;
}
public static void confirmUserEmail(String username, String emailConfirmationToken)
throws InvalidTokenException, NotFoundException, GenericException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
User user = UserManagementHelper.confirmUserEmail(username, null, emailConfirmationToken);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_USER_PARAM, user);
}
public static void requestPasswordReset(String servletPath, String usernameOrEmail, String localeString)
throws GenericException, NotFoundException, IllegalOperationException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
String username = null;
String email = null;
if (usernameOrEmail.matches(
"^[\\w-]+(\\.[\\w-]+)*@([a-z0-9-]+(\\.[a-z0-9-]+)*?\\.[a-z]{2,6}|(\\d{1,3}\\.){3}\\d{1,3})(:\\d{4})?$")) {
email = usernameOrEmail;
} else {
username = usernameOrEmail;
}
User user = UserManagementHelper.requestPasswordReset(username, email);
sendRecoverLoginEmail(servletPath, user, localeString);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_USER_PARAM, user);
}
public static void resetUserPassword(String username, String password, String resetPasswordToken)
throws InvalidTokenException, IllegalOperationException, NotFoundException, GenericException {
ControllerAssistant controllerAssistant = new ControllerAssistant() {};
User user = UserManagementHelper.resetUserPassword(username, password, resetPasswordToken);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_USER_PARAM, user);
}
private static Notification sendEmailVerification(String servletPath, User user, String localeString)
throws GenericException {
try {
Messages messages = RodaCoreFactory.getI18NMessages(ServerTools.parseLocale(localeString));
Notification notification = new Notification();
notification.setSubject(messages.getTranslation(RodaConstants.VERIFICATION_EMAIL_TEMPLATE_SUBJECT_TRANSLATION));
notification.setFromUser(messages.getTranslation(RodaConstants.VERIFICATION_EMAIL_TEMPLATE_FROM_TRANSLATION));
notification.setRecipientUsers(Arrays.asList(user.getEmail()));
String token = user.getEmailConfirmationToken();
String username = user.getName();
String verificationURL = servletPath + "/#verifyemail";
String verificationCompleteURL = verificationURL + "/"
+ URLEncoder.encode(username, RodaConstants.DEFAULT_ENCODING) + "/" + token;
Map<String, Object> scopes = new HashMap<>();
scopes.put("username", username);
scopes.put("token", token);
scopes.put("verificationURL", verificationURL);
scopes.put("verificationCompleteURL", verificationCompleteURL);
return RodaCoreFactory.getModelService().createNotification(notification,
new EmailNotificationProcessor(RodaConstants.VERIFICATION_EMAIL_TEMPLATE, scopes, localeString));
} catch (UnsupportedEncodingException | AuthorizationDeniedException e) {
throw new GenericException("Error sending email verification", e);
}
}
private static void sendRecoverLoginEmail(String servletPath, User user, String localeString)
throws GenericException {
try {
Messages messages = RodaCoreFactory.getI18NMessages(ServerTools.parseLocale(localeString));
Notification notification = new Notification();
notification.setSubject(messages.getTranslation(RodaConstants.RECOVER_LOGIN_EMAIL_TEMPLATE_SUBJECT_TRANSLATION));
notification.setFromUser(messages.getTranslation(RodaConstants.RECOVER_LOGIN_EMAIL_TEMPLATE_FROM_TRANSLATION));
notification.setRecipientUsers(Arrays.asList(user.getEmail()));
String token = user.getResetPasswordToken();
String username = user.getName();
String recoverLoginURL = servletPath + "/#resetpassword";
String recoverLoginCompleteURL = recoverLoginURL + "/"
+ URLEncoder.encode(username, RodaConstants.DEFAULT_ENCODING) + "/" + token;
Map<String, Object> scopes = new HashMap<>();
scopes.put("username", username);
scopes.put("token", token);
scopes.put("recoverLoginURL", recoverLoginURL);
scopes.put("recoverLoginCompleteURL", recoverLoginCompleteURL);
RodaCoreFactory.getModelService().createNotification(notification,
new EmailNotificationProcessor(RodaConstants.RECOVER_LOGIN_EMAIL_TEMPLATE, scopes, localeString));
} catch (Exception e) {
throw new GenericException("Problem sending email");
}
}
public static UserExtraBundle retrieveUserExtraBundle(User user, String name)
throws AuthorizationDeniedException, GenericException, NotFoundException {
final ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// check permissions
controllerAssistant.checkRoles(user);
// delegate
UserExtraBundle extraBudle = UserManagementHelper.retrieveUserExtraBundle(name);
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS, RodaConstants.CONTROLLER_NAME_PARAM, name);
return extraBudle;
}
public static UserExtraBundle retrieveUserExtraBundle(User user) throws AuthorizationDeniedException {
final ControllerAssistant controllerAssistant = new ControllerAssistant() {};
// check permissions
controllerAssistant.checkRoles(user);
// delegate
UserExtraBundle extraBudle = UserManagementHelper.retrieveDefaultExtraBundle();
// register action
controllerAssistant.registerAction(user, LOG_ENTRY_STATE.SUCCESS);
return extraBudle;
}
}