net.rrm.ehour.user.service.UserServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for net.rrm.ehour.user.service.UserServiceImpl.java

Source

/*
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package net.rrm.ehour.user.service;

import com.google.common.collect.Lists;
import net.rrm.ehour.data.DateRange;
import net.rrm.ehour.domain.ProjectAssignment;
import net.rrm.ehour.domain.User;
import net.rrm.ehour.domain.UserDepartment;
import net.rrm.ehour.domain.UserRole;
import net.rrm.ehour.exception.ObjectNotFoundException;
import net.rrm.ehour.exception.ObjectNotUniqueException;
import net.rrm.ehour.persistence.user.dao.UserDao;
import net.rrm.ehour.persistence.user.dao.UserDepartmentDao;
import net.rrm.ehour.persistence.user.dao.UserRoleDao;
import net.rrm.ehour.project.service.ProjectAssignmentManagementService;
import net.rrm.ehour.report.reports.element.AssignmentAggregateReportElement;
import net.rrm.ehour.report.reports.util.ReportUtil;
import net.rrm.ehour.report.service.AggregateReportService;
import net.rrm.ehour.timesheet.service.IDeleteTimesheetEntry;
import net.rrm.ehour.util.DateUtil;
import net.rrm.ehour.util.DomainUtil;
import org.apache.commons.lang.Validate;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.encoding.MessageDigestPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author Thies Edeling (thies@te-con.nl)
 */
@Service("userService")
public class UserServiceImpl implements UserService {
    private static final Logger LOGGER = Logger.getLogger(UserServiceImpl.class);

    @Autowired
    private UserDao userDAO;
    @Autowired
    private UserDepartmentDao userDepartmentDAO;
    @Autowired
    private UserRoleDao userRoleDAO;
    @Autowired
    private ProjectAssignmentManagementService projectAssignmentManagementService;
    @Autowired
    private AggregateReportService aggregateReportService;
    @Autowired
    private IDeleteTimesheetEntry deleteTimesheetEntryService;

    @Autowired
    private MessageDigestPasswordEncoder passwordEncoder;

    @Transactional(readOnly = true)
    public User getUser(Integer userId) throws ObjectNotFoundException {
        User user = userDAO.findById(userId);
        Set<ProjectAssignment> inactiveAssignments = new HashSet<>();

        if (user != null && user.getProjectAssignments() != null) {
            splitActiveAndInactiveAssignments(user, inactiveAssignments);
        } else {
            throw new ObjectNotFoundException("User not found");
        }

        return user;
    }

    private void splitActiveAndInactiveAssignments(User user, Set<ProjectAssignment> inactiveAssignments) {
        Date currentDate = new Date();

        for (ProjectAssignment assignment : user.getProjectAssignments()) {
            DateRange assignmentRange = new DateRange(assignment.getDateStart(), assignment.getDateEnd());

            if ((!DateUtil.isDateWithinRange(currentDate, assignmentRange))
                    || (assignment.getProject() == null || !assignment.getProject().isActive())) {
                inactiveAssignments.add(assignment);
            }
        }

        user.getProjectAssignments().removeAll(inactiveAssignments);
        user.setInactiveProjectAssignments(inactiveAssignments);
    }

    @Transactional(readOnly = true)
    public User getUserAndCheckDeletability(Integer userId) throws ObjectNotFoundException {
        User user = getUser(userId);

        if ((!user.getProjectAssignments().isEmpty()) && (!user.getInactiveProjectAssignments().isEmpty())) {
            user.setDeletable(true);
        } else {
            // bummer, we need to check if the user booked any hours on the assignments
            List<Integer> assignmentIds = new ArrayList<>();

            assignmentIds.addAll(DomainUtil.getIdsFromDomainObjects(user.getProjectAssignments()));
            assignmentIds.addAll(DomainUtil.getIdsFromDomainObjects(user.getInactiveProjectAssignments()));

            List<AssignmentAggregateReportElement> aggregates = aggregateReportService
                    .getHoursPerAssignment(assignmentIds);

            user.setDeletable(ReportUtil.isEmptyAggregateList(aggregates));
        }

        LOGGER.info("Retrieved user " + user.getUsername() + ", deletable: " + user.isDeletable());

        return user;
    }

    @Transactional(readOnly = true)
    public User getUser(String username) {
        return userDAO.findByUsername(username);
    }

    @Transactional(readOnly = true)
    public List<UserDepartment> getUserDepartments() {
        return userDepartmentDAO.findAll();
    }

    @Transactional
    public UserDepartment persistUserDepartment(UserDepartment department) throws ObjectNotUniqueException {
        UserDepartment otherDept;

        otherDept = userDepartmentDAO.findOnNameAndCode(department.getName(), department.getCode());

        if (otherDept == null) {
            userDepartmentDAO.persist(department);
        } else if (otherDept.getDepartmentId().equals(department.getDepartmentId())) {
            userDepartmentDAO.merge(department);
        } else {
            throw new ObjectNotUniqueException("name/code not unique");
        }

        return department;
    }

    @Transactional(readOnly = true)
    public UserDepartment getUserDepartment(Integer departmentId) throws ObjectNotFoundException {
        UserDepartment userDepartment = userDepartmentDAO.findById(departmentId);

        if (userDepartment == null) {
            throw new ObjectNotFoundException("Department not found");
        }

        userDepartment.setDeletable(!userDepartment.getUsers().isEmpty());

        return userDepartment;
    }

    @Transactional(readOnly = true)
    public List<User> getUsers() {
        return userDAO.findUsers(false);
    }

    @Transactional(readOnly = true)
    public List<User> getActiveUsers() {
        return userDAO.findActiveUsers();
    }

    @Transactional(readOnly = true)
    public List<UserRole> getUserRoles() {
        return Lists.newArrayList(UserRole.ROLES.values());
    }

    @Transactional
    public User persistEditedUser(User user) throws ObjectNotUniqueException {
        // check username uniqueness
        User dbUser = userDAO.findByUsername(user.getUsername());

        if (dbUser != null && !dbUser.getUserId().equals(user.getUserId())) {
            throw new ObjectNotUniqueException("Username already in use");
        } else if (dbUser == null) {
            dbUser = findUserOnId(user);
        }

        dbUser.setActive(user.isActive());
        dbUser.setEmail(user.getEmail());
        dbUser.setFirstName(user.getFirstName());
        dbUser.setLastName(user.getLastName());
        dbUser.getUserDepartments().clear();
        dbUser.getUserDepartments().addAll(user.getUserDepartments());
        dbUser.setUsername(user.getUsername());

        boolean reAddPm = dbUser.getUserRoles().contains(UserRole.PROJECTMANAGER);
        dbUser.setUserRoles(user.getUserRoles());

        if (reAddPm && !user.getUserRoles().contains(UserRole.PROJECTMANAGER)) {
            dbUser.addUserRole(UserRole.PROJECTMANAGER);
        }

        userDAO.persist(dbUser);

        return dbUser;
    }

    private User findUserOnId(User user) {
        User dbUser = userDAO.findById(user.getUserId());

        if (dbUser == null) {
            throw new IllegalArgumentException(String.format("%d user ID not found", user.getUserId()));
        }
        return dbUser;
    }

    @Override
    @Transactional
    public void persistNewUser(User user, String password) throws ObjectNotUniqueException {
        // check username uniqueness
        User dbUser = userDAO.findByUsername(user.getUsername());

        if (dbUser != null && !dbUser.getUserId().equals(user.getUserId())) {
            throw new ObjectNotUniqueException("Username already in use");
        }

        // encrypt password
        user.setSalt((int) (Math.random() * 10000));
        user.setPassword(encryptPassword(password, user.getSalt()));

        userDAO.persist(user);

        // assign new users to default projects
        projectAssignmentManagementService.assignUserToDefaultProjects(user);
    }

    @Override
    @Transactional
    public void changePassword(String username, String currentPassword, String newUnencryptedPassword)
            throws BadCredentialsException {
        User user = userDAO.findByUsername(username);

        Validate.notNull(user, String.format("Can't find user with username %s", username));

        String encryptedCurrentPassword = encryptPassword(currentPassword, user.getSalt());

        if (!user.getPassword().equals(encryptedCurrentPassword)) {
            throw new BadCredentialsException("Invalid current password");
        }

        changePassword(user, newUnencryptedPassword);
    }

    @Override
    @Transactional
    public void changePassword(String username, String newUnencryptedPassword) {
        User user = userDAO.findByUsername(username);
        Validate.notNull(user, String.format("Can't find user with username %s", username));

        changePassword(user, newUnencryptedPassword);
    }

    private void changePassword(User user, String newUnencryptedPassword) {
        int salt = (int) (Math.random() * 10000);
        user.setSalt(salt);
        user.setPassword(encryptPassword(newUnencryptedPassword, salt));

        userDAO.persist(user);
    }

    private String encryptPassword(String plainPassword, Object salt) {
        return passwordEncoder.encodePassword(plainPassword, salt);
    }

    public List<User> getUsersWithEmailSet() {
        return userDAO.findAllActiveUsersWithEmailSet();
    }

    @Override
    @Transactional
    public User validateProjectManagementRoles(Integer userId) {
        User user = null;
        try {
            if (userId != null) {
                user = getAndAddPmRole(userId);
            }

            userDAO.deletePmWithoutProject();
        } catch (ObjectNotUniqueException e) {
            // won't happen
            LOGGER.error("Account already exists", e);
        }

        return user;
    }

    /**
     * Find user on id and add PM role
     */
    private User getAndAddPmRole(Integer userId) throws ObjectNotUniqueException {
        User user = userDAO.findById(userId);

        UserRole userRole = userRoleDAO.findById(UserRole.ROLE_PROJECTMANAGER);

        user.getUserRoles().add(userRole);

        userDAO.persist(user);

        return user;
    }

    @Override
    @Transactional(readOnly = true)
    public List<User> getUsers(UserRole userRole) {
        return UserUtil.filterUserOnRole(userDAO.findActiveUsers(), userRole);
    }

    @Transactional
    public void deleteUser(Integer userId) {
        User user = userDAO.findById(userId);

        deleteTimesheetEntryService.deleteAllTimesheetDataForUser(user);

        userDAO.delete(user);
    }

    @Transactional
    public void deleteDepartment(Integer departmentId) {
        UserDepartment department = userDepartmentDAO.findById(departmentId);

        LOGGER.info("Deleting department: " + department);

        for (User user : department.getUsers()) {
            LOGGER.info("Deleting user: " + user);

            deleteUser(user.getUserId());
        }

        userDepartmentDAO.delete(department);
    }

    public void setPasswordEncoder(MessageDigestPasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    public void setProjectAssignmentManagementService(
            ProjectAssignmentManagementService projectAssignmentManagementService) {
        this.projectAssignmentManagementService = projectAssignmentManagementService;
    }

    public void setUserDAO(UserDao dao) {
        userDAO = dao;
    }

    public void setUserDepartmentDAO(UserDepartmentDao dao) {
        userDepartmentDAO = dao;
    }

    public void setUserRoleDAO(UserRoleDao dao) {
        userRoleDAO = dao;
    }
}