package org.activityinfo.server.command.handler;
/*
* #%L
* ActivityInfo Server
* %%
* Copyright (C) 2009 - 2013 UNICEF
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import com.google.inject.Inject;
import org.activityinfo.legacy.shared.command.UpdateUserPermissions;
import org.activityinfo.legacy.shared.command.result.CommandResult;
import org.activityinfo.legacy.shared.exception.CommandException;
import org.activityinfo.legacy.shared.exception.IllegalAccessCommandException;
import org.activityinfo.legacy.shared.model.UserPermissionDTO;
import org.activityinfo.server.database.hibernate.dao.*;
import org.activityinfo.server.database.hibernate.entity.User;
import org.activityinfo.server.database.hibernate.entity.UserDatabase;
import org.activityinfo.server.database.hibernate.entity.UserPermission;
import org.activityinfo.server.mail.InvitationMessage;
import org.activityinfo.server.mail.MailSender;
import org.activityinfo.server.mail.Message;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author Alex Bertram
* @see org.activityinfo.legacy.shared.command.UpdateUserPermissions
*/
public class UpdateUserPermissionsHandler implements CommandHandler<UpdateUserPermissions> {
// TODO: this needs to be pushed down into the domain layer, it doesn't
// belong here at the endpoint layer
private final UserDAO userDAO;
private final UserDatabaseDAO databaseDAO;
private final PartnerDAO partnerDAO;
private final UserPermissionDAO permDAO;
private final MailSender mailSender;
private static final Logger logger = Logger.getLogger(UpdateUserPermissionsHandler.class.getName());
@Inject
public UpdateUserPermissionsHandler(UserDatabaseDAO databaseDAO,
PartnerDAO partnerDAO,
UserDAO userDAO,
UserPermissionDAO permDAO,
MailSender mailSender) {
this.userDAO = userDAO;
this.partnerDAO = partnerDAO;
this.permDAO = permDAO;
this.mailSender = mailSender;
this.databaseDAO = databaseDAO;
}
@Override
public CommandResult execute(UpdateUserPermissions cmd, User executingUser) throws CommandException {
UserDatabase database = databaseDAO.findById(cmd.getDatabaseId());
UserPermissionDTO dto = cmd.getModel();
/*
* First check that the current user has permission to add users to to
* the queries
*/
boolean isOwner = executingUser.getId() == database.getOwner().getId();
if (!isOwner) {
verifyAuthority(cmd, queryUserPermission(executingUser, database));
}
User user = null;
if (userDAO.doesUserExist(dto.getEmail())) {
user = userDAO.findUserByEmail(dto.getEmail());
}
if (user == null) {
user = createNewUser(executingUser, dto);
}
/*
* Does the permission record exist ?
*/
UserPermission perm = queryUserPermission(user, database);
if (perm == null) {
perm = new UserPermission(database, user);
doUpdate(perm, dto, isOwner, queryUserPermission(executingUser, database));
permDAO.persist(perm);
} else {
doUpdate(perm, dto, isOwner, queryUserPermission(executingUser, database));
}
return null;
}
private UserPermission queryUserPermission(User user, UserDatabase database) {
return permDAO.findUserPermissionByUserIdAndDatabaseId(user.getId(), database.getId());
}
private User createNewUser(User executingUser, UserPermissionDTO dto) throws CommandException {
if (executingUser.getId() == 0) {
throw new AssertionError("executingUser.id == 0!");
}
if (executingUser.getName() == null) {
throw new AssertionError("executingUser.name == null!");
}
User user = UserDAOImpl.createNewUser(dto.getEmail(), dto.getName(), executingUser.getLocale());
user.setInvitedBy(executingUser);
userDAO.persist(user);
try {
Message message = mailSender.createMessage(new InvitationMessage(user, executingUser));
message.replyTo(executingUser.getEmail(), executingUser.getName());
mailSender.send(message);
} catch (Exception e) {
logger.log(Level.SEVERE, "Could not send invitation mail", e);
throw new CommandException("Failed to send invitation email");
}
return user;
}
/**
* Verifies that the user executing the command has the permission to do
* assign these permissions.
* <p/>
* Static and visible for testing
*
* @param cmd
* @param executingUserPermissions
* @throws IllegalAccessCommandException
*/
public static void verifyAuthority(UpdateUserPermissions cmd,
UserPermission executingUserPermissions) throws IllegalAccessCommandException {
if (!executingUserPermissions.isAllowManageUsers()) {
throw new IllegalAccessCommandException("Current user does not have the right to manage other users");
}
if (!executingUserPermissions.isAllowManageAllUsers() &&
executingUserPermissions.getPartner().getId() != cmd.getModel().getPartner().getId()) {
throw new IllegalAccessCommandException(
"Current user does not have the right to manage users from other partners");
}
if (!executingUserPermissions.isAllowDesign() && cmd.getModel().getAllowDesign()) {
throw new IllegalAccessCommandException("Current user does not have the right to grant design privileges");
}
if (!executingUserPermissions.isAllowManageAllUsers() &&
(cmd.getModel().getAllowViewAll() || cmd.getModel().getAllowEditAll() ||
cmd.getModel().getAllowManageAllUsers())) {
throw new IllegalAccessCommandException(
"Current user does not have the right to grant viewAll, editAll, or manageAllUsers privileges");
}
}
protected void doUpdate(UserPermission perm,
UserPermissionDTO dto,
boolean isOwner,
UserPermission executingUserPermissions) {
perm.setPartner(partnerDAO.findById(dto.getPartner().getId()));
perm.setAllowView(dto.getAllowView());
perm.setAllowEdit(dto.getAllowEdit());
perm.setAllowManageUsers(dto.getAllowManageUsers());
// If currentUser does not have the manageAllUsers permission, then
// careful not to overwrite permissions that may have been granted by
// other users with greater permissions
// The exception is when a user with partner-level user management
// rights
// (manageUsers but not manageAllUsers) removes view or edit permissions
// from
// an existing user who had been previously granted viewAll or editAll
// rights
// by a user with greater permissions.
//
// In this case, the only logical outcome (I think) is that
if (isOwner || executingUserPermissions.isAllowManageAllUsers() || !dto.getAllowView()) {
perm.setAllowViewAll(dto.getAllowViewAll());
}
if (isOwner || executingUserPermissions.isAllowManageAllUsers() || !dto.getAllowEdit()) {
perm.setAllowEditAll(dto.getAllowEditAll());
}
if (isOwner || executingUserPermissions.isAllowManageAllUsers()) {
perm.setAllowManageAllUsers(dto.getAllowManageAllUsers());
}
if (isOwner || executingUserPermissions.isAllowDesign()) {
perm.setAllowDesign(dto.getAllowDesign());
}
perm.setLastSchemaUpdate(new Date());
}
}