From 28a7ea0cf76a1466dd8e42cf1d65a8585fca59d1 Mon Sep 17 00:00:00 2001 From: Lucas Koehler Date: Fri, 28 Feb 2020 12:01:54 +0100 Subject: [PATCH] Bug 560633 - Transitive Project Admin role does not allow creating projects Add the project admin role to a user which creates a new user but only has the project admin role via group membership. Change-Id: I2a89a85d734c6fa35245a2237360362ad52140c0 Signed-off-by: Lucas Koehler --- .../server/core/AdminEmfStoreImpl.java | 10 +++ .../test/AddInitialParticipantTest.java | 69 ++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/core/AdminEmfStoreImpl.java b/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/core/AdminEmfStoreImpl.java index 6e9f8c68e..cbc01746d 100644 --- a/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/core/AdminEmfStoreImpl.java +++ b/bundles/org.eclipse.emf.emfstore.server/src/org/eclipse/emf/emfstore/internal/server/core/AdminEmfStoreImpl.java @@ -443,6 +443,16 @@ public void addInitialParticipant(SessionId sessionId, ProjectId projectId, ACOr return; } } + + // If we get until here, the user has the priviliges to create the project and be the initial participant. + // Because the corresponding role was not found in the user's roles, it must be part of one of the user's + // groups. To avoid the whole group becoming participants of the project, create the role for the user and add + // the project id. + final Role newRole = createRoleFromEClass(roleClass); + + newRole.getProjects().add(ModelUtil.clone(projectId)); + orgUnit.getRoles().add(newRole); + save(); } private static void checkIfSessionIsAssociatedWithProject(SessionId sessionId, ProjectId projectId) diff --git a/tests/org.eclipse.emf.emfstore.server.test/src/org/eclipse/emf/emfstore/server/accesscontrol/test/AddInitialParticipantTest.java b/tests/org.eclipse.emf.emfstore.server.test/src/org/eclipse/emf/emfstore/server/accesscontrol/test/AddInitialParticipantTest.java index 43ca3e297..3da4b9714 100644 --- a/tests/org.eclipse.emf.emfstore.server.test/src/org/eclipse/emf/emfstore/server/accesscontrol/test/AddInitialParticipantTest.java +++ b/tests/org.eclipse.emf.emfstore.server.test/src/org/eclipse/emf/emfstore/server/accesscontrol/test/AddInitialParticipantTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011-2015 EclipseSource Muenchen GmbH and others. + * Copyright (c) 2011-2020 EclipseSource Muenchen GmbH and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -13,6 +13,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.junit.Assert.fail; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.emf.emfstore.client.ESRemoteProject; @@ -21,7 +22,9 @@ import org.eclipse.emf.emfstore.internal.client.model.Usersession; import org.eclipse.emf.emfstore.internal.client.model.impl.api.ESUsersessionImpl; import org.eclipse.emf.emfstore.internal.server.core.Messages; +import org.eclipse.emf.emfstore.internal.server.exceptions.AccessControlException; import org.eclipse.emf.emfstore.internal.server.model.ProjectId; +import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACOrgUnit; import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACOrgUnitId; import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.roles.ProjectAdminRole; import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.roles.Role; @@ -219,4 +222,68 @@ public void shouldSucceedIfAllPrerequisitesAreMet() throws ESException { final Role role = getSuperAdminBroker().getRole(projectId, userId); assertThat(role, instanceOf(ProjectAdminRole.class)); } + + /** + * Tests that the project admin role is added to the initial participant if they + * only have the project admin role via a group. Additionally, the project's id is added to the role created in the + * user's {@link ACOrgUnit}. This is necessary because the project id mustn't be added to the group's role. + * + * @throws ESException + */ + @Test + public void shouldSucceedIfAllPrerequisitesAreMetViaGroup() throws ESException { + final Usersession session = ESUsersessionImpl.class.cast(getUsersession()).toInternalAPI(); + final ACOrgUnitId userId = session.getACUser().getId(); + + // Create group, add project admin role, and add user to the group + final ACOrgUnitId group = getSuperAdminBroker().createGroup("TestGroup"); //$NON-NLS-1$ + getSuperAdminBroker().assignRole(group, Roles.projectAdmin()); + getSuperAdminBroker().addMember(group, userId); + + final ESRemoteProject sharedProject = getLocalProject().shareProject( + getUsersession(), new NullProgressMonitor()); + final ProjectId projectId = ESGlobalProjectIdImpl.class.cast( + sharedProject.getGlobalProjectId()) + .toInternalAPI(); + + final Role role = getSuperAdminBroker().getRole(projectId, userId); + assertThat(role, instanceOf(ProjectAdminRole.class)); + } + + /** + * Scenario: A user is member of a group which has the project admin role. They create a project and, with this, + * obtain the project admin role. Afterwards, they leave the group and delete the project. Now, they mustn't be able + * to share any more projects. + * + * @throws ESException + */ + @Test + public void shouldThrowACExceptionAfterTransitiveProjectAdminWasRemoved() throws ESException { + final Usersession session = ESUsersessionImpl.class.cast(getUsersession()).toInternalAPI(); + final ACOrgUnitId userId = session.getACUser().getId(); + + // Create group, add project admin role, and add user to the group + final ACOrgUnitId group = getSuperAdminBroker().createGroup("TestGroup2"); //$NON-NLS-1$ + getSuperAdminBroker().assignRole(group, Roles.projectAdmin()); + getSuperAdminBroker().addMember(group, userId); + + final ESRemoteProject sharedProject = getLocalProject().shareProject( + getUsersession(), + new NullProgressMonitor()); + ESGlobalProjectIdImpl.class.cast( + sharedProject.getGlobalProjectId()) + .toInternalAPI(); + + getSuperAdminBroker().removeMember(group, userId); + sharedProject.delete(getUsersession(), new NullProgressMonitor()); + + // Try-catch instead of JUnit's expect because we need to make sure the exceptions is thrown here and not above. + try { + getLocalProject().shareProject(getUsersession(), new NullProgressMonitor()); + } catch (final AccessControlException ex) { + return; + } + + fail("Expected AccessControlException for second project sharing."); //$NON-NLS-1$ + } }