org.zlogic.vogon.web.security.UserService.java Source code

Java tutorial

Introduction

Here is the source code for org.zlogic.vogon.web.security.UserService.java

Source

/*
 * Vogon personal finance/expense analyzer.
 * Licensed under Apache license: http://www.apache.org/licenses/LICENSE-2.0
 * Author: Dmitry Zolotukhin <zlogic@gmail.com>
 */
package org.zlogic.vogon.web.security;

import java.util.ResourceBundle;
import javax.annotation.Resource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import org.zlogic.vogon.data.Constants;
import org.zlogic.vogon.data.VogonUser;
import org.zlogic.vogon.web.data.UserRepository;

/**
 * The user details service for Spring Security
 *
 * @author Dmitry Zolotukhin [zlogic@gmail.com]
 */
@Service
public class UserService implements UserDetailsService, InitializingBean {

    /**
     * Localization messages
     */
    private static final ResourceBundle messages = ResourceBundle.getBundle("org/zlogic/vogon/web/messages");
    /**
     * The users repository
     */
    @Autowired
    private UserRepository userRepository;
    /**
     * The Spring PlatformTransactionManager instance
     */
    @Resource
    private PlatformTransactionManager transactionManager;
    /**
     * The PasswordEncoder instance
     */
    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * Loads a user by username
     *
     * @param username the username
     * @return the loaded user
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        VogonUser user = userRepository.findByUsernameIgnoreCase(username);
        if (user == null)
            throw new UsernameNotFoundException(messages.getString("USER_CANNOT_BE_FOUND"));
        else
            return new VogonSecurityUser(user);
    }

    /**
     * Updates user from database (e.g. to reflect
     *
     * @param securityUser user to update
     */
    public void refreshUser(VogonSecurityUser securityUser) {
        if (securityUser.getUser() != null) {
            VogonUser user = userRepository.findOne(securityUser.getUser().getId());
            securityUser.setUser(user);
        }
    }

    /**
     * Returns true if the username is already in use
     *
     * @param username the username to check
     * @return true if the username is already in use
     */
    private boolean isUsernameExists(final String username) {
        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.setReadOnly(true);
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        return transactionTemplate.execute(new TransactionCallback<Boolean>() {

            @Override
            public Boolean doInTransaction(TransactionStatus ts) {
                return userRepository.findByUsernameIgnoreCase(username) != null;
            }
        });
    }

    /**
     * Saves a user
     *
     * @param user the VogonUser to save
     * @return the saved user
     * @throws UsernameExistsException if username is already in use
     */
    private VogonUser saveUser(VogonUser user) throws UsernameExistsException {
        try {
            return userRepository.saveAndFlush(user);
        } catch (JpaSystemException ex) {
            if (isUsernameExists(user.getUsername()))
                throw new UsernameExistsException();
            else
                throw ex;
        }
    }

    /**
     * Creates a new user
     *
     * @param createUser the user parameters to use
     * @return the persisted user
     * @throws org.zlogic.vogon.web.security.UsernameExistsException in case the
     * username is already in use
     */
    public VogonUser createUser(VogonUser createUser) throws UsernameExistsException {
        VogonUser user = new VogonUser(createUser.getUsername(), passwordEncoder.encode(createUser.getPassword()));
        user.setAuthorities(VogonSecurityUser.AUTHORITY_USER);
        saveUser(user);
        return user;
    }

    /**
     * Updates a user
     *
     * @param userPrincipal the user principal to update
     * @param updatedUser the user parameters to use
     * @return the persisted user
     * @throws org.zlogic.vogon.web.security.UsernameExistsException in case the
     * new username is already in use
     */
    public VogonSecurityUser updateUser(VogonSecurityUser userPrincipal, VogonUser updatedUser)
            throws UsernameExistsException {
        VogonUser user = userRepository.findByUsernameIgnoreCase(userPrincipal.getUsername());
        user.setDefaultCurrency(updatedUser.getDefaultCurrency());
        if (updatedUser.getUsername() != null && !updatedUser.getUsername().isEmpty()
                && !updatedUser.getUsername().equals(user.getUsername()))
            user.setUsername(updatedUser.getUsername());
        if (updatedUser.getPassword() != null)
            user.setPassword(passwordEncoder.encode(updatedUser.getPassword()));
        saveUser(user);
        refreshUser(userPrincipal);
        return userPrincipal;
    }

    /**
     * Applies default properties and creates default user if needed
     *
     * @throws Exception in case of errors
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        if (userRepository.count() == 0) {
            VogonUser defaultUser = new VogonUser(Constants.DEFAULT_USERNAME,
                    passwordEncoder.encode(Constants.DEFAULT_PASSWORD));
            defaultUser.setAuthorities(VogonSecurityUser.AUTHORITY_ADMIN, VogonSecurityUser.AUTHORITY_USER);
            userRepository.saveAndFlush(defaultUser);
        }
    }
}