org.ambraproject.service.user.UserRegistrationServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.ambraproject.service.user.UserRegistrationServiceImpl.java

Source

/*
 * Copyright (c) 2007-2014 by Public Library of Science
 *
 * http://plos.org
 * http://ambraproject.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.ambraproject.service.user;

import org.ambraproject.models.UserProfile;
import org.ambraproject.service.hibernate.HibernateServiceImpl;
import org.ambraproject.service.mailer.AmbraMailer;
import org.ambraproject.service.password.PasswordDigestService;
import org.ambraproject.util.TokenGenerator;
import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Alex Kudlick 9/24/12
 */
public class UserRegistrationServiceImpl extends HibernateServiceImpl implements UserRegistrationService {
    private static final Logger log = LoggerFactory.getLogger(UserRegistrationServiceImpl.class);

    private AmbraMailer ambraMailer;

    private PasswordDigestService passwordDigestService;

    @Required
    public void setAmbraMailer(AmbraMailer ambraMailer) {
        this.ambraMailer = ambraMailer;
    }

    @Required
    public void setPasswordDigestService(PasswordDigestService passwordDigestService) {
        this.passwordDigestService = passwordDigestService;
    }

    /**
     * {@inheritDoc}
     *
     * @param userProfile
     * @param password
     */
    @Override
    @Transactional
    public Long registerUser(UserProfile userProfile, String password) throws DuplicateUserException {
        int existingUserCount = DataAccessUtils.intResult(hibernateTemplate.findByCriteria(
                DetachedCriteria.forClass(UserProfile.class).add(Restrictions.eq("email", userProfile.getEmail()))
                        .setProjection(Projections.count("email"))));
        if (existingUserCount > 0) {
            throw new DuplicateUserException(DuplicateUserException.Field.EMAIL);
        }

        existingUserCount = DataAccessUtils.intResult(hibernateTemplate.findByCriteria(DetachedCriteria
                .forClass(UserProfile.class).add(Restrictions.eq("displayName", userProfile.getDisplayName()))
                .setProjection(Projections.count("displayName"))));
        if (existingUserCount > 0) {
            throw new DuplicateUserException(DuplicateUserException.Field.DISPLAY_NAME);
        }

        try {
            log.debug("Registering new user with email: {}", userProfile.getEmail());
            userProfile.setPassword(passwordDigestService.generateDigest(password));
            Long id = (Long) hibernateTemplate.save(userProfile);
            ambraMailer.sendVerificationEmail(userProfile.getEmail(), userProfile.getVerificationToken());
            return id;
        } catch (DataIntegrityViolationException e) {
            throw new IllegalArgumentException("Didn't provide required field for user profile", e);
        }
    }

    @Override
    public void verifyUser(String email, String verificationToken)
            throws NoSuchUserException, UserAlreadyVerifiedException, VerificationTokenException {
        if (StringUtils.isEmpty(email)) {
            throw new IllegalArgumentException("Must supply an email");
        }
        if (StringUtils.isEmpty(verificationToken)) {
            throw new IllegalArgumentException("Must supply a verification token");
        }
        UserProfile profile = (UserProfile) DataAccessUtils.uniqueResult(hibernateTemplate
                .findByCriteria(DetachedCriteria.forClass(UserProfile.class).add(Restrictions.eq("email", email))));
        if (profile == null) {
            throw new NoSuchUserException("No user with email: " + email);
        } else if (profile.getVerified()) {
            throw new UserAlreadyVerifiedException("User " + email + " was already verified");
        } else if (!verificationToken.equals(profile.getVerificationToken())) {
            throw new VerificationTokenException("An invalid verification token was given for this user");
        }
        log.debug("Verifying user {}", email);
        profile.setVerified(true);
        hibernateTemplate.update(profile);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional
    public String resendVerificationEmail(String email) throws NoSuchUserException, UserAlreadyVerifiedException {
        if (StringUtils.isEmpty(email)) {
            throw new IllegalArgumentException("Must supply an email");
        }

        UserProfile profile = (UserProfile) DataAccessUtils.uniqueResult(hibernateTemplate
                .findByCriteria(DetachedCriteria.forClass(UserProfile.class).add(Restrictions.eq("email", email))));
        if (profile == null) {
            throw new NoSuchUserException("No user with the email: " + email);
        }
        if (profile.getVerified()) {
            throw new UserAlreadyVerifiedException();
        }

        profile.setVerificationToken(TokenGenerator.getUniqueToken());
        hibernateTemplate.update(profile);

        log.debug("Resending verification email to {}", email);
        ambraMailer.sendVerificationEmail(email, profile.getVerificationToken());

        return profile.getVerificationToken();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional
    public String sendForgotPasswordMessage(String email) throws NoSuchUserException {
        if (StringUtils.isEmpty(email)) {
            throw new IllegalArgumentException("Must supply an email");
        }
        UserProfile profile = (UserProfile) DataAccessUtils
                .uniqueResult(hibernateTemplate.findByCriteria(DetachedCriteria.forClass(UserProfile.class)
                        .add(Restrictions.eq("email", email)).add(Restrictions.eq("verified", true))));
        if (profile == null) {
            throw new NoSuchUserException("No user with the email: " + email);
        }
        log.debug("Sending forgotten newPassword message to {}", email);
        String passwordResetToken = TokenGenerator.getUniqueToken();
        profile.setVerificationToken(passwordResetToken);
        hibernateTemplate.update(profile);
        ambraMailer.sendForgotPasswordEmail(email, passwordResetToken);

        return passwordResetToken;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional(readOnly = true)
    public boolean validateVerificationToken(String email, String verificationToken) {
        if (StringUtils.isEmpty(email)) {
            throw new IllegalArgumentException("Must supply an email");
        }
        if (StringUtils.isEmpty(verificationToken)) {
            throw new IllegalArgumentException("Must supplay an verificationToken");
        }
        int count = DataAccessUtils.intResult(hibernateTemplate
                .findByCriteria(DetachedCriteria.forClass(UserProfile.class).add(Restrictions.eq("email", email))
                        .add(Restrictions.eq("verificationToken", verificationToken))
                        .setProjection(Projections.count("email"))));
        if (count > 1) {
            throw new IllegalStateException(
                    "More than one user with email: " + email + " and verification token: " + verificationToken);
        }

        return count == 1;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional
    public void removeVerificationToken(String email) {
        UserProfile profile = (UserProfile) DataAccessUtils.uniqueResult(hibernateTemplate
                .findByCriteria(DetachedCriteria.forClass(UserProfile.class).add(Restrictions.eq("email", email))));
        if (profile == null) {
            throw new IllegalArgumentException("Incorrect email: " + email);
        }

        log.debug("Resetting token for {}", email);

        profile.setVerificationToken(null);

        hibernateTemplate.update(profile);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional
    public void resetPassword(final String email, final String newPassword) {
        for (Map.Entry<String, String> argument : new HashMap<String, String>() {
            {
                put("email", email);
                put("new password", newPassword);
            }
        }.entrySet()) {
            if (StringUtils.isEmpty(argument.getValue())) {
                throw new IllegalArgumentException("Must supply a(n) " + argument.getKey());
            }
        }

        UserProfile profile = (UserProfile) DataAccessUtils.uniqueResult(hibernateTemplate
                .findByCriteria(DetachedCriteria.forClass(UserProfile.class).add(Restrictions.eq("email", email))));
        if (profile == null) {
            throw new IllegalArgumentException("Incorrect email: " + email);
        }

        log.debug("Setting new password for {}", email);
        profile.setPassword(passwordDigestService.generateDigest(newPassword));
        hibernateTemplate.update(profile);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional
    public String sendEmailChangeMessage(final String oldEmail, final String newEmail, final String password)
            throws NoSuchUserException, DuplicateUserException {
        for (Map.Entry<String, String> argument : new HashMap<String, String>() {
            {
                put("old email", oldEmail);
                put("new email", newEmail);
                put("password", password);
            }
        }.entrySet()) {
            if (StringUtils.isEmpty(argument.getValue())) {
                throw new IllegalArgumentException("Must supply a(n) " + argument.getKey());
            }
        }

        UserProfile profile = (UserProfile) DataAccessUtils.uniqueResult(hibernateTemplate.findByCriteria(
                DetachedCriteria.forClass(UserProfile.class).add(Restrictions.eq("email", oldEmail))));

        if (profile == null) {
            throw new NoSuchUserException("No user with the email: " + oldEmail);
        }

        boolean validPassword = passwordDigestService.verifyPassword(password, profile.getPassword());
        if (!validPassword) {
            throw new SecurityException("Invalid password");
        }

        int existingUserCount = DataAccessUtils.intResult(hibernateTemplate.findByCriteria(
                DetachedCriteria.forClass(UserProfile.class).add(Restrictions.eq("email", newEmail).ignoreCase())
                        .setProjection(Projections.count("email"))));
        if (existingUserCount > 0) {
            throw new DuplicateUserException(DuplicateUserException.Field.EMAIL);
        }

        log.debug("sending email change verification to {}", newEmail);
        profile.setVerificationToken(TokenGenerator.getUniqueToken());
        hibernateTemplate.update(profile);
        ambraMailer.sendChangeEmailNotice(oldEmail, newEmail, profile.getVerificationToken());

        return profile.getVerificationToken();
    }

    @Override
    @Transactional
    public void updateEmailAddress(final String oldEmail, final String newEmail, final String verificationToken)
            throws NoSuchUserException, VerificationTokenException, DuplicateUserException {
        for (Map.Entry<String, String> argument : new HashMap<String, String>() {
            {
                put("old email", oldEmail);
                put("new email", newEmail);
                put("verification token", verificationToken);
            }
        }.entrySet()) {
            if (StringUtils.isEmpty(argument.getValue())) {
                throw new IllegalArgumentException("Must supply a(n) " + argument.getKey());
            }
        }

        UserProfile profile = (UserProfile) DataAccessUtils.uniqueResult(hibernateTemplate.findByCriteria(
                DetachedCriteria.forClass(UserProfile.class).add(Restrictions.eq("email", oldEmail))));

        if (profile == null) {
            throw new NoSuchUserException("No user with the email: " + oldEmail);
        } else if (!verificationToken.equals(profile.getVerificationToken())) {
            throw new VerificationTokenException("An invalid verification token was given for this user");
        }

        int existingUserCount = DataAccessUtils.intResult(hibernateTemplate.findByCriteria(
                DetachedCriteria.forClass(UserProfile.class).add(Restrictions.eq("email", newEmail).ignoreCase())
                        .setProjection(Projections.count("email"))));
        if (existingUserCount > 0) {
            throw new DuplicateUserException(DuplicateUserException.Field.EMAIL);
        }

        log.debug("Changing email for {} to {}", oldEmail, newEmail);
        profile.setEmail(newEmail);
        hibernateTemplate.update(profile);
    }
}