/******************************************************************************* * 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.workspace.server; import sun.security.acl.PrincipalImpl; import org.eclipse.che.api.account.server.dao.Account; import org.eclipse.che.api.account.server.dao.AccountDao; import org.eclipse.che.api.account.server.dao.Subscription; import org.eclipse.che.api.core.NotFoundException; import org.eclipse.che.api.core.ServerException; import org.eclipse.che.api.core.rest.ApiExceptionMapper; import org.eclipse.che.api.core.rest.shared.dto.Link; import org.eclipse.che.api.core.rest.shared.dto.ServiceError; 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.workspace.server.dao.Member; import org.eclipse.che.api.workspace.server.dao.MemberDao; import org.eclipse.che.api.workspace.server.dao.Workspace; import org.eclipse.che.api.workspace.server.dao.WorkspaceDao; import org.eclipse.che.api.workspace.shared.dto.MemberDescriptor; import org.eclipse.che.api.workspace.shared.dto.NewMembership; import org.eclipse.che.api.workspace.shared.dto.NewWorkspace; import org.eclipse.che.api.workspace.shared.dto.WorkspaceDescriptor; import org.eclipse.che.api.workspace.shared.dto.WorkspaceUpdate; import org.eclipse.che.commons.json.JsonHelper; import org.eclipse.che.dto.server.DtoFactory; 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.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 java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; 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.project.server.Constants.LINK_REL_GET_PROJECTS; import static org.eclipse.che.api.user.server.Constants.LINK_REL_GET_USER_BY_ID; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static javax.ws.rs.core.Response.Status; import static javax.ws.rs.core.Response.Status.CONFLICT; import static javax.ws.rs.core.Response.Status.CREATED; import static javax.ws.rs.core.Response.Status.FORBIDDEN; import static javax.ws.rs.core.Response.Status.NO_CONTENT; import static javax.ws.rs.core.Response.Status.OK; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; /** * Tests for {@link WorkspaceService} * * @author Eugene Voevodin * @see WorkspaceService */ @Listeners(value = {MockitoTestNGListener.class}) public class WorkspaceServiceTest { private static final String BASE_URI = "http://localhost/service"; private static final String SERVICE_PATH = BASE_URI + "/workspace"; @Mock WorkspaceDao workspaceDao; @Mock UserDao userDao; @Mock MemberDao memberDao; @Mock AccountDao accountDao; @Mock UserProfileDao profileDao; @Mock PreferenceDao preferenceDao; @Mock SecurityContext securityContext; @Mock EnvironmentContext environmentContext; ResourceLauncher launcher; WorkspaceService service; User testUser; @BeforeMethod public void before() throws Exception { //set up launcher final ResourceBinderImpl resources = new ResourceBinderImpl(); resources.addResource(WorkspaceService.class, null); final DependencySupplierImpl dependencies = new DependencySupplierImpl(); dependencies.addComponent(WorkspaceDao.class, workspaceDao); dependencies.addComponent(MemberDao.class, memberDao); dependencies.addComponent(UserDao.class, userDao); dependencies.addComponent(UserProfileDao.class, profileDao); dependencies.addComponent(AccountDao.class, accountDao); dependencies.addComponent(PreferenceDao.class, preferenceDao); final ApplicationProviderBinder binder = new ApplicationProviderBinder(); binder.addExceptionMapper(ApiExceptionMapper.class); 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, binder); contextImpl.setDependencySupplier(dependencies); ApplicationContextImpl.setCurrent(contextImpl); final EverrestProcessor processor = new EverrestProcessor(resources, binder, dependencies, new EverrestConfiguration(), null); launcher = new ResourceLauncher(processor); service = (WorkspaceService)resources.getMatchedResource("/workspace", new ArrayList<String>()) .getInstance(ApplicationContextImpl.getCurrent()); when(environmentContext.get(SecurityContext.class)).thenReturn(securityContext); //set up test user final String userId = "test_user_id"; final String userEmail = "test@test.com"; testUser = new User().withId(userId).withEmail(userEmail); when(userDao.getById(userId)).thenReturn(testUser); when(userDao.getByAlias(userEmail)).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; } }); when(securityContext.getUserPrincipal()).thenReturn(new PrincipalImpl(testUser.getEmail())); } @Test public void shouldBeAbleToCreateFirstWorkspace() throws Exception { //create new account with empty workspace list final Account testAccount = createAccount(); when(workspaceDao.getByAccount(testAccount.getId())).thenReturn(Collections.<Workspace>emptyList()); //new workspace descriptor final NewWorkspace newWorkspace = newDTO(NewWorkspace.class).withName("new_workspace") .withAccountId(testAccount.getId()); final WorkspaceDescriptor descriptor = doPost(SERVICE_PATH, newWorkspace, CREATED); assertEquals(descriptor.getName(), newWorkspace.getName()); assertEquals(descriptor.getAccountId(), newWorkspace.getAccountId()); assertTrue(descriptor.getAttributes().isEmpty()); assertFalse(descriptor.isTemporary()); verify(workspaceDao).create(any(Workspace.class)); } @Test public void workspaceNameShouldBeGeneratedIfNewWorkspaceDoesNotContainsIt() throws Exception { //create new account with empty workspace list final Account testAccount = createAccount(); when(workspaceDao.getByAccount(testAccount.getId())).thenReturn(Collections.<Workspace>emptyList()); final String email = testUser.getEmail(); final String expectedWsName = email.substring(0, email.indexOf('@')); when(workspaceDao.getByName(expectedWsName)).thenThrow(new NotFoundException("not found")); final NewWorkspace newWorkspace = newDTO(NewWorkspace.class).withAccountId(testAccount.getId()); final WorkspaceDescriptor descriptor = doPost(SERVICE_PATH, newWorkspace, CREATED); assertEquals(descriptor.getName(), expectedWsName); } @Test public void workspaceNameShouldBeGeneratedUntilNotReservedIsFound() throws Exception { //create new account with empty workspace list final Account testAccount = createAccount(); when(workspaceDao.getByAccount(testAccount.getId())).thenReturn(Collections.<Workspace>emptyList()); final String email = testUser.getEmail(); final String expectedWsName = email.substring(0, email.indexOf('@')) + "11"; when(workspaceDao.getByName(expectedWsName)).thenThrow(new NotFoundException("not found")); final NewWorkspace newWorkspace = newDTO(NewWorkspace.class).withAccountId(testAccount.getId()); final WorkspaceDescriptor descriptor = doPost(SERVICE_PATH, newWorkspace, CREATED); assertEquals(descriptor.getName(), expectedWsName); } @Test public void shouldNotBeAbleToCreateWorkspaceAssociatedWithOtherAccount() throws Exception { //new workspace descriptor final NewWorkspace newWorkspace = newDTO(NewWorkspace.class).withName("new_workspace") .withAccountId("fake_account_id"); when(accountDao.getByOwner(testUser.getId())).thenReturn(new ArrayList<Account>()); final String errorJson = doPost(SERVICE_PATH, newWorkspace, CONFLICT); assertEquals(asError(errorJson).getMessage(), "You can create workspace associated only with your own account"); } @Test public void shouldBeAbleToCreateMultiWorkspaces() throws Exception { final Account testAccount = createAccount(); when(workspaceDao.getByAccount(testAccount.getId())).thenReturn(singletonList(new Workspace())); //new workspace descriptor final NewWorkspace newWorkspace = newDTO(NewWorkspace.class).withName("test_workspace") .withAccountId(testAccount.getId()); final WorkspaceDescriptor descriptor = doPost(SERVICE_PATH, newWorkspace, CREATED); assertEquals(descriptor.getName(), newWorkspace.getName()); assertEquals(descriptor.getAccountId(), newWorkspace.getAccountId()); verify(workspaceDao).create(any(Workspace.class)); } @Test public void shouldNotBeAbleToCreateNewWorkspaceWithNotValidAttribute() throws Exception { final NewWorkspace newWorkspace = newDTO(NewWorkspace.class).withName("new_workspace") .withAccountId("fake_account") .withAttributes(singletonMap("codenvy:god_mode", "true")); final String errorJson = doPost(SERVICE_PATH, newWorkspace, CONFLICT); assertEquals(asError(errorJson).getMessage(), "Attribute2 name 'codenvy:god_mode' is not valid"); } @Test public void shouldBeAbleToCreateNewTemporaryWorkspace() throws Exception { final NewWorkspace newWorkspace = newDTO(NewWorkspace.class).withName("new_workspace") .withAccountId("fake_account_id"); createAccount(); final WorkspaceDescriptor descriptor = doPost(SERVICE_PATH + "/temp", newWorkspace, CREATED); assertTrue(descriptor.isTemporary()); assertEquals(descriptor.getName(), newWorkspace.getName()); assertEquals(descriptor.getAccountId(), newWorkspace.getAccountId()); verify(userDao, never()).create(any(User.class)); verify(profileDao, never()).create(any(Profile.class)); verify(workspaceDao).create(any(Workspace.class)); } @Test public void shouldBeAbleToCreateNewTemporaryWorkspaceWhenUserDoesNotExist() throws Exception { when(securityContext.getUserPrincipal()).thenReturn(null); final NewWorkspace newWorkspace = newDTO(NewWorkspace.class).withName("new_workspace") .withAccountId("fake_account"); final WorkspaceDescriptor descriptor = doPost(SERVICE_PATH + "/temp", newWorkspace, CREATED); assertTrue(descriptor.isTemporary()); assertEquals(descriptor.getName(), newWorkspace.getName()); assertEquals(descriptor.getAccountId(), newWorkspace.getAccountId()); verify(userDao).create(any(User.class)); verify(profileDao).create(any(Profile.class)); verify(workspaceDao).create(any(Workspace.class)); } @Test public void shouldNotBeAbleToCreateTemporaryWorkspaceWithNotValidAttribute() throws Exception { final Workspace testWorkspace = createWorkspace(); testWorkspace.getAttributes().put("codenvy:god_mode", "true"); final String errorJson = doPost(SERVICE_PATH + "/temp", testWorkspace, CONFLICT); assertEquals(asError(errorJson).getMessage(), "Attribute2 name 'codenvy:god_mode' is not valid"); } @Test public void shouldBeAbleToGetWorkspaceByIdWithAttributesForWorkspaceAdmin() throws Exception { final Workspace testWorkspace = createWorkspace(); final Map<String, String> actualAttributes = new HashMap<>(testWorkspace.getAttributes()); prepareRole("workspace/admin"); final WorkspaceDescriptor descriptor = doGet(SERVICE_PATH + "/" + testWorkspace.getId()); assertEquals(descriptor.getAttributes(), actualAttributes); } @Test public void shouldBeAbleToGetWorkspaceByIdWithAttributesForWorkspaceDeveloper() throws Exception { final Workspace testWorkspace = createWorkspace(); final Map<String, String> actualAttributes = new HashMap<>(testWorkspace.getAttributes()); prepareRole("workspace/developer"); final WorkspaceDescriptor descriptor = doGet(SERVICE_PATH + "/" + testWorkspace.getId()); assertEquals(descriptor.getAttributes(), actualAttributes); } @Test public void shouldBeAbleToGetWorkspaceByIdWithAttributesForAccountOwner() throws Exception { final Workspace testWorkspace = createWorkspace(); final Map<String, String> actualAttributes = new HashMap<>(testWorkspace.getAttributes()); prepareRole("account/owner"); final WorkspaceDescriptor descriptor = doGet(SERVICE_PATH + "/" + testWorkspace.getId()); assertEquals(descriptor.getAttributes(), actualAttributes); } @Test public void shouldBeAbleToGetWorkspaceByIdWithEmptyAttributesForAnyone() throws Exception { final Workspace testWorkspace = createWorkspace(); final WorkspaceDescriptor descriptor = doGet(SERVICE_PATH + "/" + testWorkspace.getId()); assertEquals(descriptor.getId(), testWorkspace.getId()); assertEquals(descriptor.getName(), testWorkspace.getName()); assertEquals(descriptor.isTemporary(), testWorkspace.isTemporary()); assertEquals(descriptor.getAccountId(), testWorkspace.getAccountId()); assertTrue(descriptor.getAttributes().isEmpty()); } @Test public void shouldBeAbleToGetWorkspaceByIdWithAttributeAllowAnyoneAddMember() throws Exception { final Workspace testWorkspace = createWorkspace(); testWorkspace.getAttributes().put("test2_attribute", "test"); testWorkspace.getAttributes().put("allowAnyoneAddMember", "true"); final WorkspaceDescriptor descriptor = doGet(SERVICE_PATH + "/" + testWorkspace.getId()); assertEquals(descriptor.getId(), testWorkspace.getId()); assertEquals(descriptor.getName(), testWorkspace.getName()); assertEquals(descriptor.isTemporary(), testWorkspace.isTemporary()); assertEquals(descriptor.getAccountId(), testWorkspace.getAccountId()); assertEquals(descriptor.getAttributes().size(), 1); assertEquals(descriptor.getAttributes().get("allowAnyoneAddMember"), "true"); } @Test public void shouldBeAbleToGetWorkspaceByNameForWorkspaceAdmin() throws Exception { final Workspace testWorkspace = createWorkspace(); final Map<String, String> actualAttributes = new HashMap<>(testWorkspace.getAttributes()); prepareRole("workspace/admin"); final WorkspaceDescriptor descriptor = doGet(SERVICE_PATH + "?name=" + testWorkspace.getName()); assertEquals(descriptor.getAttributes(), actualAttributes); } @Test public void shouldBeAbleToGetWorkspaceByNameForWorkspaceDeveloper() throws Exception { final Workspace testWorkspace = createWorkspace(); final Map<String, String> actualAttributes = new HashMap<>(testWorkspace.getAttributes()); prepareRole("workspace/developer"); final WorkspaceDescriptor descriptor = doGet(SERVICE_PATH + "?name=" + testWorkspace.getName()); assertEquals(descriptor.getAttributes(), actualAttributes); } @Test public void shouldBeAbleToGetWorkspaceByNameForWorkspaceAccountOwner() throws Exception { final Workspace testWorkspace = createWorkspace(); final Map<String, String> actualAttributes = new HashMap<>(testWorkspace.getAttributes()); prepareRole("account/owner"); final WorkspaceDescriptor descriptor = doGet(SERVICE_PATH + "?name=" + testWorkspace.getName()); assertEquals(descriptor.getAttributes(), actualAttributes); } @Test public void shouldBeAbleToGetWorkspaceByNameWithEmptyAttributesForAnyone() throws Exception { final Workspace testWorkspace = createWorkspace(); final WorkspaceDescriptor descriptor = doGet(SERVICE_PATH + "/" + testWorkspace.getId()); assertEquals(descriptor.getId(), testWorkspace.getId()); assertEquals(descriptor.getName(), testWorkspace.getName()); assertEquals(descriptor.isTemporary(), testWorkspace.isTemporary()); assertEquals(descriptor.getAccountId(), testWorkspace.getAccountId()); assertTrue(descriptor.getAttributes().isEmpty()); } @Test public void shouldBeAbleToGetWorkspaceByNameWithAttributeAllowAnyoneAddMember() throws Exception { final Workspace testWorkspace = createWorkspace(); testWorkspace.getAttributes().put("test2_attribute", "test"); testWorkspace.getAttributes().put("allowAnyoneAddMember", "true"); final WorkspaceDescriptor descriptor = doGet(SERVICE_PATH + "/" + testWorkspace.getId()); assertEquals(descriptor.getId(), testWorkspace.getId()); assertEquals(descriptor.getName(), testWorkspace.getName()); assertEquals(descriptor.isTemporary(), testWorkspace.isTemporary()); assertEquals(descriptor.getAccountId(), testWorkspace.getAccountId()); assertEquals(descriptor.getAttributes().size(), 1); assertEquals(descriptor.getAttributes().get("allowAnyoneAddMember"), "true"); } @Test public void shouldNotBeAbleToRemoveAttributeIfAttributeNameStartsWithCodenvy() throws Exception { final Workspace testWorkspace = createWorkspace(); final String errorJson = doDelete(SERVICE_PATH + "/" + testWorkspace.getId() + "/attribute?name=codenvy:runner_ram", CONFLICT); assertEquals(asError(errorJson).getMessage(), "Attribute2 name 'codenvy:runner_ram' is not valid"); } @Test public void shouldBeAbleToRemoveAttribute() throws Exception { final Workspace testWorkspace = createWorkspace().withAttributes(new HashMap<>(singletonMap("test", "test"))); doDelete(SERVICE_PATH + "/" + testWorkspace.getId() + "/attribute?name=test", NO_CONTENT); verify(workspaceDao).update(testWorkspace); assertTrue(testWorkspace.getAttributes().isEmpty()); } @Test public void shouldBeAbleToUpdateWorkspace() throws Exception { final Workspace testWorkspace = createWorkspace().withAttributes(new HashMap<>(singletonMap("test", "test"))); final String newName = "new_workspace"; //workspace update descriptor final WorkspaceUpdate update = newDTO(WorkspaceUpdate.class).withName(newName) .withAttributes(singletonMap("test", "other_value")); final WorkspaceDescriptor descriptor = doPost(SERVICE_PATH + "/" + testWorkspace.getId(), update, OK); assertEquals(descriptor.getName(), newName); assertEquals(descriptor.getAttributes().size(), 1); assertEquals(descriptor.getAttributes().get("test"), "other_value"); verify(workspaceDao).update(testWorkspace); } @Test public void shouldNotBeAbleToUpdateWorkspaceIfUpdateContainsNotValidAttribute() throws Exception { final Workspace testWorkspace = createWorkspace(); final String newName = "new_workspace"; //ensure workspace with update workspace name doesn't exist when(workspaceDao.getByName(newName)).thenThrow(new NotFoundException("workspace doesn't exist")); //workspace update descriptor final WorkspaceUpdate update = newDTO(WorkspaceUpdate.class).withName(newName) .withAttributes(singletonMap("codenvy:runner_ram", "64GB")); final String errorJson = doPost(SERVICE_PATH + "/" + testWorkspace.getId(), update, CONFLICT); assertEquals(asError(errorJson).getMessage(), "Attribute2 name 'codenvy:runner_ram' is not valid"); } @Test public void shouldBeAbleToGetWorkspaceMembers() throws Exception { final Workspace testWorkspace = createWorkspace(); final Member testMember = new Member().withWorkspaceId(testWorkspace.getId()) .withUserId(testUser.getId()) .withRoles(singletonList("workspace/admin")); final List<Member> members = singletonList(testMember); when(memberDao.getWorkspaceMembers(testWorkspace.getId())).thenReturn(members); final List<MemberDescriptor> descriptors = doGet(SERVICE_PATH + "/" + testWorkspace.getId() + "/members"); assertEquals(descriptors.size(), 1); final MemberDescriptor descriptor = descriptors.get(0); assertEquals(descriptor.getUserId(), testMember.getUserId()); assertEquals(descriptor.getWorkspaceReference().getId(), testMember.getWorkspaceId()); assertEquals(descriptor.getRoles(), testMember.getRoles()); } @Test public void shouldBeAbleToGetWorkspaceMember() throws Exception { final Workspace testWorkspace = createWorkspace(); final Member testMember = new Member().withWorkspaceId(testWorkspace.getId()) .withUserId(testUser.getId()) .withRoles(singletonList("workspace/admin")); when(memberDao.getWorkspaceMember(testMember.getWorkspaceId(), testMember.getUserId())).thenReturn(testMember); final MemberDescriptor descriptor = doGet(SERVICE_PATH + "/" + testMember.getWorkspaceId() + "/membership"); assertEquals(descriptor.getUserId(), testMember.getUserId()); assertEquals(descriptor.getWorkspaceReference().getId(), testMember.getWorkspaceId()); assertEquals(descriptor.getRoles(), testMember.getRoles()); } @Test public void shouldBeAbleToAddWorkspaceMemberToNotEmptyWorkspaceForWorkspaceAdmin() throws Exception { final Workspace testWorkspace = createWorkspace(); when(memberDao.getWorkspaceMembers(testWorkspace.getId())).thenReturn(singletonList(new Member())); final NewMembership membership = newDTO(NewMembership.class).withRoles(singletonList("workspace/developer")) .withUserId("test_user_id"); prepareRole("workspace/admin"); final MemberDescriptor descriptor = doPost(SERVICE_PATH + "/" + testWorkspace.getId() + "/members", membership, CREATED); assertEquals(descriptor.getUserId(), membership.getUserId()); assertEquals(descriptor.getWorkspaceReference().getId(), testWorkspace.getId()); assertEquals(descriptor.getRoles(), membership.getRoles()); verify(memberDao).create(any(Member.class)); } @Test public void shouldNotBeAbleToAddMemberToNotEmptyWorkspaceIfUserIsNotWorkspaceAdmin() throws Exception { final Workspace testWorkspace = createWorkspace(); when(memberDao.getWorkspaceMembers(testWorkspace.getId())).thenReturn(singletonList(new Member())); final NewMembership membership = newDTO(NewMembership.class).withRoles(singletonList("workspace/developer")) .withUserId(testUser.getId()); prepareRole("workspace/developer"); final String errorJson = doPost(SERVICE_PATH + "/" + testWorkspace.getId() + "/members", membership, FORBIDDEN); assertEquals(asError(errorJson).getMessage(), "Access denied"); } @Test public void shouldBeAbleToAddMemberToNotEmptyWorkspaceIfUserIsAccountOwner() throws Exception { final Workspace testWorkspace = createWorkspace(); final Account account = createAccount(); when(workspaceDao.getByAccount(account.getId())).thenReturn(singletonList(testWorkspace)); when(memberDao.getWorkspaceMembers(testWorkspace.getId())).thenReturn(singletonList(new Member())); final NewMembership membership = newDTO(NewMembership.class).withRoles(singletonList("workspace/developer")) .withUserId(testUser.getId()); prepareRole("account/owner"); final MemberDescriptor descriptor = doPost(SERVICE_PATH + "/" + testWorkspace.getId() + "/members", membership, CREATED); assertEquals(descriptor.getUserId(), membership.getUserId()); assertEquals(descriptor.getWorkspaceReference().getId(), testWorkspace.getId()); assertEquals(descriptor.getRoles(), membership.getRoles()); verify(memberDao).create(any(Member.class)); } @Test public void shouldBeAbleToAddMemberToNotEmptyWorkspaceForAnyUserIfAllowAttributeIsTrue() throws Exception { final Workspace testWorkspace = createWorkspace(); when(memberDao.getWorkspaceMembers(testWorkspace.getId())).thenReturn(singletonList(new Member())); testWorkspace.getAttributes().put("allowAnyoneAddMember", "true"); final NewMembership membership = newDTO(NewMembership.class).withRoles(singletonList("workspace/developer")) .withUserId(testUser.getId()); final MemberDescriptor descriptor = doPost(SERVICE_PATH + "/" + testWorkspace.getId() + "/members", membership, CREATED); assertEquals(descriptor.getRoles(), membership.getRoles()); assertEquals(descriptor.getUserId(), membership.getUserId()); assertEquals(descriptor.getWorkspaceReference().getId(), testWorkspace.getId()); verify(memberDao).create(any(Member.class)); } @Test public void shouldNotBeAbleToAddMemberToNotEmptyWorkspaceForAnyUserIfAllowAttributeIsFalse() throws Exception { final Workspace testWorkspace = createWorkspace(); when(memberDao.getWorkspaceMembers(testWorkspace.getId())).thenReturn(singletonList(any(Member.class))); testWorkspace.getAttributes().put("allowAnyoneAddMember", "false"); final NewMembership membership = newDTO(NewMembership.class).withRoles(singletonList("workspace/developer")) .withUserId(testUser.getId()); final String errorJson = doPost(SERVICE_PATH + "/" + testWorkspace.getId() + "/members", membership, FORBIDDEN); assertEquals(asError(errorJson).getMessage(), "Access denied"); } @Test public void shouldNotBeAbleToAddMemberToNotEmptyWorkspaceForAnyUserIfAllowAttributeMissed() throws Exception { final Workspace testWorkspace = createWorkspace(); when(memberDao.getWorkspaceMembers(testWorkspace.getId())).thenReturn(singletonList(new Member())); final NewMembership membership = newDTO(NewMembership.class).withRoles(singletonList("workspace/developer")) .withUserId(testUser.getId()); final String errorJson = doPost(SERVICE_PATH + "/" + testWorkspace.getId() + "/members", membership, FORBIDDEN); assertEquals(asError(errorJson).getMessage(), "Access denied"); } @Test public void shouldBeAbleToAddMemberToEmptyWorkspaceForAnyUser() throws Exception { final Workspace testWorkspace = createWorkspace(); final NewMembership membership = newDTO(NewMembership.class).withUserId(testUser.getId()); final MemberDescriptor descriptor = doPost(SERVICE_PATH + "/" + testWorkspace.getId() + "/members", membership, CREATED); assertEquals(descriptor.getUserId(), membership.getUserId()); assertEquals(descriptor.getWorkspaceReference().getId(), testWorkspace.getId()); assertEquals(new HashSet<>(descriptor.getRoles()), new HashSet<>(asList("workspace/admin", "workspace/developer"))); } @Test public void shouldNotBeAbleToAddNewWorkspaceMemberWithoutOfRolesToNotEmptyWorkspace() throws Exception { final Workspace testWorkspace = createWorkspace(); when(memberDao.getWorkspaceMembers(testWorkspace.getId())).thenReturn(singletonList(new Member())); final NewMembership membership = newDTO(NewMembership.class).withUserId(testUser.getId()); prepareRole("workspace/admin"); final String errorJson = doPost(SERVICE_PATH + "/" + testWorkspace.getId() + "/members", membership, CONFLICT); assertEquals(asError(errorJson).getMessage(), "Roles should not be empty"); } @Test public void shouldBeAbleToRemoveWorkspaceMember() throws Exception { final Workspace testWorkspace = createWorkspace(); doDelete(SERVICE_PATH + "/" + testWorkspace.getId() + "/members/" + testUser.getId(), NO_CONTENT); verify(memberDao).remove(any(Member.class)); } @Test public void shouldBeAbleToRemoveWorkspace() throws Exception { final Workspace testWorkspace = createWorkspace(); doDelete(SERVICE_PATH + "/" + testWorkspace.getId(), NO_CONTENT); verify(workspaceDao).remove(testWorkspace.getId()); } @Test public void testWorkspaceDescriptorLinksForUser() throws NotFoundException, ServerException { final Workspace testWorkspace = createWorkspace(); when(securityContext.isUserInRole("user")).thenReturn(true); final Set<String> expectedRels = new HashSet<>(asList(Constants.LINK_REL_GET_CURRENT_USER_WORKSPACES, Constants.LINK_REL_GET_CURRENT_USER_MEMBERSHIP, LINK_REL_GET_PROJECTS)); assertEquals(asRels(service.toDescriptor(testWorkspace, securityContext).getLinks()), expectedRels); } @Test public void testWorkspaceDescriptorLinksForWorkspaceDeveloper() throws NotFoundException, ServerException { final Workspace testWorkspace = createWorkspace(); prepareRole("workspace/developer"); final Set<String> expectedRels = new HashSet<>(asList(Constants.LINK_REL_GET_WORKSPACE_BY_NAME, Constants.LINK_REL_GET_WORKSPACE_BY_ID, Constants.LINK_REL_GET_WORKSPACE_MEMBERS, Constants.LINK_REL_GET_CURRENT_USER_WORKSPACES, Constants.LINK_REL_GET_CURRENT_USER_MEMBERSHIP, LINK_REL_GET_PROJECTS)); assertEquals(asRels(service.toDescriptor(testWorkspace, securityContext).getLinks()), expectedRels); } @Test public void testWorkspaceDescriptorLinksForWorkspaceAdmin() throws NotFoundException, ServerException { final Workspace testWorkspace = createWorkspace(); prepareRole("workspace/admin"); final Set<String> expectedRels = new HashSet<>(asList(Constants.LINK_REL_GET_WORKSPACE_BY_NAME, Constants.LINK_REL_GET_WORKSPACE_BY_ID, Constants.LINK_REL_GET_WORKSPACE_MEMBERS, Constants.LINK_REL_REMOVE_WORKSPACE, Constants.LINK_REL_GET_CURRENT_USER_WORKSPACES, Constants.LINK_REL_GET_CURRENT_USER_MEMBERSHIP, LINK_REL_GET_PROJECTS)); assertEquals(asRels(service.toDescriptor(testWorkspace, securityContext).getLinks()), expectedRels); } @Test public void testWorkspaceDescriptorLinksForSystemManager() throws NotFoundException, ServerException { final Workspace testWorkspace = createWorkspace(); prepareRole("system/manager"); final Set<String> expectedRels = new HashSet<>(asList(Constants.LINK_REL_GET_WORKSPACE_BY_NAME, Constants.LINK_REL_GET_WORKSPACE_BY_ID, Constants.LINK_REL_GET_WORKSPACE_MEMBERS)); assertEquals(asRels(service.toDescriptor(testWorkspace, securityContext).getLinks()), expectedRels); } @Test public void testWorkspaceDescriptorLinksForSystemAdmin() throws NotFoundException, ServerException { final Workspace testWorkspace = createWorkspace(); prepareRole("system/admin"); final Set<String> expectedRels = new HashSet<>(asList(Constants.LINK_REL_GET_WORKSPACE_BY_NAME, Constants.LINK_REL_GET_WORKSPACE_BY_ID, Constants.LINK_REL_GET_WORKSPACE_MEMBERS, Constants.LINK_REL_REMOVE_WORKSPACE)); assertEquals(asRels(service.toDescriptor(testWorkspace, securityContext).getLinks()), expectedRels); } @Test public void testMemberDescriptorLinksForWorkspaceDeveloper() throws NotFoundException, ServerException { final Workspace testWorkspace = createWorkspace(); final Member testMember = new Member().withUserId(testUser.getId()) .withWorkspaceId(testWorkspace.getId()); prepareRole("workspace/developer"); final Set<String> expectedRels = new HashSet<>(asList(Constants.LINK_REL_GET_WORKSPACE_MEMBERS, LINK_REL_GET_USER_BY_ID)); assertEquals(asRels(service.toDescriptor(testMember, testWorkspace, securityContext).getLinks()), expectedRels); } @Test public void testMemberDescriptorLinksForWorkspaceAdmin() throws NotFoundException, ServerException { final Workspace testWorkspace = createWorkspace(); final Member testMember = new Member().withUserId(testUser.getId()) .withWorkspaceId(testWorkspace.getId()); prepareRole("workspace/admin"); final Set<String> expectedRels = new HashSet<>(asList(Constants.LINK_REL_GET_WORKSPACE_MEMBERS, LINK_REL_GET_USER_BY_ID, Constants.LINK_REL_REMOVE_WORKSPACE_MEMBER)); assertEquals(asRels(service.toDescriptor(testMember, testWorkspace, securityContext).getLinks()), expectedRels); } @SuppressWarnings("unchecked") private <T> T doDelete(String path, Status expectedResponseStatus) throws Exception { final ContainerResponse response = launcher.service("DELETE", path, BASE_URI, null, null, null, environmentContext); assertEquals(response.getStatus(), expectedResponseStatus.getStatusCode()); return (T)response.getEntity(); } @SuppressWarnings("unchecked") private <T> T doGet(String path) throws Exception { final ContainerResponse response = launcher.service("GET", path, BASE_URI, null, null, null, environmentContext); assertEquals(response.getStatus(), OK.getStatusCode()); return (T)response.getEntity(); } @SuppressWarnings("unchecked") private <T> T doPost(String path, Object entity, Status expectedResponseStatus) throws Exception { final byte[] data = JsonHelper.toJson(entity).getBytes(); final Map<String, List<String>> headers = new HashMap<>(4); headers.put("Content-Type", singletonList("application/json")); final ContainerResponse response = launcher.service("POST", path, BASE_URI, headers, data, null, environmentContext); assertEquals(response.getStatus(), expectedResponseStatus.getStatusCode()); return (T)response.getEntity(); } private ServiceError asError(String json) { return DtoFactory.getInstance().createDtoFromJson(json, ServiceError.class); } private <T> T newDTO(Class<T> dto) { return DtoFactory.getInstance().createDto(dto); } private Set<String> asRels(List<Link> links) { final Set<String> rels = new HashSet<>(); for (Link link : links) { rels.add(link.getRel()); } return rels; } private Account createAccount() throws NotFoundException, ServerException { final Account account = new Account().withId("fake_account_id"); when(accountDao.getById(account.getId())).thenReturn(account); when(accountDao.getByOwner(testUser.getId())).thenReturn(singletonList(account)); return account; } private Workspace createWorkspace() throws NotFoundException, ServerException { final String workspaceId = "test_workspace_id"; final String workspaceName = "test_workspace_name"; final String accountId = "test_account_id"; final Map<String, String> attributes = new HashMap<>(); attributes.put("default_attribute", "default_value"); final Workspace testWorkspace = new Workspace().withId(workspaceId) .withName(workspaceName) .withTemporary(false) .withAccountId(accountId) .withAttributes(attributes); when(workspaceDao.getById(workspaceId)).thenReturn(testWorkspace); when(workspaceDao.getByName(workspaceName)).thenReturn(testWorkspace); when(workspaceDao.getByAccount(accountId)).thenReturn(singletonList(testWorkspace)); return testWorkspace; } private Workspace createExtraWorkspace() throws NotFoundException, ServerException { final String workspaceId = "extra_test_workspace_id"; final String workspaceName = "extra_test_workspace_name"; final String accountId = "test_account_id"; final Map<String, String> attributes = new HashMap<>(); attributes.put("codenvy:role", "extra"); final Workspace extraWorkspace = new Workspace().withId(workspaceId) .withName(workspaceName) .withTemporary(false) .withAccountId(accountId) .withAttributes(attributes); when(workspaceDao.getById(workspaceId)).thenReturn(extraWorkspace); when(workspaceDao.getByName(workspaceName)).thenReturn(extraWorkspace); return extraWorkspace; } private void prepareRole(String role) { when(securityContext.isUserInRole(anyString())).thenReturn(false); if (!role.equals("system/admin") && !role.equals("system/manager")) { when(securityContext.isUserInRole("user")).thenReturn(true); } when(securityContext.isUserInRole(role)).thenReturn(true); } }