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()); } }