gr.abiss.calipso.service.impl.UserServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for gr.abiss.calipso.service.impl.UserServiceImpl.java

Source

/**
 * Copyright (c) 2007 - 2013 www.Abiss.gr
 *
 * This file is part of Calipso, a software platform by www.Abiss.gr.
 *
 * Calipso 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.
 *
 * Calipso 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 Calipso. If not, see http://www.gnu.org/licenses/agpl.html
 */
package gr.abiss.calipso.service.impl;

import gr.abiss.calipso.model.Role;
import gr.abiss.calipso.model.User;
import gr.abiss.calipso.model.UserDTO;
import gr.abiss.calipso.model.interfaces.Metadatum;
import gr.abiss.calipso.model.metadata.UserMetadatum;
import gr.abiss.calipso.repository.RoleRepository;
import gr.abiss.calipso.repository.UserRepository;
import gr.abiss.calipso.service.EmailService;
import gr.abiss.calipso.service.UserService;
import gr.abiss.calipso.tiers.service.AbstractModelServiceImpl;
import gr.abiss.calipso.userDetails.integration.LocalUser;
import gr.abiss.calipso.userDetails.integration.LocalUserService;
import gr.abiss.calipso.userDetails.model.ICalipsoUserDetails;
import gr.abiss.calipso.userDetails.util.DuplicateEmailException;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;
import javax.mail.MessagingException;
import javax.persistence.Query;

import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.LockMode;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.keygen.KeyGenerators;
import org.springframework.security.crypto.keygen.StringKeyGenerator;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

//@Named("userService")
public class UserServiceImpl extends AbstractModelServiceImpl<User, String, UserRepository> implements UserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);

    private final StringKeyGenerator generator = KeyGenerators.string();
    private RoleRepository roleRepository;

    @Inject
    public void setRoleRepository(RoleRepository roleRepository) {
        this.roleRepository = roleRepository;
    }

    @Override
    @Transactional(readOnly = false)
    public void updateLastLogin(ICalipsoUserDetails u) {
        this.repository.updateLastLogin(u.getId());
    }

    /**
     * {@inheritDoc}
     * @see gr.abiss.calipso.userDetails.integration.LocalUserService#findByCredentials(java.lang.String, java.lang.String, java.util.Map)
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public User findByCredentials(String userNameOrEmail, String password, Map metadata) {
        if (LOGGER.isDebugEnabled())
            LOGGER.debug("findByCredentials, userNameOrEmail: " + userNameOrEmail + ", password: " + password
                    + ", metadata: " + metadata);
        User user = null;
        try {
            user = this.repository.findByCredentials(userNameOrEmail, password);
            LOGGER.error("findByCredentials: matched user: " + user);
            if (user != null) {
                if (!CollectionUtils.isEmpty(metadata)) {
                    List<Metadatum> saved = this.repository.addMetadata(user.getId(), metadata);
                    for (Metadatum meta : saved) {
                        user.addMetadatum((UserMetadatum) meta);
                    }

                }
            }
        } catch (RuntimeException e) {
            LOGGER.error("failed finding user by credentials", e);
        }
        return user;
    }

    @Override
    @Transactional(readOnly = false)
    public User create(User resource) {
        Role userRole = roleRepository.findByName(Role.ROLE_USER);
        resource.addRole(userRole);
        resource.setResetPasswordToken(generator.generateKey());
        resource = super.create(resource);
        emailService.sendAccountConfirmation(resource);
        return resource;
    }

    @Override
    @Transactional(readOnly = false)
    public void expireResetPasswordTokens() {
        // get a hibernate session suitable for read-only access to large datasets
        StatelessSession session = ((Session) this.repository.getEntityManager().getDelegate()).getSessionFactory()
                .openStatelessSession();
        Date yesterday = DateUtils.addDays(new Date(), -1);

        // send email notifications for account confirmation tokens that expired
        org.hibernate.Query query = session.createQuery(
                "SELECT new gr.abiss.calipso.model.UserDTO(u.id, u.firstName, u.lastName,u.username, u.email, u.emailHash) FROM User u "
                        + "WHERE u.password IS NULL and u.resetPasswordTokenCreated IS NOT NULL and u.resetPasswordTokenCreated  < :yesterday");
        query.setParameter("yesterday", yesterday);
        query.setFetchSize(Integer.valueOf(1000));
        query.setReadOnly(true);
        query.setLockMode("a", LockMode.NONE);
        ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY);
        while (results.next()) {
            UserDTO dto = (UserDTO) results.get(0);
            // TODO: send expiration email
            this.emailService.sendAccountConfirmationExpired(new User(dto));
        }
        results.close();
        session.close();

        // expire tokens, including password reset requests
        this.repository.expireResetPasswordTokens(yesterday);
    }

    @Override
    @Transactional(readOnly = false)
    public User createActive(User resource) {
        Role userRole = roleRepository.findByName(Role.ROLE_USER);
        resource.addRole(userRole);
        resource.setResetPasswordToken(generator.generateKey());
        resource = super.create(resource);
        return resource;
    }

    @Override
    @Transactional(readOnly = false)
    public User handlePasswordResetToken(String userNameOrEmail, String token, String newPassword) {
        Assert.notNull(userNameOrEmail);
        User user = this.findByUserNameOrEmail(userNameOrEmail);
        if (user == null) {
            throw new UsernameNotFoundException("Could not match username: " + userNameOrEmail);
        }
        user.setResetPasswordToken(null);
        user.setPassword(newPassword);
        user = this.update(user);

        LOGGER.info("handlePasswordResetToken returning local user: " + user);
        return user;
    }

    @Override
    @Transactional(readOnly = false)
    public void handlePasswordResetRequest(String userNameOrEmail) {
        Assert.notNull(userNameOrEmail);
        User user = this.findByUserNameOrEmail(userNameOrEmail);
        if (user == null || !user.getActive()) {
            throw new UsernameNotFoundException("Could not match username to an active user: " + userNameOrEmail);
        }
        // keep any existing token
        if (user.getResetPasswordToken() == null) {
            user.setResetPasswordToken(this.generator.generateKey());
            user = this.userRepository.save(user);
        }
        emailService.sendPasswordResetLink(user);

    }

    //   @Override
    //   @Transactional(readOnly = false)
    //   public User confirmPrincipal(String confirmationToken) {
    //      Assert.notNull(confirmationToken);
    //      //LoggedInUserDetails loggedInUserDetails = new LoggedInUserDetails();
    //      User original = this.userRepository.findByConfirmationToken(confirmationToken);
    //      if (original != null) {
    //         // enable and update user
    //         original.setResetPasswordToken(null);
    //         original = this.userRepository.save(original);
    //      } else {
    //         LOGGER.warn("Could not find any user matching confirmation token: " + confirmationToken);
    //      }
    //
    //      LOGGER.info("create returning local user: " + original);
    //      return original;
    //   }

    /**
     * {@inheritDoc}
     */
    @Override
    public User findByUserNameOrEmail(String userNameOrEmail) {
        return this.repository.findByUsernameOrEmail(userNameOrEmail);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional(readOnly = false)
    public User createForImplicitSignup(LocalUser userAccountData) throws DuplicateEmailException {
        LOGGER.info("createForImplicitSignup, localUser: " + userAccountData);
        User user = new User();
        user.setEmail(userAccountData.getEmail());
        user.setUsername(userAccountData.getUsername());
        user.setFirstName(userAccountData.getFirstName());
        user.setLastName(userAccountData.getLastName());
        user.setPassword(userAccountData.getPassword());
        User existing = this.repository.findByUsernameOrEmail(user.getEmail());
        if (existing == null) {
            existing = this.repository.findByUsernameOrEmail(user.getUsername());
        }

        //      if (this.repository.findByUsernameOrEmail(user.getUsername()) != null) {
        //         throw new DuplicateEmailException("Email address exists: " + userAccountData.getEmail());
        //      }
        //      if (this.repository.findByUsernameOrEmail(user.getUsername()) != null) {
        //         throw new DuplicateEmailException("Username exists: " + userAccountData.getEmail());
        //      }
        //
        //      if(LOGGER.isDebugEnabled()){
        //         LOGGER.debug("createForImplicitSignup returning local user: " + user);
        //      }
        return existing != null ? existing : createActive(user);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional(readOnly = false)
    public User changePassword(String userNameOrEmail, String oldPassword, String newPassword,
            String newPasswordConfirm) {

        // make sure we have all params
        String[] params = { userNameOrEmail, oldPassword, newPassword, newPasswordConfirm };
        Assert.noNullElements(params,
                "Failed updating user pass: Username/email, old password, new password and new password confirmation must be provided ");

        // make sure new password and confirm match
        Assert.isTrue(newPassword.equals(newPasswordConfirm),
                "Failed updating user pass: New password and new password confirmation must be equal");

        // make sure a user matching the credentials is found
        User u = this.findByCredentials(userNameOrEmail, oldPassword, null);
        Assert.notNull(u, "Failed updating user pass: A user could not be found with the given credentials");

        // update password and return user
        u.setPassword(newPassword);
        u.setLastPassWordChangeDate(new Date());
        u = this.update(u);
        return u;
    }

}