]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11812 Prevent setting a directory as favorite
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 12 Mar 2019 17:51:57 +0000 (18:51 +0100)
committerSonarTech <sonartech@sonarsource.com>
Mon, 18 Mar 2019 19:20:59 +0000 (20:20 +0100)
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v77/DbVersion77.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v77/DeleteFavouritesOnNotSupportedComponentQualifiers.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v77/DbVersion77Test.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v77/DeleteFavouritesOnNotSupportedComponentQualifiersTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v77/DeleteFavouritesOnNotSupportedComponentQualifiersTest/schema.sql [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/favorite/ws/AddAction.java
server/sonar-server/src/test/java/org/sonar/server/favorite/ws/AddActionTest.java

index d7a09e032adf67b9cd9e035af675ef8c4933b778..39de1e9f499bbd2edf8c7b6826ea13f2a3f6fd01 100644 (file)
@@ -34,6 +34,7 @@ public class DbVersion77 implements DbVersion {
       .add(2604, "Add baseline columns in PROJECT_BRANCHES", AddManualBaselineToProjectBranches.class)
       .add(2605, "Add SNAPSHOTS.PROJECT_VERSION", AddProjectVersionToSnapshot.class)
       .add(2606, "Drop DATA_TYPE column from FILE_SOURCES table", DropDataTypeFromFileSources.class)
-      .add(2607, "Add MEMBERS_SYNC_ENABLED column to ORGANIZATIONS_ALM_BINDING table", AddMembersSyncFlagToOrgAlmBinding.class);
+      .add(2607, "Add MEMBERS_SYNC_ENABLED column to ORGANIZATIONS_ALM_BINDING table", AddMembersSyncFlagToOrgAlmBinding.class)
+      .add(2608, "Delete favorites on not supported components", DeleteFavouritesOnNotSupportedComponentQualifiers.class);
   }
 }
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v77/DeleteFavouritesOnNotSupportedComponentQualifiers.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v77/DeleteFavouritesOnNotSupportedComponentQualifiers.java
new file mode 100644 (file)
index 0000000..12a314b
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v77;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.SupportsBlueGreen;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.MassUpdate;
+
+@SupportsBlueGreen
+public class DeleteFavouritesOnNotSupportedComponentQualifiers extends DataChange {
+
+  public DeleteFavouritesOnNotSupportedComponentQualifiers(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    MassUpdate massUpdate = context.prepareMassUpdate().rowPluralName("favourites");
+    massUpdate.select("SELECT prop.id FROM properties prop " +
+      "INNER JOIN projects p ON p.id=prop.resource_id AND p.qualifier NOT IN ('TRK', 'FIL', 'VW', 'SVW', 'APP') " +
+      "WHERE prop_key=? AND user_id IS NOT NULL")
+      .setString(1, "favourite");
+    massUpdate.update("DELETE FROM properties WHERE id=?");
+    massUpdate.execute((row, update) -> {
+      int id = row.getInt(1);
+      update.setInt(1, id);
+      return true;
+    });
+  }
+
+}
index 57b6c22920900eda2a1730a13fa5816e9b08a5d9..23b3f6cfc17de9ff21abb471ed31b449c17b1619 100644 (file)
@@ -36,7 +36,7 @@ public class DbVersion77Test {
 
   @Test
   public void verify_migration_count() {
-    verifyMigrationCount(underTest, 8);
+    verifyMigrationCount(underTest, 9);
   }
 
 }
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v77/DeleteFavouritesOnNotSupportedComponentQualifiersTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v77/DeleteFavouritesOnNotSupportedComponentQualifiersTest.java
new file mode 100644 (file)
index 0000000..188cf91
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.platform.db.migration.version.v77;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.commons.lang.math.RandomUtils.nextInt;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DeleteFavouritesOnNotSupportedComponentQualifiersTest {
+
+  private static final String TABLE = "properties";
+  private static final String FAVOURITE_PROPERTY = "favourite";
+
+  @Rule
+  public CoreDbTester db = CoreDbTester.createForSchema(DeleteFavouritesOnNotSupportedComponentQualifiersTest.class, "schema.sql");
+
+  private DeleteFavouritesOnNotSupportedComponentQualifiers underTest = new DeleteFavouritesOnNotSupportedComponentQualifiers(db.database());
+
+  @Test
+  public void delete_favorites_on_none_supported_component_qualifiers() throws SQLException {
+    int moduleId = insertComponent("BRC");
+    insertProperty(FAVOURITE_PROPERTY, moduleId);
+    insertProperty(FAVOURITE_PROPERTY, moduleId);
+    insertProperty(FAVOURITE_PROPERTY, moduleId);
+    int libId = insertComponent("LIB");
+    insertProperty(FAVOURITE_PROPERTY, libId);
+
+    underTest.execute();
+
+    assertThat(db.countRowsOfTable(TABLE)).isZero();
+  }
+
+  @Test
+  public void ignore_favorites_on_supported_component_qualifiers() throws SQLException {
+    int projectId = insertComponent("TRK");
+    int prop1 = insertProperty(FAVOURITE_PROPERTY, projectId);
+    int fileId = insertComponent("FIL");
+    int prop2 = insertProperty(FAVOURITE_PROPERTY, fileId);
+    int portfolioId = insertComponent("VW");
+    int prop3 = insertProperty(FAVOURITE_PROPERTY, portfolioId);
+    int subPortfolioId = insertComponent("SVW");
+    int prop4 = insertProperty(FAVOURITE_PROPERTY, subPortfolioId);
+    int applicationId = insertComponent("APP");
+    int prop5 = insertProperty(FAVOURITE_PROPERTY, applicationId);
+
+    underTest.execute();
+
+    assertProperties(prop1, prop2, prop3, prop4, prop5);
+  }
+
+  @Test
+  public void ignore_other_properties() throws SQLException {
+    int moduleId = insertComponent("BRC");
+    int prop1 = insertProperty("other", moduleId);
+    int prop2 = insertProperty("other", moduleId);
+    int libId = insertComponent("LIB");
+    int prop3 = insertProperty("other", libId);
+
+    underTest.execute();
+
+    assertProperties(prop1, prop2, prop3);
+  }
+
+  private void assertProperties(Integer... expectedIds) {
+    assertThat(db.select("SELECT id FROM properties")
+      .stream()
+      .map(map -> ((Long) map.get("ID")).intValue())
+      .collect(toList()))
+        .containsExactlyInAnyOrder(expectedIds);
+  }
+
+  private int insertProperty(String key, int componentId) {
+    int id = nextInt();
+    db.executeInsert(
+      TABLE,
+      "ID", id,
+      "PROP_KEY", key,
+      "USER_ID", nextInt(),
+      "RESOURCE_ID", componentId,
+      "IS_EMPTY", true,
+      "CREATED_AT", 123456);
+    return id;
+  }
+
+  private int insertComponent(String qualifier) {
+    int id = nextInt();
+    String uuid = "uuid_" + id;
+    db.executeInsert(
+      "projects",
+      "ID", id,
+      "UUID", uuid,
+      "ORGANIZATION_UUID", "org_" + id,
+      "UUID_PATH", "path_" + id,
+      "ROOT_UUID", "root_" + id,
+      "PROJECT_UUID", "project_" + id,
+      "QUALIFIER", qualifier,
+      "ENABLED", true,
+      "PRIVATE", false);
+    return id;
+  }
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v77/DeleteFavouritesOnNotSupportedComponentQualifiersTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v77/DeleteFavouritesOnNotSupportedComponentQualifiersTest/schema.sql
new file mode 100644 (file)
index 0000000..65a4b55
--- /dev/null
@@ -0,0 +1,59 @@
+CREATE TABLE "PROPERTIES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "PROP_KEY" VARCHAR(512) NOT NULL,
+  "RESOURCE_ID" INTEGER,
+  "USER_ID" INTEGER,
+  "IS_EMPTY" BOOLEAN NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000),
+  "CLOB_VALUE" CLOB,
+  "CREATED_AT" BIGINT
+);
+CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY");
+
+CREATE TABLE "PROJECTS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "KEE" VARCHAR(400),
+  "UUID" VARCHAR(50) NOT NULL,
+  "UUID_PATH" VARCHAR(1500) NOT NULL,
+  "ROOT_UUID" VARCHAR(50) NOT NULL,
+  "PROJECT_UUID" VARCHAR(50) NOT NULL,
+  "MODULE_UUID" VARCHAR(50),
+  "MODULE_UUID_PATH" VARCHAR(1500),
+  "MAIN_BRANCH_PROJECT_UUID" VARCHAR(50),
+  "NAME" VARCHAR(2000),
+  "DESCRIPTION" VARCHAR(2000),
+  "PRIVATE" BOOLEAN NOT NULL,
+  "TAGS" VARCHAR(500),
+  "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
+  "SCOPE" VARCHAR(3),
+  "QUALIFIER" VARCHAR(10),
+  "DEPRECATED_KEE" VARCHAR(400),
+  "PATH" VARCHAR(2000),
+  "LANGUAGE" VARCHAR(20),
+  "COPY_COMPONENT_UUID" VARCHAR(50),
+  "LONG_NAME" VARCHAR(2000),
+  "DEVELOPER_UUID" VARCHAR(50),
+  "CREATED_AT" TIMESTAMP,
+  "AUTHORIZATION_UPDATED_AT" BIGINT,
+  "B_CHANGED" BOOLEAN,
+  "B_COPY_COMPONENT_UUID" VARCHAR(50),
+  "B_DESCRIPTION" VARCHAR(2000),
+  "B_ENABLED" BOOLEAN,
+  "B_UUID_PATH" VARCHAR(1500),
+  "B_LANGUAGE" VARCHAR(20),
+  "B_LONG_NAME" VARCHAR(500),
+  "B_MODULE_UUID" VARCHAR(50),
+  "B_MODULE_UUID_PATH" VARCHAR(1500),
+  "B_NAME" VARCHAR(500),
+  "B_PATH" VARCHAR(2000),
+  "B_QUALIFIER" VARCHAR(10)
+);
+
+CREATE INDEX "PROJECTS_ORGANIZATION" ON "PROJECTS" ("ORGANIZATION_UUID");
+CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE");
+CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID");
+CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID");
+CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID");
+CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID");
+CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER");
index d8edb28f307185d164d86d459e3207a322af7aa4..7523ae174db85f4c8cd3f8a39a54d6ec0578c31f 100644 (file)
  */
 package org.sonar.server.favorite.ws;
 
+import java.util.List;
 import java.util.function.Consumer;
 import org.sonar.api.server.ws.Change;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
-import org.sonar.api.web.UserRole;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -33,9 +33,18 @@ import org.sonar.server.favorite.FavoriteUpdater;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.ws.KeyExamples;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
+import static java.lang.String.join;
+import static java.util.Arrays.asList;
+import static org.sonar.api.web.UserRole.USER;
 import static org.sonar.server.favorite.ws.FavoritesWsParameters.PARAM_COMPONENT;
 
 public class AddAction implements FavoritesWsAction {
+
+  private static final List<String> SUPPORTED_QUALIFIERS = asList("TRK", "VW", "APP", "SVW", "FIL");
+  private static final String SUPPORTED_QUALIFIERS_AS_STRING = join(", ", SUPPORTED_QUALIFIERS);
+
   private final UserSession userSession;
   private final DbClient dbClient;
   private final FavoriteUpdater favoriteUpdater;
@@ -51,15 +60,17 @@ public class AddAction implements FavoritesWsAction {
   @Override
   public void define(WebService.NewController context) {
     WebService.NewAction action = context.createAction("add")
-      .setDescription("Add a component (project, directory, file etc.) as favorite for the authenticated user.<br>" +
+      .setDescription("Add a component (project, file etc.) as favorite for the authenticated user.<br>" +
         "Requires authentication and the following permission: 'Browse' on the project of the specified component.")
       .setSince("6.3")
-      .setChangelog(new Change("7.6", String.format("The use of module keys in parameter '%s' is deprecated", PARAM_COMPONENT)))
+      .setChangelog(
+        new Change("7.7", "It's no more possible to set a directory as favorite"),
+        new Change("7.6", format("The use of module keys in parameter '%s' is deprecated", PARAM_COMPONENT)))
       .setPost(true)
       .setHandler(this);
 
     action.createParam(PARAM_COMPONENT)
-      .setDescription("Component key")
+      .setDescription(format("Component key. Only components with qualifiers %s are supported", SUPPORTED_QUALIFIERS_AS_STRING))
       .setRequired(true)
       .setExampleValue(KeyExamples.KEY_FILE_EXAMPLE_001);
   }
@@ -74,9 +85,10 @@ public class AddAction implements FavoritesWsAction {
     return request -> {
       try (DbSession dbSession = dbClient.openSession(false)) {
         ComponentDto componentDto = componentFinder.getByKey(dbSession, request.mandatoryParam(PARAM_COMPONENT));
+        checkArgument(SUPPORTED_QUALIFIERS.contains(componentDto.qualifier()), "Only components with qualifiers %s are supported", SUPPORTED_QUALIFIERS_AS_STRING);
         userSession
           .checkLoggedIn()
-          .checkComponentPermission(UserRole.USER, componentDto);
+          .checkComponentPermission(USER, componentDto);
         favoriteUpdater.add(dbSession, componentDto, userSession.isLoggedIn() ? userSession.getUserId() : null);
         dbSession.commit();
       }
index 0b7e75a28005dc66effb603afe9ecfc8085d86c0..da1b5b18b684a5bbd58a1ab126e1da021bcdbc69 100644 (file)
@@ -33,6 +33,7 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.property.PropertyDto;
 import org.sonar.db.property.PropertyQuery;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.component.TestComponentFinder;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
@@ -47,14 +48,12 @@ import static java.lang.String.format;
 import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
 import static java.util.Optional.ofNullable;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.web.UserRole.USER;
+import static org.sonar.db.component.ComponentTesting.newDirectory;
 import static org.sonar.db.component.ComponentTesting.newFileDto;
-import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
 import static org.sonar.server.favorite.ws.FavoritesWsParameters.PARAM_COMPONENT;
 
 public class AddActionTest {
-  private static final String PROJECT_KEY = "project-key";
-  private static final String PROJECT_UUID = "project-uuid";
-  private static final int USER_ID = 123;
 
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
@@ -71,50 +70,52 @@ public class AddActionTest {
 
   @Test
   public void add_a_project() {
-    ComponentDto project = insertProjectAndPermissions();
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(USER, project);
 
-    TestResponse result = call(PROJECT_KEY);
+    TestResponse result = call(project.getKey());
 
     assertThat(result.getStatus()).isEqualTo(HTTP_NO_CONTENT);
     List<PropertyDto> favorites = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder()
-      .setUserId(USER_ID)
+      .setUserId(user.getId())
       .setKey("favourite")
       .build(), dbSession);
     assertThat(favorites).hasSize(1);
     PropertyDto favorite = favorites.get(0);
     assertThat(favorite)
       .extracting(PropertyDto::getResourceId, PropertyDto::getUserId, PropertyDto::getKey)
-      .containsOnly(project.getId(), USER_ID, "favourite");
+      .containsOnly(project.getId(), user.getId(), "favourite");
   }
 
   @Test
   public void add_a_file() {
-    ComponentDto project = insertProjectAndPermissions();
+    ComponentDto project = db.components().insertPrivateProject();
     ComponentDto file = db.components().insertComponent(newFileDto(project));
-    userSession.addProjectPermission(UserRole.USER, project, file);
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(USER, project);
 
-    call(file.getDbKey());
+    call(file.getKey());
 
     List<PropertyDto> favorites = dbClient.propertiesDao().selectByQuery(PropertyQuery.builder()
-      .setUserId(USER_ID)
+      .setUserId(user.getId())
       .setKey("favourite")
       .build(), dbSession);
     assertThat(favorites).hasSize(1);
     PropertyDto favorite = favorites.get(0);
     assertThat(favorite)
       .extracting(PropertyDto::getResourceId, PropertyDto::getUserId, PropertyDto::getKey)
-      .containsOnly(file.getId(), USER_ID, "favourite");
+      .containsOnly(file.getId(), user.getId(), "favourite");
   }
 
   @Test
   public void fail_when_no_browse_permission_on_the_project() {
-    ComponentDto project = insertProject();
-    userSession.logIn();
-    userSession.addProjectPermission(UserRole.ADMIN, project);
+    ComponentDto project = db.components().insertPrivateProject();
+    userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
 
     expectedException.expect(ForbiddenException.class);
 
-    call(PROJECT_KEY);
+    call(project.getKey());
   }
 
   @Test
@@ -128,19 +129,20 @@ public class AddActionTest {
 
   @Test
   public void fail_when_user_is_not_authenticated() {
-    insertProject();
+    ComponentDto project = db.components().insertPrivateProject();
 
     expectedException.expect(UnauthorizedException.class);
 
-    call(PROJECT_KEY);
+    call(project.getKey());
   }
 
   @Test
   public void fail_when_using_branch_db_key() throws Exception {
     OrganizationDto organization = db.organizations().insert();
     ComponentDto project = db.components().insertMainBranch(organization);
-    userSession.logIn().addProjectPermission(UserRole.USER, project);
     ComponentDto branch = db.components().insertProjectBranch(project);
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(USER, project);
 
     expectedException.expect(NotFoundException.class);
     expectedException.expectMessage(format("Component key '%s' not found", branch.getDbKey()));
@@ -148,6 +150,19 @@ public class AddActionTest {
     call(branch.getDbKey());
   }
 
+  @Test
+  public void fail_on_directory() {
+    ComponentDto project = db.components().insertPrivateProject();
+    ComponentDto directory = db.components().insertComponent(newDirectory(project, "dir"));
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(USER, project);
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Only components with qualifiers TRK, VW, APP, SVW, FIL are supported");
+
+    call(directory.getKey());
+  }
+
   @Test
   public void definition() {
     WebService.Action definition = ws.getDef();
@@ -157,20 +172,6 @@ public class AddActionTest {
     assertThat(definition.param("component").isRequired()).isTrue();
   }
 
-  private ComponentDto insertProject() {
-    return db.components().insertComponent(newPrivateProjectDto(db.organizations().insert(), PROJECT_UUID).setDbKey(PROJECT_KEY));
-  }
-
-  private ComponentDto insertProjectAndPermissions() {
-    ComponentDto project = insertProject();
-    userSession
-      .logIn()
-      .setUserId(USER_ID)
-      .addProjectPermission(UserRole.USER, project);
-
-    return project;
-  }
-
   private TestResponse call(@Nullable String componentKey) {
     TestRequest request = ws.newRequest();
     ofNullable(componentKey).ifPresent(c -> request.setParam(PARAM_COMPONENT, c));