/* * This program is part of the OpenLMIS logistics management information system platform software. * Copyright © 2013 VillageReach * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero 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 Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.  */ package org.openlmis.core.service; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import org.openlmis.core.domain.*; import org.openlmis.core.exception.DataException; import org.openlmis.core.hash.Encoder; import org.openlmis.core.repository.UserRepository; import org.openlmis.email.exception.EmailException; import org.openlmis.email.service.EmailService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.SimpleMailMessage; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; /** * Exposes the services for handling User entity. */ @Service public class UserService { static final String USER_EMAIL_NOT_FOUND = "user.email.not.found"; static final String USER_EMAIL_INCORRECT = "user.email.incorrect"; static final String PASSWORD_RESET_TOKEN_INVALID = "user.password.reset.token.invalid"; static final String USER_USERNAME_INCORRECT = "user.username.incorrect"; @Autowired private UserRepository userRepository; @Autowired private EmailService emailService; @Autowired private RoleAssignmentService roleAssignmentService; @Autowired private MessageService messageService; public static String getCommaSeparatedIds(List<Long> idList) { return idList == null ? "{}" : idList.toString().replace("[", "").replace("]", "").replace(", ", ","); } @Transactional public void create(User user, String resetPasswordLink) { save(user); if (!user.isMobileUser()) { sendUserCreationEmail(user, resetPasswordLink); } } public void createUser(User user, String passwordResetLink) { save(user); if (!user.isMobileUser()) { prepareForEmailNotification(user, passwordResetLink); } } @Transactional public void update(User user) { user.validate(); userRepository.update(user); roleAssignmentService.saveRolesForUser(user); } public LinkedHashMap getPreferences(Long userId){ List<LinkedHashMap> preferences = userRepository.getPreferences(userId); LinkedHashMap preference = new LinkedHashMap(); // transform the shape of the list for(LinkedHashMap map: preferences){ preference.put(map.get("key"), map.get("value")); } return preference; } public void sendForgotPasswordEmail(User user, String resetPasswordLink) { user = getValidatedUser(user); userRepository.deletePasswordResetTokenForUser(user.getId()); String subject = messageService.message("forgot.password.email.subject"); SimpleMailMessage emailMessage = createEmailMessage(user, resetPasswordLink, subject); sendEmail(emailMessage); } public List<User> searchUser(String searchParam, Pagination pagination) { return userRepository.searchUser(searchParam,pagination); } public User getUserWithRolesById(Long id) { User user = userRepository.getById(id); user.setHomeFacilityRoles(roleAssignmentService.getHomeFacilityRoles(id)); user.setSupervisorRoles(roleAssignmentService.getSupervisorRoles(id)); user.setAdminRole(roleAssignmentService.getAdminRole(id)); user.setReportingRole(roleAssignmentService.getReportingRole(id)); user.setAllocationRoles(roleAssignmentService.getAllocationRoles(id)); user.setReportRoles(roleAssignmentService.getReportRole(id)); user.setFulfillmentRoles(roleAssignmentService.getFulfilmentRoles(id)); return user; } public User getById(Long id) { return userRepository.getById(id); } public Long getUserIdByPasswordResetToken(String token) { Long userId = userRepository.getUserIdForPasswordResetToken(token); if (userId == null) { throw new DataException(PASSWORD_RESET_TOKEN_INVALID); } return userId; } @Transactional public void updateUserPassword(String token, String password) { Long userId = getUserIdByPasswordResetToken(token); userRepository.updateUserPasswordAndActivate(userId, Encoder.hash(password)); userRepository.deletePasswordResetTokenForUser(userId); } public User getByUserName(String userName) { return userRepository.getByUserName(userName); } public User selectUserByUserNameAndPassword(String userName, String password) { return userRepository.selectUserByUserNameAndPassword(userName, password); } private void prepareForEmailNotification(User user, String passwordResetLink) { String subject = messageService.message("account.created.email.subject"); SimpleMailMessage emailMessage = createEmailMessage(user, passwordResetLink, subject); userRepository.insertEmailNotification(emailMessage); } public void updateUserPassword(Long userId, String password) { userRepository.updateUserPassword(userId, Encoder.hash(password)); } @Transactional public void disable(Long userId, Long modifiedBy) { userRepository.disable(userId, modifiedBy); userRepository.deletePasswordResetTokenForUser(userId); } public List<User> getUsersWithRightInNodeForProgram(Program program, SupervisoryNode node, String rightName) { return userRepository.getUsersWithRightInNodeForProgram(program, node, rightName); } public List<User> getUsersWithRightInHierarchyUsingBaseNode(Long nodeId, Program program, String rightName) { return userRepository.getUsersWithRightInHierarchyUsingBaseNode(nodeId, program.getId(), rightName); } public List<User> getUsersWithRightOnWarehouse(Long id, String rightName) { return userRepository.getUsersWithRightOnWarehouse(id, rightName); } private void sendUserCreationEmail(User user, String resetPasswordLink) { String subject = messageService.message("account.created.email.subject"); SimpleMailMessage emailMessage = createEmailMessage(user, resetPasswordLink, subject); sendEmail(emailMessage); } private void save(User user) { user.validate(); userRepository.create(user); roleAssignmentService.saveRolesForUser(user); } private void sendEmail(SimpleMailMessage emailMessage) { try { emailService.queueMessage(emailMessage); } catch (EmailException e) { throw new DataException(USER_EMAIL_NOT_FOUND); } } private User getValidatedUser(User user) { if (user.getEmail() != null && !user.getEmail().equals("")) { user = userRepository.getByEmail(user.getEmail()); if (user == null || !user.getActive()) throw new DataException(USER_EMAIL_INCORRECT); } else { user = userRepository.getByUserName(user.getUserName()); if (user == null || !user.getActive()) throw new DataException(USER_USERNAME_INCORRECT); } return user; } private SimpleMailMessage createEmailMessage(User user, String resetPasswordLink, String subject) { String passwordResetToken = generateUUID(); String[] passwordResetLink = new String[]{user.getFirstName(), user.getLastName(), user.getUserName(), resetPasswordLink + passwordResetToken}; String mailBody = messageService.message("password.reset.email.body", (Object[]) passwordResetLink); userRepository.insertPasswordResetToken(user, passwordResetToken); SimpleMailMessage emailMessage = new SimpleMailMessage(); emailMessage.setSubject(subject); emailMessage.setText(mailBody); emailMessage.setTo(user.getEmail()); return emailMessage; } private String generateUUID() { return Encoder.hash(UUID.randomUUID().toString()); } public ArrayList<User> filterForActiveUsers(List<User> userList) { Set<User> users = new LinkedHashSet<>(userList); CollectionUtils.filter(users, new Predicate() { @Override public boolean evaluate(Object o) { return o != null && ((User) o).getActive(); } }); return new ArrayList<>(users); } public Integer getTotalSearchResultCount(String searchParam) { return userRepository.getTotalSearchResultCount(searchParam); } @Transactional public String updateUserPreferences(Long userId, User user, Long programId, Long facilityId, List<Long> products, Long geographicZoneId) { return userRepository.updateUserPreferences(userId, user, programId, facilityId,geographicZoneId, getCommaSeparatedIds(products)); } public List<String> getSupervisoryRights(Long userId) { return userRepository.getSupervisoryRights(userId); } }