fi.hsl.parkandride.core.service.UserServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for fi.hsl.parkandride.core.service.UserServiceTest.java

Source

// Copyright  2015 HSL <https://www.hsl.fi>
// This program is dual-licensed under the EUPL v1.2 and AGPLv3 licenses.

package fi.hsl.parkandride.core.service;

import static fi.hsl.parkandride.core.ViolationAssert.*;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.lang3.StringUtils;
import org.jasypt.util.password.PasswordEncryptor;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import fi.hsl.parkandride.core.back.UserRepository;
import fi.hsl.parkandride.core.domain.NewUser;
import fi.hsl.parkandride.core.domain.Role;
import fi.hsl.parkandride.core.domain.User;
import fi.hsl.parkandride.core.domain.UserSecret;

public class UserServiceTest {
    @Mock
    private UserRepository userRepository;

    @Mock
    private PasswordEncryptor passwordEncryptor;

    private UserService userService;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        userService = new UserService(userRepository,
                new AuthenticationService(userRepository, passwordEncryptor,
                        StringUtils.repeat('x', AuthenticationService.SECRET_MIN_LENGTH), Period.seconds(60),
                        Period.days(60), Period.days(14)),
                new ValidationService());
    }

    private final static Long DEFAULT_OPERATOR = 0L;
    private final static String DEFAULT_PASSWORD = "paSs1234";
    private final static String NEW_PASSWORD = "paSs1234_new";
    private final AtomicLong seq = new AtomicLong(1L);

    private final User adminActor = actor("admin_actor", Role.ADMIN);
    private final User operatorActor = actor("operator_actor", Role.OPERATOR);
    private final User operatorAPIActor = actor("operator_api_actor", Role.OPERATOR_API);

    private final NewUser admin = input("admin", Role.ADMIN, DEFAULT_PASSWORD);
    private final NewUser operator = input("operator", Role.OPERATOR, DEFAULT_PASSWORD);
    private final NewUser operatorAPI = input("operator_api", Role.OPERATOR_API, null);

    @Test
    public void password_is_required_for_operator() {
        Runnable createFn = () -> userService.createUser(operator, adminActor);

        createFn.run();
        verify(userRepository).insertUser(anyObject());

        operator.password = null;
        assertBadPassword(createFn);

        operator.password = "";
        assertBadPassword(createFn);

        operator.password = " ";
        assertBadPassword(createFn);
    }

    @Test
    public void password_is_not_required_for_operator_api() {
        operatorAPI.password = null;
        userService.createUser(operatorAPI, adminActor);
        verify(userRepository).insertUser(anyObject());
    }

    @Test
    public void password_is_required_for_admin() {
        Runnable createFn = () -> userService.createUser(admin, adminActor);

        createFn.run();
        verify(userRepository).insertUser(anyObject());

        admin.password = null;
        assertBadPassword(createFn);
    }

    @Test
    public void operator_is_required_for_operator() {
        Runnable createFn = () -> userService.createUser(operator, adminActor);

        createFn.run();
        verify(userRepository).insertUser(anyObject());

        operator.operatorId = null;
        assertOperatorRequired(createFn);
    }

    @Test
    public void operator_is_required_for_operator_api() {
        Runnable createFn = () -> userService.createUser(operatorAPI, adminActor);

        createFn.run();
        verify(userRepository).insertUser(anyObject());

        operatorAPI.operatorId = null;
        assertOperatorRequired(createFn);
    }

    @Test
    public void operator_is_not_allowed_for_admin() {
        Runnable createFn = () -> userService.createUser(admin, adminActor);

        createFn.run();
        verify(userRepository).insertUser(anyObject());

        admin.operatorId = DEFAULT_OPERATOR;
        assertOperatorNotAllowed(createFn);
    }

    @Test
    public void role_is_required() {
        operator.role = null;
        assertNotNull(() -> userService.createUser(operator, adminActor));
    }

    @Test(expected = AccessDeniedException.class)
    public void operator_cannot_create_admin() {
        userService.createUser(admin, operatorActor);
    }

    @Test(expected = AccessDeniedException.class)
    public void operator_cannot_create_other_operators_user() {
        operatorAPI.operatorId = DEFAULT_OPERATOR + 1;
        userService.createUser(operatorAPI, operatorActor);
    }

    @Test
    public void operator_api_cannot_create_users() {
        assertAccessDenied(() -> userService.createUser(admin, operatorAPIActor));
        assertAccessDenied(() -> userService.createUser(operator, operatorAPIActor));
        assertAccessDenied(() -> userService.createUser(input("same_operator__other_api", Role.OPERATOR_API, null),
                operatorAPIActor));
    }

    @Test
    public void api_token_can_be_reset() {
        DateTime now = DateTime.now();

        when(userRepository.getUser(operatorAPI.id)).thenReturn(userSecret(operatorAPI));
        when(userRepository.getCurrentTime()).thenReturn(now);

        userService.resetToken(operatorAPI.id, adminActor);
        userService.resetToken(operatorAPI.id, operatorActor);
        verify(userRepository, times(2)).revokeTokens(operatorAPI.id, now);
    }

    @Test
    public void non_api_token_cannot_be_reset() {
        when(userRepository.getUser(admin.id)).thenReturn(userSecret(admin));
        when(userRepository.getUser(operator.id)).thenReturn(userSecret(operator));
        when(userRepository.getCurrentTime()).thenReturn(DateTime.now());

        assertPerpetualTokenNotAllowed(() -> userService.resetToken(admin.id, adminActor));
        assertPerpetualTokenNotAllowed(() -> userService.resetToken(operator.id, operatorActor));
    }

    @Test(expected = AccessDeniedException.class)
    public void operator_cannot_reset_other_operators_api_token() {
        NewUser otherAPI = input("other_operator_api", Role.OPERATOR_API, DEFAULT_PASSWORD);
        otherAPI.operatorId = DEFAULT_OPERATOR + 1;

        when(userRepository.getUser(otherAPI.id)).thenReturn(userSecret(otherAPI));
        when(userRepository.getCurrentTime()).thenReturn(DateTime.now());

        userService.resetToken(otherAPI.id, operatorActor);
    }

    @Test(expected = AccessDeniedException.class)
    public void operator_api_cannot_reset_tokens() {
        when(userRepository.getUser(operatorAPI.id)).thenReturn(userSecret(operatorAPI));
        userService.resetToken(operatorAPI.id, operatorAPI);
    }

    @Test
    public void operator_can_update_operator_password() {
        when(userRepository.getUser(operator.id)).thenReturn(userSecret(operator));
        when(passwordEncryptor.encryptPassword(NEW_PASSWORD)).thenReturn("newPassEncrypted");

        userService.updatePassword(operator.id, NEW_PASSWORD, operatorActor);

        verify(userRepository).updatePassword(operator.id, "newPassEncrypted");
    }

    @Test(expected = AccessDeniedException.class)
    public void operator_cannot_update_admin_password() {
        when(userRepository.getUser(admin.id)).thenReturn(userSecret(admin));
        userService.updatePassword(admin.id, NEW_PASSWORD, operatorActor);
    }

    @Test
    public void admin_can_update_operator_password() {
        when(userRepository.getUser(operator.id)).thenReturn(userSecret(operator));
        when(passwordEncryptor.encryptPassword(NEW_PASSWORD)).thenReturn("newPassEncrypted");

        userService.updatePassword(operator.id, NEW_PASSWORD, adminActor);

        verify(userRepository).updatePassword(operator.id, "newPassEncrypted");
    }

    @Test
    public void admin_can_update_admin_password() {
        when(userRepository.getUser(admin.id)).thenReturn(userSecret(admin));
        when(passwordEncryptor.encryptPassword(NEW_PASSWORD)).thenReturn("newPassEncrypted");

        userService.updatePassword(admin.id, NEW_PASSWORD, adminActor);

        verify(userRepository).updatePassword(admin.id, "newPassEncrypted");
    }

    @Test(expected = AccessDeniedException.class)
    public void operator_api_cannot_update_passwords() {
        when(userRepository.getUser(operator.id)).thenReturn(userSecret(operator));
        userService.updatePassword(operator.id, NEW_PASSWORD, operatorAPIActor);
    }

    @Test(expected = AccessDeniedException.class)
    public void operator_cannot_update_other_operators_password() {
        operator.operatorId = DEFAULT_OPERATOR + 1;
        when(userRepository.getUser(operator.id)).thenReturn(userSecret(operator));

        userService.updatePassword(operator.id, NEW_PASSWORD, operatorActor);
    }

    @Test
    public void operator_api_password_cannot_be_updated() {
        when(userRepository.getUser(operatorAPI.id)).thenReturn(userSecret(operatorAPI));
        assertPasswordUpdateNotApplicable(
                () -> userService.updatePassword(operatorAPI.id, NEW_PASSWORD, adminActor));
    }

    @Test
    public void admin_can_delete_other_admin() {
        NewUser otherAdmin = input("other_admin", Role.ADMIN, DEFAULT_PASSWORD);
        when(userRepository.getUser(otherAdmin.id)).thenReturn(userSecret(otherAdmin));

        userService.deleteUser(otherAdmin.id, adminActor);

        verify(userRepository).deleteUser(otherAdmin.id);
    }

    @Test
    public void admin_can_delete_operator() {
        when(userRepository.getUser(operator.id)).thenReturn(userSecret(operator));

        userService.deleteUser(operator.id, adminActor);

        verify(userRepository).deleteUser(operator.id);
    }

    @Test(expected = AccessDeniedException.class)
    public void operator_cannot_delete_admin() {
        when(userRepository.getUser(admin.id)).thenReturn(userSecret(admin));

        userService.deleteUser(admin.id, operatorActor);
    }

    @Test
    public void operator_can_delete_other_user_of_the_same_operator() {
        when(userRepository.getUser(operatorAPI.id)).thenReturn(userSecret(operatorAPI));

        userService.deleteUser(operatorAPI.id, operatorActor);

        verify(userRepository).deleteUser(operatorAPI.id);
    }

    @Test(expected = AccessDeniedException.class)
    public void operator_cannot_delete_other_operators_user() {
        operatorAPI.operatorId = DEFAULT_OPERATOR + 1;
        when(userRepository.getUser(operatorAPI.id)).thenReturn(userSecret(operatorAPI));

        userService.deleteUser(operatorAPI.id, operatorActor);
    }

    @Test(expected = AccessDeniedException.class)
    public void operator_api_cannot_delete_users() {
        when(userRepository.getUser(operator.id)).thenReturn(userSecret(operator));
        userService.deleteUser(operator.id, operatorAPIActor);
    }

    @Test
    public void user_cannot_delete_itself() {
        when(userRepository.getUser(admin.id)).thenReturn(userSecret(admin));
        when(userRepository.getUser(operator.id)).thenReturn(userSecret(operator));

        assertAccessDenied(() -> userService.deleteUser(admin.id, admin));
        assertAccessDenied(() -> userService.deleteUser(operator.id, operator));
    }

    private UserSecret userSecret(User u) {
        UserSecret us = new UserSecret();
        us.user = u;
        return us;
    }

    private NewUser input(String username, Role role, String pass) {
        NewUser input = new NewUser(seq.incrementAndGet(), username, role, pass);
        if (role != Role.ADMIN) {
            input.operatorId = DEFAULT_OPERATOR;
        }
        return input;
    }

    private User actor(String username, Role role) {
        User actor = new User(seq.incrementAndGet(), username, role);
        if (role != Role.ADMIN) {
            actor.operatorId = DEFAULT_OPERATOR;
        }
        return actor;
    }

    private static void assertAccessDenied(Runnable r) {
        try {
            r.run();
            Assert.fail("did not throw AccessDeniedException");
        } catch (AccessDeniedException expected) {
        }
    }
}