All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.formkiq.server.service.UserServiceImpl Maven / Gradle / Ivy

/*
 * Copyright (C) 2016 FormKiQ Inc.
 *
 * 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 com.formkiq.server.service;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.validator.routines.EmailValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.formkiq.server.config.DateService;
import com.formkiq.server.dao.FolderDao;
import com.formkiq.server.dao.UserDao;
import com.formkiq.server.domain.Folder;
import com.formkiq.server.domain.FolderAccess;
import com.formkiq.server.domain.User;
import com.formkiq.server.domain.type.FolderPermission;
import com.formkiq.server.domain.type.UserDTO;
import com.formkiq.server.domain.type.UserListDTO;
import com.formkiq.server.domain.type.UserRole;
import com.formkiq.server.domain.type.UserStatus;

/**
 * UserService Implementation.
 *
 */
@Service
public class UserServiceImpl implements UserService {

    /** Default User Token expiry time. */
	private static final int DEFAULT_EXPIRY_MINUTES = 24 * 60;

	/** DateService. */
	@Autowired
	private DateService dateservice;

	/** FolderDao. */
    @Autowired
    private FolderDao folderDao;

    /** FolderService. */
    @Autowired
    private FolderService folderservice;

    /** PasswordEncoder. */
    @Autowired
    private PasswordEncoder passwordEncoder;

    /** SpringSecurityService. */
    @Autowired
    private SpringSecurityService securityService;

    /** SystemPropertyService. */
    @Autowired
    private SystemPropertyService systemPropertyService;

	/** UserDao. */
	@Autowired
	private UserDao userDao;

	/**
	 * default constructor.
	 */
	public UserServiceImpl() {
	}

	@Override
    public User createUser(final String email,
            final String password, final UserStatus status, final UserRole role)
            throws PreconditionFailedException {

	    if (!this.securityService.isAdmin()) {

            if (this.systemPropertyService.isInviteOnly()
                    && !UserStatus.INVITE.equals(status)) {
                throw new PreconditionFailedException(
                        "User can only be created via invite");
            }
	    }

	    if (!EmailValidator.getInstance().isValid(email)) {
	        throw new PreconditionFailedException("Invalid Email " + email);
	    }

	    if (StringUtils.isEmpty(password)) {
	        throw new PreconditionFailedException("Password required");
	    }

	    if (status == null) {
            throw new PreconditionFailedException("UserStatus required");
        }

	    if (role == null) {
            throw new PreconditionFailedException("UserRole required");
        }

	    if (this.userDao.findUser(email) != null) {
	        throw new PreconditionFailedException("Email already registered");
	    }

		User user = new User();
	    user.setEmail(email);
	    user.setStatus(status);
	    user.setRole(role);
	    setUserPassword(user, password);

		user = this.userDao.saveUser(user);

        this.folderservice.saveFolder(user, null, email);

		return user;
	}

	@Override
    public void deleteUser(final String email) {

        if (!StringUtils.isEmpty(email)) {

            User user = this.userDao.findUser(email);
            if (user != null) {

                if (!(UserRole.ROLE_ADMIN.equals(user.getRole())
                        && this.userDao.getAdminUserCount() == 1)) {
                    this.userDao.deleteUser(user);
                } else {
                    throw new PreconditionFailedException(
                            "Cannot delete, only admin");
                }

            } else {
                throw new PreconditionFailedException(
                        "Email " + email + " not found");
            }

        } else {

            throw new PreconditionFailedException("Invalid Email");
        }
    }

	@Override
    public UserDetails findActiveUser(final String email,
            final String password) throws AuthenticationFailureException {

        User user = null;

        if (!StringUtils.isEmpty(email) && !StringUtils.isEmpty(password)) {

            user = findActiveUserByEmail(email);

            boolean matched = isMatch(password, user.getPassword());

            if (!matched) {
                user = null;
            }
        }

        if (user == null) {
            throw new AuthenticationFailureException("Authentication failed. "
                    + "Please verify your email address "
                    + "and password and try again.");
        }

        return user;
    }

	/**
     * Find Active User.
     * @param email {@link String}
     * @return {@link User}
     */
	@Override
    public User findActiveUserByEmail(final String email) {

        User user = this.userDao.findUser(email);

        if (user != null) {

            if (UserStatus.ACTIVE.equals(user.getStatus())) {
                return user;
            }

            throw new AuthenticationFailureException("Authentication failed. "
                    + "User account is disabled.");
        }

        throw new AuthenticationFailureException("Authentication failed. "
                + "Please verify your email address "
                + "and password and try again.");
	}

	@Override
    public UserDTO findUser(final String email, final boolean includePassword)
            throws AuthenticationFailureException {

	    UserDTO user = null;

		if (!StringUtils.isEmpty(email)) {

			user = this.userDao.findUserDTO(email);

			if (user != null && !includePassword) {
			    user.setPassword(null);
			}
		}

		if (user == null) {
            throw new AuthenticationFailureException("Authentication failed. "
                    + "Please verify your email address "
                    + "and password and try again.");
		}

		return user;
	}

	/**
     * Find User.
     * @param email {@link String}
     * @return {@link User}
     */
    @Override
    public UserDetails findUserByEmail(final String email) {
        return this.userDao.findUser(email);
    }

	@Override
    public UserListDTO findUsers(final String token) {
        return this.userDao.findUsers(token);
    }

	/**
	 * Generate secured Password Hash.
	 * @param password String
	 * @return {@link String}
	 */
	String generatedSecuredPasswordHash(final String password) {

		String securedPasswordHash = this.passwordEncoder.encode(password);
		return securedPasswordHash;
	}

	@Override
	public String generateResetToken(final String email)
			throws AuthenticationFailureException {

		User user = findActiveUserByEmail(email);
		String token = generateSecurityToken();
		String securedTokenHash = generatedSecuredPasswordHash(token);

		Date now = this.dateservice.now();

		user.setResetToken(securedTokenHash);
		user.setResetInsertedDate(now);
		user.setUpdatedDate(now);
		this.userDao.saveUser(user);

		return token;
	}

    @Override
	public String generateSecurityToken() {

        String securityToken = UUID.randomUUID().toString().replaceAll("-", "");
        return securityToken;
	}

    /**
	 * Gets the User Reset Token expiry in minutes.
	 * @return int
	 */
	protected int getUserTokenExpiryInMinutes() {
		return DEFAULT_EXPIRY_MINUTES;
	}

    @Override
    public boolean inviteUserToFolder(final UserDetails ud, final String email,
            final String folderId, final List permissions) {

        boolean isnew = false;
        User user = (User) ud;
        FolderAccess fa = null;
        FolderAccess access = this.folderDao.findFolderAccess(user, folderId);

        if (this.securityService.hasPermission(access,
                FolderPermission.PERM_FORM_ADMIN)) {

            User inviteUser = this.userDao.findUser(email);

            Folder folder = this.folderDao.findFolder(folderId);

            if (inviteUser == null) {

                String password = this.generateSecurityToken();
                inviteUser = this.createUser(email, password, UserStatus.INVITE,
                        UserRole.ROLE_USER);
            } else {

                fa = this.folderDao.findFolderAccess(inviteUser, folderId);
            }

            if (fa == null) {
                isnew = true;
                fa = new FolderAccess();
            }

            fa.setFolderid(folder.getFolderid());
            fa.setUserid(inviteUser.getUserid());
            fa.setPermissions(permissions);
            this.folderDao.saveFolderAccess(fa);

        } else {

            throw new FormAccessDeniedException();
        }

        return isnew;
    }

    /**
     * Checks password match.
     * @param rawPassword String
     * @param encodedPassword String
     * @return boolean
     */
    private boolean isMatch(final String rawPassword,
            final String encodedPassword) {
        return this.passwordEncoder.matches(rawPassword, encodedPassword);
    }

    @Override
    public User saveUser(final String email,
            final String password, final UserRole role,
            final UserStatus status) {

        User user = this.userDao.findUser(email);

        if (user != null) {

            if (role != null) {
                user.setRole(role);
            }

            if (status != null) {
                user.setStatus(status);
            }

            setUserPassword(user, password);
            user = this.userDao.saveUser(user);

        } else {

            user = createUser(email, password, status, role);
        }

        return user;
    }

    /**
     * Encrypts the User Password and set it into the object.
     * @param user User
     * @param password unencrypted password
     */
    private void setUserPassword(final User user, final String password) {

        if (!StringUtils.isEmpty(password)) {
            String securedPassHash = generatedSecuredPasswordHash(password);
            user.setPassword(securedPassHash);
        }
    }

    @Override
    public void updateLastLogin(final String email, final Date date) {
        this.userDao.updateLastLogin(email, date);
    }

    @Override
    public void updatePassword(final String email, final String resettoken,
            final String newPassword) {

        boolean updated = false;

        if (!StringUtils.isEmpty(resettoken)) {

            User user = this.userDao.findUser(email);

            if (user != null) {

                if (isMatch(resettoken, user.getResetToken())) {

                    Date now = this.dateservice.now();
                    Date date = DateUtils.addMinutes(now,
                            -getUserTokenExpiryInMinutes());

                    if (user.getResetInsertedDate().after(date)) {

                        user.setResetInsertedDate(null);
                        user.setResetToken(null);
                        setUserPassword(user, newPassword);

                        this.userDao.saveUser(user);
                        updated = true;
                    }
                }
            }
        }

        if (!updated) {
            throw new PreconditionFailedException("Invalid Reset Token");
        }
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy