it.greenvulcano.gvesb.iam.service.internal.GVUsersManager.java Source code

Java tutorial

Introduction

Here is the source code for it.greenvulcano.gvesb.iam.service.internal.GVUsersManager.java

Source

/*******************************************************************************
 * Copyright (c) 2009, 2016 GreenVulcano ESB Open Source Project.
 * All rights reserved.
 *
 * This file is part of GreenVulcano ESB.
 *
 * GreenVulcano ESB 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 3 of the License, or
 * (at your option) any later version.
 *
 * GreenVulcano ESB 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 GreenVulcano ESB. If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package it.greenvulcano.gvesb.iam.service.internal;

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.apache.commons.codec.digest.DigestUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import it.greenvulcano.gvesb.iam.domain.Role;
import it.greenvulcano.gvesb.iam.domain.User;
import it.greenvulcano.gvesb.iam.domain.UserInfo;
import it.greenvulcano.gvesb.iam.domain.jpa.RoleJPA;
import it.greenvulcano.gvesb.iam.domain.jpa.UserJPA;
import it.greenvulcano.gvesb.iam.exception.GVSecurityException;
import it.greenvulcano.gvesb.iam.exception.InvalidPasswordException;
import it.greenvulcano.gvesb.iam.exception.InvalidRoleException;
import it.greenvulcano.gvesb.iam.exception.InvalidUsernameException;
import it.greenvulcano.gvesb.iam.exception.PasswordMissmatchException;
import it.greenvulcano.gvesb.iam.exception.UnverifiableUserException;
import it.greenvulcano.gvesb.iam.exception.UserExistException;
import it.greenvulcano.gvesb.iam.exception.UserExpiredException;
import it.greenvulcano.gvesb.iam.exception.UserNotFoundException;
import it.greenvulcano.gvesb.iam.repository.hibernate.RoleRepositoryHibernate;
import it.greenvulcano.gvesb.iam.repository.hibernate.UserRepositoryHibernate;
import it.greenvulcano.gvesb.iam.service.SearchCriteria;
import it.greenvulcano.gvesb.iam.service.SearchResult;
import it.greenvulcano.gvesb.iam.service.UsersManager;

public class GVUsersManager implements UsersManager {

    private UserRepositoryHibernate userRepository;
    private RoleRepositoryHibernate roleRepository;

    public void setUserRepository(UserRepositoryHibernate userRepository) {
        this.userRepository = userRepository;
    }

    public void setRoleRepository(RoleRepositoryHibernate roleRepository) {
        this.roleRepository = roleRepository;
    }

    @Override
    public User createUser(String username, String password)
            throws InvalidUsernameException, InvalidPasswordException, UserExistException {
        if (!username.matches(User.USERNAME_PATTERN))
            throwException(new InvalidUsernameException(username));
        if (!password.matches(User.PASSWORD_PATTERN))
            throwException(new InvalidPasswordException(password));

        UserJPA user = new UserJPA();
        user.setUsername(username);
        user.setPassword(DigestUtils.sha256Hex(password));
        user.setPasswordTime(new Date());
        user.setEnabled(true);

        try {
            userRepository.add(user);
        } catch (org.hibernate.StaleObjectStateException
                | ConstraintViolationException constraintViolationException) {
            throwException(new UserExistException(username));
        }

        return userRepository.get(username).get();
    }

    @Override
    public Role createRole(String name, String description) throws InvalidRoleException {
        if (!name.matches(Role.ROLE_PATTERN))
            throw new InvalidRoleException(name);

        Role role = new RoleJPA(name, description);
        roleRepository.add(role);
        return role;
    }

    @Override
    public void updateUser(String username, UserInfo userInfo, Set<Role> grantedRoles, boolean enabled,
            boolean expired) throws UserNotFoundException, InvalidRoleException {
        User user = userRepository.get(username).orElseThrow(() -> new UserNotFoundException(username));
        user.setUserInfo(userInfo);
        user.setEnabled(enabled);
        user.setExpired(expired);
        user.clearRoles();
        if (grantedRoles != null) {

            Predicate<Role> roleIsValid = role -> Optional.ofNullable(role.getName()).orElse("")
                    .matches(Role.ROLE_PATTERN);

            Optional<Role> notValidRole = grantedRoles.stream().filter(roleIsValid.negate()).findAny();
            if (notValidRole.isPresent()) {
                throw new InvalidRoleException(notValidRole.get().getName());
            }

            for (Role r : grantedRoles) {
                user.addRole(roleRepository.get(r.getName()).orElse(r));
            }

        }
        userRepository.add(user);
    }

    @Override
    public User getUser(Long id) throws UserNotFoundException {
        User user = userRepository.get(id).orElseThrow(() -> new UserNotFoundException(id.toString()));
        return user;
    }

    @Override
    public User getUser(String username) throws UserNotFoundException {
        User user = userRepository.get(username).orElseThrow(() -> new UserNotFoundException(username));
        return user;
    }

    @Override
    public void deleteUser(String username) {
        userRepository.get(username).ifPresent(userRepository::remove);
    }

    @Override
    public User resetUserPassword(String username, String defaultPassword)
            throws UserNotFoundException, InvalidPasswordException, UnverifiableUserException {
        User user = userRepository.get(username).orElseThrow(() -> new UserNotFoundException(username));

        if (!Objects.requireNonNull(defaultPassword, "A default password is required")
                .matches(User.PASSWORD_PATTERN))
            throw new InvalidPasswordException(defaultPassword);
        if (!user.getPassword().isPresent())
            throw new UnverifiableUserException(username);

        user.setPassword(DigestUtils.sha256Hex(defaultPassword));
        user.setPasswordTime(new Date());
        user.setExpired(true);
        userRepository.add(user);
        return user;

    }

    @Override
    public User changeUserPassword(String username, String oldPassword, String newPassword)
            throws UserNotFoundException, PasswordMissmatchException, InvalidPasswordException,
            UnverifiableUserException {

        User user = userRepository.get(username).orElseThrow(() -> new UserNotFoundException(username));
        if (!newPassword.matches(User.PASSWORD_PATTERN))
            throw new InvalidPasswordException(newPassword);
        if (!user.getPassword().isPresent())
            throw new UnverifiableUserException(username);

        user.setUsername(username);
        user.setPassword(DigestUtils.sha256Hex(newPassword));
        user.setPasswordTime(new Date());
        user.setExpired(false);

        userRepository.add(user);

        return user;
    }

    @Override
    public User validateUser(String username, String password) throws UserNotFoundException,
            PasswordMissmatchException, UserExpiredException, UnverifiableUserException {

        User user = userRepository.get(username).orElseThrow(() -> new UserNotFoundException(username));
        if (user.getPassword().orElseThrow(() -> new UnverifiableUserException(username))
                .equals(DigestUtils.sha256Hex(password))) {
            if (user.isExpired()) {
                throw new UserExpiredException(username);
            } else if (!user.isEnabled()) {
                throw new UserNotFoundException(username);
            }
        } else {
            throw new PasswordMissmatchException(username);
        }

        return user;

    }

    @Override
    public void deleteRole(String roleName) {
        roleRepository.get(roleName).ifPresent(roleRepository::remove);

    }

    @Override
    public Set<Role> getRoles() {
        return roleRepository.getAll();
    }

    @Override
    public Role getRole(String name) {
        Optional<Role> role = roleRepository.get(name);
        if (role.isPresent()) {
            return role.get();
        }
        return null;
    }

    public Set<User> getUsers() {
        return userRepository.getAll();
    }

    @Override
    public SearchResult searchUsers(SearchCriteria criteria) {

        SearchResult result = new SearchResult();

        Map<UserRepositoryHibernate.Parameter, Object> parameters = criteria.getParameters().keySet().stream()
                .map(UserRepositoryHibernate.Parameter::valueOf).filter(Objects::nonNull)
                .collect(Collectors.toMap(Function.identity(), k -> criteria.getParameters().get(k.name())));

        LinkedHashMap<UserRepositoryHibernate.Parameter, UserRepositoryHibernate.Order> order = new LinkedHashMap<>(
                criteria.getOrder().size());
        for (Entry<String, String> e : criteria.getOrder().entrySet()) {
            Optional.ofNullable(UserRepositoryHibernate.Parameter.get(e.getKey())).ifPresent(p -> {
                order.put(p, UserRepositoryHibernate.Order.get(e.getValue()));
            });
        }

        result.setTotalCount(userRepository.count(parameters));
        if (criteria.getOffset() > result.getTotalCount()) {
            result.setFounds(new HashSet<>());
        } else {
            result.setFounds(userRepository.find(parameters, order, criteria.getOffset(), criteria.getLimit()));
        }

        return result;
    }

    @Override
    public User enableUser(String username, boolean enable) throws UserNotFoundException {
        User user = userRepository.get(username).orElseThrow(() -> new UserNotFoundException(username));
        user.setEnabled(enable);
        userRepository.add(user);

        return user;
    }

    @Override
    public User setUserExpiration(String username, boolean expired) throws UserNotFoundException {
        User user = userRepository.get(username).orElseThrow(() -> new UserNotFoundException(username));
        user.setExpired(expired);
        userRepository.add(user);

        return user;
    }

    @Override
    public User switchUserStatus(String username) throws UserNotFoundException {
        User user = userRepository.get(username).orElseThrow(() -> new UserNotFoundException(username));
        user.setEnabled(!user.isEnabled());
        userRepository.add(user);

        return user;
    }

    @Override
    public void checkManagementRequirements() {
        final Logger logger = LoggerFactory.getLogger(getClass());

        Map<UserRepositoryHibernate.Parameter, Object> parameters = new HashMap<>(2);
        parameters.put(UserRepositoryHibernate.Parameter.role, Authority.ADMINISTRATOR);
        parameters.put(UserRepositoryHibernate.Parameter.enabled, Boolean.TRUE);

        int admins = userRepository.count(parameters);
        /**
         * Adding default user 'gvadmin' if no present      
         */
        if (admins == 0) {
            logger.info("Creating a default 'gvadmin'");
            User admin;
            try {
                createUser("gvadmin", "gvadmin");
            } catch (SecurityException | InvalidUsernameException | InvalidPasswordException
                    | UserExistException e) {
                logger.info("A user named 'gvadmin' exist: restoring his default settings", e);

                admin = userRepository.get("gvadmin").get();
                admin.setPassword(DigestUtils.sha256Hex("gvadmin"));
                admin.setPasswordTime(new Date());
                admin.setExpired(true);
                userRepository.add(admin);

            }

            admin = userRepository.get("gvadmin").get();
            admin.setEnabled(true);
            admin.clearRoles();
            admin.addRole(new RoleJPA(Authority.ADMINISTRATOR, "Created by GV"));

            //roles required to use karaf 
            admin.addRole(new RoleJPA("admin", "Created by GV"));
            admin.addRole(new RoleJPA("manager", "Created by GV"));
            admin.addRole(new RoleJPA("viewer", "Created by GV"));
            admin.addRole(new RoleJPA("systembundles", "Created by GV"));
            admin.addRole(new RoleJPA("ssh", "Created by GV"));

            userRepository.add(admin);
        }

    }

    @Override
    public void revokeRole(String username, String role) throws UserNotFoundException {
        try {
            User user = userRepository.get(username)
                    .orElseThrow(() -> new SecurityException(new UserNotFoundException(username)));
            user.removeRole(role);
            userRepository.add(user);
        } catch (SecurityException e) {
            if (e.getCause() instanceof UserNotFoundException) {
                throw (UserNotFoundException) e.getCause();
            } else {
                throw e;

            }
        }
    }

    @Override
    public void updateUsername(String username, String newUsername)
            throws UserNotFoundException, InvalidUsernameException {

        User user = userRepository.get(username).orElseThrow(() -> new UserNotFoundException(username));
        if (username.matches(User.USERNAME_PATTERN)) {
            user.setUsername(newUsername);
        } else {
            throw new InvalidUsernameException(newUsername);
        }

        userRepository.add(user);
    }

    private void throwException(GVSecurityException cause) {
        throw new SecurityException(cause);
    }

    @Override
    public void addRole(String username, String rolename) {
        if (!rolename.matches(Role.ROLE_PATTERN))
            throwException(new InvalidRoleException(rolename));

        User user = userRepository.get(username)
                .orElseThrow(() -> new SecurityException(new UserNotFoundException(username)));

        Role role = roleRepository.get(rolename).orElse(new RoleJPA(rolename, "Created by JAAS"));
        user.addRole(role);

        userRepository.add(user);

    }

}