/******************************************************************************* * Copyright (c) 2012-2015 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.api.user.server; import sun.security.acl.PrincipalImpl; import org.eclipse.che.api.core.rest.ApiExceptionMapper; import org.eclipse.che.api.core.rest.shared.dto.Link; import org.eclipse.che.api.user.server.dao.PreferenceDao; import org.eclipse.che.api.user.server.dao.Profile; import org.eclipse.che.api.user.server.dao.User; import org.eclipse.che.api.user.server.dao.UserDao; import org.eclipse.che.api.user.server.dao.UserProfileDao; import org.eclipse.che.api.user.shared.dto.ProfileDescriptor; import org.eclipse.che.commons.json.JsonHelper; import org.everrest.core.impl.ApplicationContextImpl; import org.everrest.core.impl.ApplicationProviderBinder; import org.everrest.core.impl.ContainerRequest; import org.everrest.core.impl.ContainerResponse; import org.everrest.core.impl.EnvironmentContext; import org.everrest.core.impl.EverrestConfiguration; import org.everrest.core.impl.EverrestProcessor; import org.everrest.core.impl.ProviderBinder; import org.everrest.core.impl.ResourceBinderImpl; import org.everrest.core.tools.DependencySupplierImpl; import org.everrest.core.tools.ResourceLauncher; import org.mockito.Mock; import org.mockito.testng.MockitoTestNGListener; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import javax.ws.rs.core.SecurityContext; import javax.ws.rs.core.UriInfo; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import static org.eclipse.che.api.user.server.Constants.LINK_REL_UPDATE_CURRENT_USER_PROFILE; import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_CURRENT_USER_PROFILE; import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_USER_PROFILE_BY_ID; import static org.eclipse.che.api.user.server.Constants.LINK_REL_UPDATE_PREFERENCES; import static org.eclipse.che.api.user.server.Constants.LINK_REL_UPDATE_USER_PROFILE_BY_ID; import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; import static java.util.Collections.singleton; import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static javax.ws.rs.core.Response.Status.OK; import static javax.ws.rs.core.Response.Status.NO_CONTENT; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; /** * Tests for {@link UserProfileService} * * @author Max Shaposhnik * @author Eugene Voevodin */ @Listeners(value = {MockitoTestNGListener.class}) public class UserProfileServiceTest { private static final String BASE_URI = "http://localhost/service"; private static final String SERVICE_PATH = BASE_URI + "/profile"; @Mock private UserProfileDao profileDao; @Mock private UserDao userDao; @Mock private PreferenceDao preferenceDao; @Mock private User testUser; @Mock private UriInfo uriInfo; @Mock private EnvironmentContext environmentContext; @Mock private SecurityContext securityContext; private ResourceLauncher launcher; private UserProfileService service; @BeforeMethod public void setUp() throws Exception { final ResourceBinderImpl resources = new ResourceBinderImpl(); resources.addResource(UserProfileService.class, null); final DependencySupplierImpl dependencies = new DependencySupplierImpl(); dependencies.addComponent(UserDao.class, userDao); dependencies.addComponent(UserProfileDao.class, profileDao); dependencies.addComponent(PreferenceDao.class, preferenceDao); final URI uri = new URI(BASE_URI); final ContainerRequest req = new ContainerRequest(null, uri, uri, null, null, securityContext); final ApplicationContextImpl contextImpl = new ApplicationContextImpl(req, null, ProviderBinder.getInstance()); contextImpl.setDependencySupplier(dependencies); ApplicationContextImpl.setCurrent(contextImpl); final ApplicationProviderBinder binder = new ApplicationProviderBinder(); binder.addExceptionMapper(ApiExceptionMapper.class); final EverrestProcessor processor = new EverrestProcessor(resources, binder, dependencies, new EverrestConfiguration(), null); launcher = new ResourceLauncher(processor); service = (UserProfileService)resources.getMatchedResource("/profile", new ArrayList<String>()) .getInstance(ApplicationContextImpl.getCurrent()); //setup testUser final String id = "user123abc456def"; final String email = "user@testuser.com"; when(testUser.getEmail()).thenReturn(email); when(testUser.getId()).thenReturn(id); when(environmentContext.get(SecurityContext.class)).thenReturn(securityContext); when(securityContext.getUserPrincipal()).thenReturn(new PrincipalImpl(email)); when(userDao.getByAlias(email)).thenReturn(testUser); when(userDao.getById(id)).thenReturn(testUser); org.eclipse.che.commons.env.EnvironmentContext.getCurrent().setUser(new org.eclipse.che.commons.user.User() { @Override public String getName() { return testUser.getEmail(); } @Override public boolean isMemberOf(String s) { return false; } @Override public String getToken() { return null; } @Override public String getId() { return testUser.getId(); } @Override public boolean isTemporary() { return false; } }); } @Test public void shouldBeAbleToGetCurrentProfile() throws Exception { final Profile current = new Profile().withId(testUser.getId()).withUserId(testUser.getId()); when(profileDao.getById(current.getId())).thenReturn(current); final ContainerResponse response = makeRequest("GET", SERVICE_PATH, null); assertEquals(response.getStatus(), OK.getStatusCode()); final ProfileDescriptor descriptor = (ProfileDescriptor)response.getEntity(); assertEquals(descriptor.getId(), current.getId()); assertEquals(descriptor.getUserId(), current.getUserId()); assertEquals(descriptor.getAttributes().get("email"), testUser.getEmail()); } @Test public void shouldBeAbleToGetPreferences() throws Exception { final Map<String, String> preferences = new HashMap<>(8); preferences.put("test1", "test1"); preferences.put("test2", "test2"); preferences.put("test3", "test3"); when(preferenceDao.getPreferences(testUser.getId())).thenReturn(preferences); final ContainerResponse response = makeRequest("GET", SERVICE_PATH + "/prefs", null); assertEquals(response.getStatus(), OK.getStatusCode()); assertEquals(response.getEntity(), preferences); } @Test public void shouldBeAbleToRemoveAttributes() throws Exception { final Map<String, String> attributes = new HashMap<>(8); attributes.put("test", "test"); attributes.put("test1", "test"); attributes.put("test2", "test"); final Profile profile = new Profile().withId(testUser.getId()).withAttributes(attributes); when(profileDao.getById(profile.getId())).thenReturn(profile); final ContainerResponse response = makeRequest("DELETE", SERVICE_PATH + "/attributes", asList("test", "test2")); assertEquals(response.getStatus(), NO_CONTENT.getStatusCode()); verify(profileDao, times(1)).update(profile); assertEquals(attributes.size(), 1); assertNotNull(attributes.get("test1")); } @Test public void shouldRemoveAllAttributesIfNullWasSent() throws Exception { final Map<String, String> attributes = new HashMap<>(8); attributes.put("test", "test"); attributes.put("test1", "test"); attributes.put("test2", "test"); final Profile profile = new Profile().withId(testUser.getId()).withAttributes(attributes); when(profileDao.getById(profile.getId())).thenReturn(profile); final ContainerResponse response = makeRequest("DELETE", SERVICE_PATH + "/attributes", null); assertEquals(response.getStatus(), NO_CONTENT.getStatusCode()); verify(profileDao, times(1)).update(profile); assertTrue(attributes.isEmpty()); } @Test public void shouldBeAbleToUpdatePreferences() throws Exception { final Map<String, String> preferences = new HashMap<>(8); preferences.put("test1", "test1"); preferences.put("test2", "test2"); preferences.put("test3", "test3"); when(preferenceDao.getPreferences(testUser.getId())).thenReturn(preferences); final Map<String, String> update = singletonMap("test1", "new_value"); final ContainerResponse response = makeRequest("POST", SERVICE_PATH + "/prefs", update); preferences.putAll(update); assertEquals(response.getStatus(), OK.getStatusCode()); assertEquals(response.getEntity(), preferences); verify(preferenceDao).setPreferences(testUser.getId(), preferences); } @Test public void shouldThrowExceptionIfPreferencesUpdateIsNull() throws Exception { final ContainerResponse response = makeRequest("POST", SERVICE_PATH + "/prefs", null); assertEquals(response.getStatus(), 409); } @Test public void shouldThrowExceptionIfPreferencesUpdateIsEmpty() throws Exception { final ContainerResponse response = makeRequest("POST", SERVICE_PATH + "/prefs", emptyMap()); assertEquals(response.getStatus(), 409); } @Test public void shouldBeAbleToRemovePreferences() throws Exception { final Map<String, String> preferences = new HashMap<>(8); preferences.put("test1", "test1"); preferences.put("test2", "test2"); preferences.put("test3", "test3"); when(preferenceDao.getPreferences(testUser.getId())).thenReturn(preferences); final ContainerResponse response = makeRequest("DELETE", SERVICE_PATH + "/prefs", singletonList("test1")); assertEquals(response.getStatus(), NO_CONTENT.getStatusCode()); assertNull(preferences.get("test1")); verify(preferenceDao).setPreferences(testUser.getId(), preferences); } @Test public void shouldRemoveAllPreferencesIfNullWasSend() throws Exception { final ContainerResponse response = makeRequest("DELETE", SERVICE_PATH + "/prefs", null); assertEquals(response.getStatus(), NO_CONTENT.getStatusCode()); verify(preferenceDao).remove(testUser.getId()); } @Test public void shouldBeAbleToGetProfileById() throws Exception { final Profile profile = new Profile().withId(testUser.getId()) .withUserId(testUser.getId()); when(profileDao.getById(profile.getId())).thenReturn(profile); final ContainerResponse response = makeRequest("GET", SERVICE_PATH + "/" + profile.getId(), null); assertEquals(response.getStatus(), OK.getStatusCode()); final ProfileDescriptor descriptor = (ProfileDescriptor)response.getEntity(); assertEquals(descriptor.getUserId(), profile.getId()); assertEquals(descriptor.getId(), profile.getId()); assertEquals(descriptor.getAttributes().get("email"), testUser.getEmail()); } @Test public void shouldBeAbleToUpdateCurrentProfileAttributes() throws Exception { final Profile profile = new Profile().withId(testUser.getId()) .withAttributes(new HashMap<>(singletonMap("existed", "old"))); when(profileDao.getById(profile.getId())).thenReturn(profile); final Map<String, String> attributes = new HashMap<>(4); attributes.put("existed", "new"); attributes.put("new", "value"); final ContainerResponse response = makeRequest("POST", SERVICE_PATH, attributes); assertEquals(response.getStatus(), OK.getStatusCode()); verify(profileDao, times(1)).update(profile); assertEquals(((ProfileDescriptor)response.getEntity()).getAttributes(), attributes); } @Test public void shouldThrowExceptionIfAttributesUpdateForCurrentProfileIsNull() throws Exception { final ContainerResponse response = makeRequest("POST", SERVICE_PATH, null); assertEquals(response.getStatus(), 409); } @Test public void shouldThrowExceptionIfAttributesUpdateForCurrentProfileIsEmpty() throws Exception { final ContainerResponse response = makeRequest("POST", SERVICE_PATH, emptyMap()); assertEquals(response.getStatus(), 409); } @Test public void shouldThrowExceptionIfAttributesUpdateForSpecificProfileIsNull() throws Exception { final ContainerResponse response = makeRequest("POST", SERVICE_PATH + "/any_profile_id", null); assertEquals(response.getStatus(), 409); } @Test public void shouldThrowExceptionIfAttributesUpdateForSpecificProfileIsEmpty() throws Exception { final ContainerResponse response = makeRequest("POST", SERVICE_PATH + "/any_profile_id", emptyMap()); assertEquals(response.getStatus(), 409); } @Test public void shouldBeAbleToUpdateProfileById() throws Exception { final Profile profile = new Profile().withId(testUser.getId()) .withUserId(testUser.getId()) .withAttributes(new HashMap<>(singletonMap("existed", "old"))); when(profileDao.getById(testUser.getId())).thenReturn(profile); final Map<String, String> attributes = new HashMap<>(4); attributes.put("existed", "new"); attributes.put("new", "value"); final ContainerResponse response = makeRequest("POST", SERVICE_PATH + "/" + profile.getId(), attributes); assertEquals(response.getStatus(), OK.getStatusCode()); assertEquals(((ProfileDescriptor)response.getEntity()).getAttributes(), attributes); verify(profileDao, times(1)).update(profile); } @Test public void testLinksForUser() { final Profile profile = new Profile().withId(testUser.getId()); when(securityContext.isUserInRole("user")).thenReturn(true); final Set<String> expectedRels = new HashSet<>(asList(LINK_REL_GET_CURRENT_USER_PROFILE, LINK_REL_UPDATE_CURRENT_USER_PROFILE, LINK_REL_GET_USER_PROFILE_BY_ID, LINK_REL_UPDATE_PREFERENCES)); assertEquals(asRels(service.toDescriptor(profile, securityContext).getLinks()), expectedRels); } @Test public void testLinksForSystemAdmin() { final Profile profile = new Profile().withId(testUser.getId()); when(securityContext.isUserInRole("system/admin")).thenReturn(true); final Set<String> expectedRels = new HashSet<>(asList(LINK_REL_UPDATE_USER_PROFILE_BY_ID, LINK_REL_GET_USER_PROFILE_BY_ID)); assertEquals(asRels(service.toDescriptor(profile, securityContext).getLinks()), expectedRels); } @Test public void testLinksForSystemManager() { final Profile profile = new Profile().withId(testUser.getId()); when(securityContext.isUserInRole("system/manager")).thenReturn(true); assertEquals(asRels(service.toDescriptor(profile, securityContext).getLinks()), singleton(LINK_REL_GET_USER_PROFILE_BY_ID)); } private Set<String> asRels(List<Link> links) { final Set<String> rels = new HashSet<>(); for (Link link : links) { rels.add(link.getRel()); } return rels; } private ContainerResponse makeRequest(String method, String path, Object entity) throws Exception { Map<String, List<String>> headers = null; byte[] data = null; if (entity != null) { headers = new HashMap<>(); headers.put("Content-Type", singletonList("application/json")); data = JsonHelper.toJson(entity).getBytes(); } return launcher.service(method, path, BASE_URI, headers, data, null, environmentContext); } }