]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6490 WS permissions/add_group add project permissions to a group
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 10 Aug 2015 11:50:51 +0000 (13:50 +0200)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 10 Aug 2015 13:49:25 +0000 (15:49 +0200)
server/sonar-server/src/main/java/org/sonar/server/component/ComponentFinder.java
server/sonar-server/src/main/java/org/sonar/server/permission/PermissionChange.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupAction.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionWsCommons.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java
server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupAction.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupActionTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java
server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupActionTest.java

index 5acd0f73da3f92c932ce94639b5879b7eb946833..aadbf41dfa7ebc4e6882335e61bdc24816af7cd9 100644 (file)
@@ -22,9 +22,11 @@ package org.sonar.server.component;
 
 import com.google.common.base.Optional;
 import javax.annotation.Nullable;
+import org.sonar.api.resources.Qualifiers;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.NotFoundException;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -54,10 +56,23 @@ public class ComponentFinder {
     return getIfPresentOrFail(dbClient.componentDao().selectByUuid(dbSession, uuid), String.format("Component id '%s' not found", uuid));
   }
 
+  public ComponentDto getProjectByUuidOrKey(DbSession dbSession, @Nullable String projectUuid, @Nullable String projectKey) {
+    ComponentDto project = getByUuidOrKey(dbSession, projectUuid, projectKey);
+    checkIsProjectOrModule(project);
+
+    return project;
+  }
+
   private static ComponentDto getIfPresentOrFail(Optional<ComponentDto> component, String errorMsg) {
     if (!component.isPresent()) {
       throw new NotFoundException(errorMsg);
     }
     return component.get();
   }
+
+  private static void checkIsProjectOrModule(ComponentDto component) {
+    if (!Qualifiers.PROJECT.equals(component.qualifier()) && !Qualifiers.MODULE.equals(component.qualifier())) {
+      throw new BadRequestException(String.format("Component '%s' (id: %s) must be a project or a module.", component.key(), component.uuid()));
+    }
+  }
 }
index ebec68b6f19a2a7d687734e844e8509f81a0f38f..29e4db4e06c65461874cbaaa05887600ce4572c4 100644 (file)
 package org.sonar.server.permission;
 
 import com.google.common.base.Strings;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.builder.ReflectionToStringBuilder;
 import org.sonar.core.permission.ComponentPermissions;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.server.exceptions.BadRequestException;
 
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.util.Map;
-
 public class PermissionChange {
 
   static final String USER_KEY = "user";
index cf847398204f9ad3036bb200fd03bd060d21b0e1..242ae06b86370fa17475eae364d45a443ef4f494 100644 (file)
 
 package org.sonar.server.permission.ws;
 
+import javax.annotation.Nullable;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.permission.PermissionChange;
 import org.sonar.server.permission.PermissionUpdater;
 
-import static org.sonar.server.permission.ws.PermissionWsCommons.searchName;
-
 public class AddGroupAction implements PermissionsWsAction {
 
   public static final String ACTION = "add_group";
   public static final String PARAM_PERMISSION = "permission";
   public static final String PARAM_GROUP_NAME = "groupName";
   public static final String PARAM_GROUP_ID = "groupId";
+  public static final String PARAM_PROJECT_ID = "projectId";
+  public static final String PARAM_PROJECT_KEY = "projectKey";
 
-  private final PermissionUpdater permissionUpdater;
   private final DbClient dbClient;
+  private final PermissionWsCommons permissionWsCommons;
+  private final PermissionUpdater permissionUpdater;
+  private final ComponentFinder componentFinder;
 
-  public AddGroupAction(PermissionUpdater permissionUpdater, DbClient dbClient) {
+  public AddGroupAction(DbClient dbClient, PermissionWsCommons permissionWsCommons, PermissionUpdater permissionUpdater, ComponentFinder componentFinder) {
+    this.permissionWsCommons = permissionWsCommons;
     this.permissionUpdater = permissionUpdater;
     this.dbClient = dbClient;
+    this.componentFinder = componentFinder;
   }
 
   @Override
   public void define(WebService.NewController context) {
     WebService.NewAction action = context.createAction(ACTION)
       .setDescription("Add permission to a group.<br /> " +
+        "If the project id is provided, a project permission is created.<br />" +
         "The group name or group id must be provided. <br />" +
         "Requires 'Administer System' permission.")
       .setSince("5.2")
@@ -65,8 +74,16 @@ public class AddGroupAction implements PermissionsWsAction {
       .setExampleValue("sonar-administrators");
 
     action.createParam(PARAM_GROUP_ID)
-      .setDescription("Group ID")
+      .setDescription("Group id")
       .setExampleValue("42");
+
+    action.createParam(PARAM_PROJECT_ID)
+      .setDescription("Project id")
+      .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d");
+
+    action.createParam(PARAM_PROJECT_KEY)
+      .setDescription("Project key")
+      .setExampleValue("org.apache.hbas:hbase");
   }
 
   @Override
@@ -74,15 +91,34 @@ public class AddGroupAction implements PermissionsWsAction {
     String permission = request.mandatoryParam(PARAM_PERMISSION);
     String groupNameParam = request.param(PARAM_GROUP_NAME);
     Long groupId = request.paramAsLong(PARAM_GROUP_ID);
+    String projectUuid = request.param(PARAM_PROJECT_ID);
+    String projectKey = request.param(PARAM_PROJECT_KEY);
 
-    String groupName = searchName(dbClient, groupNameParam, groupId);
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      String groupName = permissionWsCommons.searchGroupName(dbSession, groupNameParam, groupId);
+      PermissionChange permissionChange = permissionChange(dbSession, permission, groupName, projectUuid, projectKey);
 
-    permissionUpdater.addPermission(
-      new PermissionChange()
-        .setPermission(permission)
-        .setGroup(groupName)
-      );
+      permissionUpdater.addPermission(permissionChange);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
 
     response.noContent();
   }
+
+  private PermissionChange permissionChange(DbSession dbSession, String permission, String groupName, @Nullable String projectUuid, @Nullable String projectKey) {
+    PermissionChange permissionChange = new PermissionChange()
+      .setPermission(permission)
+      .setGroup(groupName);
+    if (isProjectUuidOrProjectKeyProvided(projectUuid, projectKey)) {
+      ComponentDto project = componentFinder.getProjectByUuidOrKey(dbSession, projectUuid, projectKey);
+      permissionChange.setComponentKey(project.key());
+    }
+    return permissionChange;
+  }
+
+  private static boolean isProjectUuidOrProjectKeyProvided(@Nullable String projectUuid, @Nullable String projectKey) {
+    return projectUuid != null || projectKey != null;
+  }
 }
index 5eea1e0293a4bfef571cc09494ce4b06449020ba..6660989bf99325a3d241f33cb441bb385b8fc1c0 100644 (file)
@@ -29,27 +29,24 @@ import org.sonar.server.exceptions.NotFoundException;
 
 public class PermissionWsCommons {
 
-  private PermissionWsCommons() {
-    // static stuff only
+  private final DbClient dbClient;
+
+  public PermissionWsCommons(DbClient dbClient) {
+    this.dbClient = dbClient;
   }
 
-  public static String searchName(DbClient dbClient, @Nullable String groupNameParam, @Nullable Long groupId) {
+  public String searchGroupName(DbSession dbSession, @Nullable String groupNameParam, @Nullable Long groupId) {
     checkParameters(groupNameParam, groupId);
     if (groupNameParam != null) {
       return groupNameParam;
     }
 
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      GroupDto group = dbClient.groupDao().selectById(dbSession, groupId);
-      if (group == null) {
-        throw new NotFoundException(String.format("Group with id '%d' is not found", groupId));
-      }
-
-      return group.getName();
-    } finally {
-      dbClient.closeSession(dbSession);
+    GroupDto group = dbClient.groupDao().selectById(dbSession, groupId);
+    if (group == null) {
+      throw new NotFoundException(String.format("Group with id '%d' is not found", groupId));
     }
+
+    return group.getName();
   }
 
   private static void checkParameters(@Nullable String groupName, @Nullable Long groupId) {
index 25f11a7c38619c9278f311a4fcfb5a1ad19c03f1..afc43beb42ce489668a6aa2d9c6b83f7826ac668 100644 (file)
@@ -33,6 +33,7 @@ public class PermissionsWsModule extends Module {
       RemoveUserAction.class,
       UsersAction.class,
       GroupsAction.class,
-      SearchGlobalPermissionsAction.class);
+      SearchGlobalPermissionsAction.class,
+      PermissionWsCommons.class);
   }
 }
index e5f0bf42e6ea18ba0e2c22956fd34da27e11257e..aab9f958648e8493e128fe2e1d2d50e894b77e6f 100644 (file)
@@ -25,11 +25,10 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
 import org.sonar.server.permission.PermissionChange;
 import org.sonar.server.permission.PermissionUpdater;
 
-import static org.sonar.server.permission.ws.PermissionWsCommons.searchName;
-
 public class RemoveGroupAction implements PermissionsWsAction {
 
   public static final String ACTION = "remove_group";
@@ -37,12 +36,14 @@ public class RemoveGroupAction implements PermissionsWsAction {
   public static final String PARAM_GROUP_NAME = "groupName";
   public static final String PARAM_GROUP_ID = "groupId";
 
-  private final PermissionUpdater permissionUpdater;
   private final DbClient dbClient;
+  private final PermissionWsCommons permissionWsCommons;
+  private final PermissionUpdater permissionUpdater;
 
-  public RemoveGroupAction(PermissionUpdater permissionUpdater, DbClient dbClient) {
-    this.permissionUpdater = permissionUpdater;
+  public RemoveGroupAction(DbClient dbClient, PermissionWsCommons permissionWsCommons, PermissionUpdater permissionUpdater) {
     this.dbClient = dbClient;
+    this.permissionWsCommons = permissionWsCommons;
+    this.permissionUpdater = permissionUpdater;
   }
 
   @Override
@@ -75,13 +76,18 @@ public class RemoveGroupAction implements PermissionsWsAction {
     String groupNameParam = request.param(PARAM_GROUP_NAME);
     Long groupId = request.paramAsLong(PARAM_GROUP_ID);
 
-    String groupName = searchName(dbClient, groupNameParam, groupId);
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      String groupName = permissionWsCommons.searchGroupName(dbSession, groupNameParam, groupId);
 
-    permissionUpdater.removePermission(
-      new PermissionChange()
-        .setPermission(permission)
-        .setGroup(groupName)
-    );
+      permissionUpdater.removePermission(
+        new PermissionChange()
+          .setPermission(permission)
+          .setGroup(groupName)
+        );
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
 
     response.noContent();
   }
index 26745d5185b95cfef6e0952b8e2ac22587beee89..fc7fb740369bdbfcf9a6c91f0ac2b19e39ba94df 100644 (file)
@@ -27,9 +27,14 @@ import org.junit.experimental.categories.Category;
 import org.junit.rules.ExpectedException;
 import org.mockito.ArgumentCaptor;
 import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
 import org.sonar.db.user.GroupDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.component.ComponentTesting;
 import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.exceptions.ServerException;
 import org.sonar.server.permission.PermissionChange;
 import org.sonar.server.permission.PermissionUpdater;
@@ -42,6 +47,12 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
 import static org.sonar.server.permission.ws.AddGroupAction.ACTION;
+import static org.sonar.server.permission.ws.AddGroupAction.PARAM_GROUP_ID;
+import static org.sonar.server.permission.ws.AddGroupAction.PARAM_GROUP_NAME;
+import static org.sonar.server.permission.ws.AddGroupAction.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.AddGroupAction.PARAM_PROJECT_ID;
+import static org.sonar.server.permission.ws.AddGroupAction.PARAM_PROJECT_KEY;
+import static org.sonar.server.permission.ws.PermissionsWs.ENDPOINT;
 
 @Category(DbTests.class)
 public class AddGroupActionTest {
@@ -52,24 +63,26 @@ public class AddGroupActionTest {
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
   private PermissionUpdater permissionUpdater;
+  private DbClient dbClient;
+  private ArgumentCaptor<PermissionChange> permissionChangeCaptor;
 
   @Before
   public void setUp() {
     permissionUpdater = mock(PermissionUpdater.class);
+    permissionChangeCaptor = ArgumentCaptor.forClass(PermissionChange.class);
+    dbClient = db.getDbClient();
     ws = new WsTester(new PermissionsWs(
-      new AddGroupAction(permissionUpdater, db.getDbClient())));
+      new AddGroupAction(dbClient, new PermissionWsCommons(dbClient), permissionUpdater, new ComponentFinder(dbClient))));
     userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN);
-
   }
 
   @Test
   public void call_permission_service_with_right_data() throws Exception {
-    ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION)
-      .setParam(AddGroupAction.PARAM_GROUP_NAME, "sonar-administrators")
-      .setParam(AddGroupAction.PARAM_PERMISSION, SYSTEM_ADMIN)
+    newRequest()
+      .setParam(PARAM_GROUP_NAME, "sonar-administrators")
+      .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
       .execute();
 
-    ArgumentCaptor<PermissionChange> permissionChangeCaptor = ArgumentCaptor.forClass(PermissionChange.class);
     verify(permissionUpdater).addPermission(permissionChangeCaptor.capture());
     PermissionChange permissionChange = permissionChangeCaptor.getValue();
     assertThat(permissionChange.group()).isEqualTo("sonar-administrators");
@@ -77,29 +90,95 @@ public class AddGroupActionTest {
   }
 
   @Test
-  public void search_with_group_id() throws Exception {
-    GroupDto group = db.getDbClient().groupDao().insert(db.getSession(), new GroupDto()
-      .setName("sonar-administrators"));
-    db.getSession().commit();
+  public void add_with_group_id() throws Exception {
+    GroupDto group = insertGroup("sonar-administrators");
+    commit();
+
+    newRequest()
+      .setParam(PARAM_GROUP_ID, group.getId().toString())
+      .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
+      .execute();
+
+    verify(permissionUpdater).addPermission(permissionChangeCaptor.capture());
+    PermissionChange permissionChange = permissionChangeCaptor.getValue();
+    assertThat(permissionChange.group()).isEqualTo("sonar-administrators");
+  }
+
+  @Test
+  public void add_with_project_uuid() throws Exception {
+    insertGroup("sonar-administrators");
+    insertComponent(ComponentTesting.newProjectDto("project-uuid").setKey("project-key"));
+    commit();
+
+    newRequest()
+      .setParam(PARAM_GROUP_NAME, "sonar-administrators")
+      .setParam(PARAM_PROJECT_ID, "project-uuid")
+      .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
+      .execute();
+
+    verify(permissionUpdater).addPermission(permissionChangeCaptor.capture());
+    PermissionChange permissionChange = permissionChangeCaptor.getValue();
+    assertThat(permissionChange.component()).isEqualTo("project-key");
+    assertThat(permissionChange.group()).isEqualTo("sonar-administrators");
+  }
 
-    ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION)
-      .setParam(AddGroupAction.PARAM_GROUP_ID, group.getId().toString())
-      .setParam(AddGroupAction.PARAM_PERMISSION, SYSTEM_ADMIN)
+  @Test
+  public void add_with_project_key() throws Exception {
+    insertGroup("sonar-administrators");
+    insertComponent(ComponentTesting.newProjectDto("project-uuid").setKey("project-key"));
+    commit();
+
+    newRequest()
+      .setParam(PARAM_GROUP_NAME, "sonar-administrators")
+      .setParam(PARAM_PROJECT_KEY, "project-key")
+      .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
       .execute();
 
-    ArgumentCaptor<PermissionChange> permissionChangeCaptor = ArgumentCaptor.forClass(PermissionChange.class);
     verify(permissionUpdater).addPermission(permissionChangeCaptor.capture());
     PermissionChange permissionChange = permissionChangeCaptor.getValue();
+    assertThat(permissionChange.component()).isEqualTo("project-key");
     assertThat(permissionChange.group()).isEqualTo("sonar-administrators");
   }
 
+  @Test
+  public void fail_if_project_uuid_not_found() throws Exception {
+    expectedException.expect(NotFoundException.class);
+
+    insertGroup("sonar-administrators");
+    insertComponent(ComponentTesting.newProjectDto("project-uuid").setKey("project-key"));
+    commit();
+
+    newRequest()
+      .setParam(PARAM_GROUP_NAME, "sonar-administrators")
+      .setParam(PARAM_PROJECT_ID, "unknown-project-uuid")
+      .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
+      .execute();
+  }
+
+  @Test
+  public void fail_if_component_uuid_is_not_a_project() throws Exception {
+    expectedException.expect(BadRequestException.class);
+
+    insertGroup("sonar-administrators");
+    ComponentDto project = ComponentTesting.newProjectDto("project-uuid").setKey("project-key");
+    insertComponent(project);
+    insertComponent(ComponentTesting.newFileDto(project, "file-uuid"));
+    commit();
+
+    newRequest()
+      .setParam(PARAM_GROUP_NAME, "sonar-administrators")
+      .setParam(PARAM_PROJECT_ID, "file-uuid")
+      .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
+      .execute();
+  }
+
   @Test
   public void fail_when_get_request() throws Exception {
     expectedException.expect(ServerException.class);
 
-    ws.newGetRequest(PermissionsWs.ENDPOINT, ACTION)
-      .setParam(AddGroupAction.PARAM_GROUP_NAME, "sonar-administrators")
-      .setParam(AddGroupAction.PARAM_PERMISSION, SYSTEM_ADMIN)
+    ws.newGetRequest(ENDPOINT, ACTION)
+      .setParam(PARAM_GROUP_NAME, "sonar-administrators")
+      .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
       .execute();
   }
 
@@ -108,8 +187,8 @@ public class AddGroupActionTest {
     expectedException.expect(BadRequestException.class);
     expectedException.expectMessage("Group name or group id must be provided, not both");
 
-    ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION)
-      .setParam(AddGroupAction.PARAM_PERMISSION, SYSTEM_ADMIN)
+    newRequest()
+      .setParam(PARAM_PERMISSION, SYSTEM_ADMIN)
       .execute();
   }
 
@@ -117,8 +196,24 @@ public class AddGroupActionTest {
   public void fail_when_permission_is_missing() throws Exception {
     expectedException.expect(IllegalArgumentException.class);
 
-    ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION)
-      .setParam(AddGroupAction.PARAM_GROUP_NAME, "sonar-administrators")
+    newRequest()
+      .setParam(PARAM_GROUP_NAME, "sonar-administrators")
       .execute();
   }
+
+  private WsTester.TestRequest newRequest() {
+    return ws.newPostRequest(ENDPOINT, ACTION);
+  }
+
+  private void commit() {
+    db.getSession().commit();
+  }
+
+  private void insertComponent(ComponentDto component) {
+    dbClient.componentDao().insert(db.getSession(), component);
+  }
+
+  private GroupDto insertGroup(String name) {
+    return dbClient.groupDao().insert(db.getSession(), new GroupDto().setName(name));
+  }
 }
index 8a922b8ad3ce59470f5619a75cf07819ea2ab816..bb8acb48d47f5e73711aef3c42eb2e30f3511527 100644 (file)
@@ -30,6 +30,6 @@ public class PermissionsWsModuleTest {
   public void verify_count_of_added_components() {
     ComponentContainer container = new ComponentContainer();
     new PermissionsWsModule().configure(container);
-    assertThat(container.size()).isEqualTo(10);
+    assertThat(container.size()).isEqualTo(11);
   }
 }
index 52d0b7847ceb6467a02d04d41928f3e6de386834..cf2aba1ff8088f6d2cdd60c2f19f1f643844a88f 100644 (file)
@@ -55,7 +55,7 @@ public class RemoveGroupActionTest {
   public void setUp() {
     permissionUpdater = mock(PermissionUpdater.class);
     ws = new WsTester(new PermissionsWs(
-      new RemoveGroupAction(permissionUpdater, db.getDbClient())));
+      new RemoveGroupAction(db.getDbClient(), new PermissionWsCommons(db.getDbClient()), permissionUpdater)));
     userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN);
   }