org.jtalks.jcommune.service.transactional.TransactionalUserService.java Source code

Java tutorial

Introduction

Here is the source code for org.jtalks.jcommune.service.transactional.TransactionalUserService.java

Source

/**
 * Copyright (C) 2011  JTalks.org Team
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library 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
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package org.jtalks.jcommune.service.transactional;

import org.apache.commons.lang.RandomStringUtils;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.jtalks.common.model.dao.GroupDao;
import org.jtalks.common.model.entity.User;
import org.jtalks.jcommune.model.dao.PostDao;
import org.jtalks.jcommune.model.dao.UserDao;
import org.jtalks.jcommune.model.dto.LoginUserDto;
import org.jtalks.jcommune.model.dto.UserDto;
import org.jtalks.jcommune.model.entity.*;
import org.jtalks.jcommune.plugin.api.exceptions.NoConnectionException;
import org.jtalks.jcommune.plugin.api.exceptions.NotFoundException;
import org.jtalks.jcommune.plugin.api.exceptions.UnexpectedErrorException;
import org.jtalks.jcommune.plugin.api.service.UserReader;
import org.jtalks.jcommune.service.Authenticator;
import org.jtalks.jcommune.service.UserService;
import org.jtalks.jcommune.service.dto.UserInfoContainer;
import org.jtalks.jcommune.service.dto.UserNotificationsContainer;
import org.jtalks.jcommune.service.dto.UserSecurityContainer;
import org.jtalks.jcommune.service.exceptions.MailingFailedException;
import org.jtalks.jcommune.service.nontransactional.Base64Wrapper;
import org.jtalks.jcommune.service.nontransactional.EncryptionService;
import org.jtalks.jcommune.service.nontransactional.MailService;
import org.jtalks.jcommune.service.nontransactional.MentionedUsers;
import org.jtalks.jcommune.service.security.SecurityService;
import org.jtalks.jcommune.service.util.AuthenticationStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.prepost.PreAuthorize;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;

/**
 * User service class. This class contains method needed to manipulate with User persistent entity.
 * Note that this class also encrypts passwords during account creation, password changing, generating
 * a random password.
 *
 * @author Osadchuck Eugeny
 * @author Kirill Afonin
 * @author Alexandre Teterin
 * @author Evgeniy Naumenko
 * @author Mikhail Zaitsev
 * @author Andrei Alikov
 * @author Andrey Pogorelov
 */
public class TransactionalUserService extends AbstractTransactionalEntityService<JCUser, UserDao>
        implements UserService, UserReader {

    private static final Logger LOGGER = LoggerFactory.getLogger(TransactionalUserService.class);
    protected static final int MAX_SEARCH_USER_COUNT = 20;

    private final PostDao postDao;
    private final Authenticator authenticator;
    private final GroupDao groupDao;
    private final SecurityService securityService;
    private final MailService mailService;
    private final Base64Wrapper base64Wrapper;
    //Important, use for every password creation.
    private final EncryptionService encryptionService;

    /**
     * Create an instance of User entity based service
     *
     * @param dao               for operations with data storage
     * @param groupDao          for user group operations with data storage
     * @param securityService   for security
     * @param mailService       to send e-mails
     * @param base64Wrapper     for avatar image-related operations
     * @param encryptionService encodes user password before store
     * @param postDao           for operations with posts
     * @param authenticator     for user authentication
     */
    public TransactionalUserService(UserDao dao, GroupDao groupDao, SecurityService securityService,
            MailService mailService, Base64Wrapper base64Wrapper, EncryptionService encryptionService,
            PostDao postDao, Authenticator authenticator) {
        super(dao);
        this.groupDao = groupDao;
        this.securityService = securityService;
        this.mailService = mailService;
        this.base64Wrapper = base64Wrapper;
        this.encryptionService = encryptionService;
        this.postDao = postDao;
        this.authenticator = authenticator;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JCUser getByUsername(String username) throws NotFoundException {
        JCUser user = this.getDao().getByUsername(username);
        if (user == null) {
            String msg = "JCUser [" + username + "] not found.";
            LOGGER.info(msg);
            throw new NotFoundException(msg);
        }
        return user;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public User getCommonUserByUsername(String username) throws NotFoundException {
        User user = this.getDao().getCommonUserByUsername(username);
        if (user == null) {
            String msg = "Common User [" + username + "] not found.";
            LOGGER.info(msg);
            throw new NotFoundException(msg);
        }
        return user;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<String> getUsernames(String pattern) {
        int usernameCount = 10;
        return getDao().getUsernames(pattern, usernameCount);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JCUser getCurrentUser() {
        UserInfo userInfo = securityService.getCurrentUserBasicInfo();
        return userInfo != null ? this.getDao().loadById(userInfo.getId()) : new AnonymousUser();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void updateLastLoginTime(JCUser user) {
        user.updateLastLoginTime();
        this.getDao().saveOrUpdate(user);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JCUser saveEditedUserProfile(long editedUserId, UserInfoContainer editedUserProfileInfo)
            throws NotFoundException {

        JCUser editedUser = this.get(editedUserId);
        byte[] decodedAvatar = base64Wrapper.decodeB64Bytes(editedUserProfileInfo.getB64EncodedAvatar());

        editedUser.setEmail(editedUserProfileInfo.getEmail());

        if (!Arrays.equals(editedUser.getAvatar(), decodedAvatar)) {
            editedUser.setAvatarLastModificationTime(new DateTime());
        }
        editedUser.setAvatar(decodedAvatar);
        editedUser.setSignature(editedUserProfileInfo.getSignature());
        editedUser.setFirstName(editedUserProfileInfo.getFirstName());
        editedUser.setLastName(editedUserProfileInfo.getLastName());
        editedUser.setPageSize(editedUserProfileInfo.getPageSize());
        editedUser.setLocation(editedUserProfileInfo.getLocation());

        this.getDao().saveOrUpdate(editedUser);
        LOGGER.info("Updated user profile. Username: {}", editedUser.getUsername());
        return editedUser;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JCUser saveEditedUserSecurity(long editedUserId, UserSecurityContainer userSecurityInfo)
            throws NotFoundException {
        JCUser editedUser = this.get(editedUserId);

        String newPassword = userSecurityInfo.getNewPassword();
        if (newPassword != null) {
            String encryptedPassword = encryptionService.encryptPassword(newPassword);
            editedUser.setPassword(encryptedPassword);
        }

        this.getDao().saveOrUpdate(editedUser);
        LOGGER.info("Updated user security settings. Username: {}", editedUser.getUsername());
        return editedUser;

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JCUser saveEditedUserNotifications(long editedUserId, UserNotificationsContainer userNotificationsInfo)
            throws NotFoundException {
        JCUser editedUser = this.get(editedUserId);

        editedUser.setMentioningNotificationsEnabled(userNotificationsInfo.isMentioningNotificationsEnabled());
        editedUser.setSendPmNotification(userNotificationsInfo.isSendPmNotification());
        editedUser.setAutosubscribe(userNotificationsInfo.isAutosubscribe());

        this.getDao().saveOrUpdate(editedUser);
        LOGGER.info("Updated user notification settings. Username: {}", editedUser.getUsername());
        return editedUser;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void restorePassword(String email) throws MailingFailedException {
        JCUser user = this.getDao().getByEmail(email);
        String randomPassword = RandomStringUtils.randomAlphanumeric(6);
        // first - mail attempt, then - database changes
        mailService.sendPasswordRecoveryMail(user, randomPassword);
        String encryptedRandomPassword = encryptionService.encryptPassword(randomPassword);
        user.setPassword(encryptedRandomPassword);
        this.getDao().saveOrUpdate(user);

        LOGGER.info("New random password was set for user {}", user.getUsername());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public JCUser getByUuid(String uuid) throws NotFoundException {
        JCUser user = this.getDao().getByUuid(uuid);
        if (user == null) {
            throw new NotFoundException();
        } else {
            return user;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    //  Temporarily disabled. Until we find the bug due to which activated users become not activated.
    //    @Scheduled(cron = "0 * * * * *") // cron expression: invoke every hour at :00 min, e.g. 11:00, 12:00 and so on
    public void deleteUnactivatedAccountsByTimer() {
        DateTime today = new DateTime();
        for (JCUser user : this.getDao().getNonActivatedUsers()) {
            Period period = new Period(user.getRegistrationDate(), today);
            if (period.getDays() > 0) {
                this.getDao().delete(user);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @PreAuthorize("hasPermission(#userId, 'USER', 'ProfilePermission.EDIT_OTHERS_PROFILE')")
    public void checkPermissionToEditOtherProfiles(Long userId) {
        LOGGER.debug("Check permission to edit other profiles for user - " + userId);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @PreAuthorize("hasPermission(#userId, 'USER', 'ProfilePermission.EDIT_OWN_PROFILE')")
    public void checkPermissionToEditOwnProfile(Long userId) {
        LOGGER.debug("Check permission to edit own profile for user - " + userId);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @PreAuthorize("hasPermission(#userId, 'USER', 'ProfilePermission.CREATE_FORUM_FAQ')")
    public void checkPermissionToCreateAndEditSimplePage(Long userId) {
        LOGGER.debug("Check permission to create or edit simple(static) pages - " + userId);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public AuthenticationStatus loginUser(LoginUserDto loginUserDto, HttpServletRequest request,
            HttpServletResponse response) throws UnexpectedErrorException, NoConnectionException {
        return authenticator.authenticate(loginUserDto, request, response);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String processUserBbCodesInPost(String postContent) {
        MentionedUsers mentionedUsers = MentionedUsers.parse(postContent);
        return mentionedUsers.getTextWithProcessedUserTags(getDao());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void notifyAndMarkNewlyMentionedUsers(Post post) {
        MentionedUsers mentionedUsers = MentionedUsers.parse(post);
        List<JCUser> usersToNotify = mentionedUsers.getNewUsersToNotify(getDao());

        for (JCUser user : usersToNotify) {
            mailService.sendUserMentionedNotification(user, post.getId());
        }

        mentionedUsers.markUsersAsAlreadyNotified(postDao);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void changeLanguage(JCUser jcUser, Language newLang) {
        jcUser.setLanguage(newLang);
        this.getDao().saveOrUpdate(jcUser);
    }

    @Override
    @PreAuthorize("hasPermission(#forumComponentId, 'COMPONENT', 'GeneralPermission.ADMIN')")
    public List<JCUser> findByUsernameOrEmail(long forumComponentId, String searchKey) {
        return getDao().findByUsernameOrEmail(searchKey, MAX_SEARCH_USER_COUNT);
    }

    @Override
    public List<UserDto> findByUsernameOrEmailNotInGroup(String pattern, long groupId, int count) {
        return getDao().findByUsernameOrEmailNotInGroup(pattern, groupId, count);
    }

    @Override
    @PreAuthorize("hasPermission(#forumComponentId, 'COMPONENT', 'GeneralPermission.ADMIN')")
    public List<Long> getUserGroupIDs(long forumComponentId, long userID) throws NotFoundException {
        JCUser jcUser = getDao().get(userID);
        return jcUser.getGroupsIDs();
    }

    @Override
    @PreAuthorize("hasPermission(#forumComponentId, 'COMPONENT', 'GeneralPermission.ADMIN')")
    public void addUserToGroup(long forumComponentId, long userID, long groupID) throws NotFoundException {
        JCUser jcUser = getDao().get(userID);
        jcUser.addGroup(groupDao.get(groupID));

        this.getDao().saveOrUpdate(jcUser);
    }

    @Override
    @PreAuthorize("hasPermission(#forumComponentId, 'COMPONENT', 'GeneralPermission.ADMIN')")
    public void deleteUserFromGroup(long forumComponentId, long userID, long groupID) throws NotFoundException {
        JCUser jcUser = getDao().get(userID);
        jcUser.deleteGroup(groupDao.get(groupID));

        this.getDao().saveOrUpdate(jcUser);
    }
}