]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7274 Return authorized projects in api/qualitygates/search 956/head
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 11 May 2016 13:16:07 +0000 (15:16 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Fri, 13 May 2016 08:10:16 +0000 (10:10 +0200)
server/sonar-server/src/main/java/org/sonar/server/qualitygate/QgateProjectFinder.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SearchAction.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/QgateProjectFinderTest.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java
sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java
sonar-db/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml
sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java

index 08787b786d15f76047d0d746f572ab4357e9d8b6..fdd4b53a135faceaeccc92ab2fdf0229d2cc42b7 100644 (file)
  */
 package org.sonar.server.qualitygate;
 
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nonnull;
 import org.sonar.api.server.ServerSide;
+import org.sonar.api.utils.Paging;
+import org.sonar.api.web.UserRole;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
 import org.sonar.db.qualitygate.ProjectQgateAssociation;
 import org.sonar.db.qualitygate.ProjectQgateAssociationDao;
 import org.sonar.db.qualitygate.ProjectQgateAssociationDto;
 import org.sonar.db.qualitygate.ProjectQgateAssociationQuery;
 import org.sonar.db.qualitygate.QualityGateDao;
-import org.sonar.db.qualitygate.QualityGateDto;
-import org.sonar.server.exceptions.NotFoundException;
-
-import java.util.List;
+import org.sonar.server.user.UserSession;
 
-import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.FluentIterable.from;
+import static org.sonar.api.utils.Paging.forPageIndex;
+import static org.sonar.server.ws.WsUtils.checkFound;
 
 @ServerSide
 public class QgateProjectFinder {
 
+  private final DbClient dbClient;
+  private final QualityGateDao qualitygateDao;
+  private final ProjectQgateAssociationDao associationDao;
+  private final UserSession userSession;
+
+  public QgateProjectFinder(DbClient dbClient, UserSession userSession) {
+    this.dbClient = dbClient;
+    this.userSession = userSession;
+    this.qualitygateDao = dbClient.qualityGateDao();
+    this.associationDao = dbClient.projectQgateAssociationDao();
+  }
+
+  public Association find(ProjectQgateAssociationQuery query) {
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      getQualityGateId(dbSession, query.gateId());
+      List<ProjectQgateAssociationDto> projects = associationDao.selectProjects(dbSession, query);
+      List<ProjectQgateAssociationDto> authorizedProjects = keepAuthorizedProjects(dbSession, projects);
+
+      Paging paging = forPageIndex(query.pageIndex())
+        .withPageSize(query.pageSize())
+        .andTotal(authorizedProjects.size());
+      return new Association(toProjectAssociations(getPaginatedProjects(authorizedProjects, paging)), paging.hasNextPage());
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+  }
+
+  private Long getQualityGateId(DbSession dbSession, String gateId) {
+    return checkFound(qualitygateDao.selectById(dbSession, Long.valueOf(gateId)), "Quality gate '" + gateId + "' does not exists.").getId();
+  }
+
+  private static List<ProjectQgateAssociationDto> getPaginatedProjects(List<ProjectQgateAssociationDto> projects, Paging paging) {
+    return from(projects)
+      .skip(paging.offset())
+      .limit(paging.pageSize())
+      .toList();
+  }
+
+  private static List<ProjectQgateAssociation> toProjectAssociations(List<ProjectQgateAssociationDto> dtos) {
+    return from(dtos).transform(ToProjectAssociation.INSTANCE).toList();
+  }
+
+  private List<ProjectQgateAssociationDto> keepAuthorizedProjects(DbSession dbSession, List<ProjectQgateAssociationDto> projects) {
+    List<Long> projectIds = from(projects).transform(ToProjectId.INSTANCE).toList();
+    Collection<Long> authorizedProjectIds = dbClient.authorizationDao().keepAuthorizedProjectIds(dbSession, projectIds, userSession.getUserId(), UserRole.USER);
+    return from(projects).filter(new MatchProjectId(authorizedProjectIds)).toList();
+  }
+
   public static class Association {
     private List<ProjectQgateAssociation> projects;
     private boolean hasMoreResults;
@@ -53,45 +110,35 @@ public class QgateProjectFinder {
     }
   }
 
-  private final QualityGateDao qualitygateDao;
-  private final ProjectQgateAssociationDao associationDao;
+  private enum ToProjectId implements Function<ProjectQgateAssociationDto, Long> {
+    INSTANCE;
 
-  public QgateProjectFinder(QualityGateDao qualitygateDao, ProjectQgateAssociationDao associationDao) {
-    this.qualitygateDao = qualitygateDao;
-    this.associationDao = associationDao;
+    @Override
+    public Long apply(@Nonnull ProjectQgateAssociationDto input) {
+      return input.getId();
+    }
   }
 
-  public Association find(ProjectQgateAssociationQuery query) {
-    Long gateId = validateId(query.gateId());
-    int pageSize = query.pageSize();
-    int pageIndex = query.pageIndex();
-
-    int offset = (pageIndex - 1) * pageSize;
-    // Add one to page size in order to be able to know if there's more results or not
-    int limit = pageSize + 1;
-    List<ProjectQgateAssociationDto> dtos = associationDao.selectProjects(query, gateId, offset, limit);
-    boolean hasMoreResults = false;
-    if (dtos.size() == limit) {
-      hasMoreResults = true;
-      // Removed last entry as it's only need to know if there more results or not
-      dtos.remove(dtos.size() - 1);
+  private static class MatchProjectId implements Predicate<ProjectQgateAssociationDto> {
+    private final Collection<Long> projectIds;
+
+    private MatchProjectId(Collection<Long> projectIds) {
+      this.projectIds = projectIds;
     }
-    return new Association(toProjectAssociations(dtos), hasMoreResults);
-  }
 
-  private Long validateId(String gateId) {
-    QualityGateDto qualityGateDto = qualitygateDao.selectById(Long.valueOf(gateId));
-    if (qualityGateDto == null) {
-      throw new NotFoundException("Quality gate '" + gateId + "' does not exists.");
+    @Override
+    public boolean apply(@Nonnull ProjectQgateAssociationDto input) {
+      return projectIds.contains(input.getId());
     }
-    return qualityGateDto.getId();
   }
 
-  private List<ProjectQgateAssociation> toProjectAssociations(List<ProjectQgateAssociationDto> dtos) {
-    List<ProjectQgateAssociation> groups = newArrayList();
-    for (ProjectQgateAssociationDto groupMembershipDto : dtos) {
-      groups.add(groupMembershipDto.toQgateAssociation());
+  private enum ToProjectAssociation implements Function<ProjectQgateAssociationDto, ProjectQgateAssociation> {
+    INSTANCE;
+
+    @Override
+    public ProjectQgateAssociation apply(@Nonnull ProjectQgateAssociationDto input) {
+      return input.toQgateAssociation();
     }
-    return groups;
   }
+
 }
index faba83f326e7a771004aada388e1dd656da4d51b..a859ed87d0888a3a312d7d444209d50ea2d4491b 100644 (file)
  */
 package org.sonar.server.qualitygate.ws;
 
-import org.sonar.api.server.ws.WebService.Param;
-
 import com.google.common.io.Resources;
 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.server.ws.WebService.Param;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.db.qualitygate.ProjectQgateAssociation;
 import org.sonar.db.qualitygate.ProjectQgateAssociationQuery;
@@ -41,7 +40,8 @@ public class SearchAction implements QGateWsAction {
   @Override
   public void define(WebService.NewController controller) {
     WebService.NewAction action = controller.createAction("search")
-      .setDescription("Search for projects associated (or not) to a quality gate")
+      .setDescription("Search for projects associated (or not) to a quality gate.<br/>" +
+        "Only authorized projects for current user will be returned.")
       .setSince("4.3")
       .setResponseExample(Resources.getResource(this.getClass(), "example-search.json"))
       .setHandler(this);
@@ -79,6 +79,7 @@ public class SearchAction implements QGateWsAction {
     JsonWriter writer = response.newJsonWriter();
     writer.beginObject().prop("more", associations.hasMoreResults());
     writer.name("results").beginArray();
+
     for (ProjectQgateAssociation project : associations.projects()) {
       writer.beginObject().prop("id", project.id()).prop("name", project.name()).prop(Param.SELECTED, project.isMember()).endObject();
     }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QgateProjectFinderTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QgateProjectFinderTest.java
new file mode 100644 (file)
index 0000000..04db472
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.qualitygate;
+
+import com.google.common.base.Function;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.property.PropertyDto;
+import org.sonar.db.qualitygate.ProjectQgateAssociation;
+import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.db.user.GroupRoleDto;
+import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserRoleDto;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.qualitygate.QgateProjectFinder.Association;
+import org.sonar.server.tester.UserSessionRule;
+
+import static com.google.common.collect.FluentIterable.from;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.component.ComponentTesting.newProjectDto;
+import static org.sonar.db.qualitygate.ProjectQgateAssociationQuery.IN;
+import static org.sonar.db.qualitygate.ProjectQgateAssociationQuery.OUT;
+import static org.sonar.db.qualitygate.ProjectQgateAssociationQuery.builder;
+import static org.sonar.db.user.UserTesting.newUserDto;
+import static org.sonar.server.qualitygate.QualityGates.SONAR_QUALITYGATE_PROPERTY;
+
+public class QgateProjectFinderTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Rule
+  public UserSessionRule userSession = UserSessionRule.standalone();
+
+  @Rule
+  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+  DbClient dbClient = dbTester.getDbClient();
+
+  DbSession dbSession = dbTester.getSession();
+
+  ComponentDbTester componentDbTester = new ComponentDbTester(dbTester);
+
+  UserDto userDto;
+
+  QualityGateDto qGate;
+
+  QgateProjectFinder underTest = new QgateProjectFinder(dbClient, userSession);
+
+  @Before
+  public void setUp() throws Exception {
+    userDto = newUserDto();
+    dbClient.userDao().insert(dbSession, userDto);
+
+    qGate = new QualityGateDto().setName("Default Quality Gate");
+    dbClient.qualityGateDao().insert(qGate, dbSession);
+
+    dbTester.commit();
+  }
+
+  @Test
+  public void return_empty_association() throws Exception {
+    Association result = underTest.find(
+      builder()
+        .gateId(Long.toString(qGate.getId()))
+        .build());
+
+    assertThat(result.projects()).isEmpty();
+  }
+
+  @Test
+  public void return_all_projects() throws Exception {
+    ComponentDto associatedProject = insertProjectAuthorizedToAnyone(newProjectDto());
+    ComponentDto unassociatedProject = insertProjectAuthorizedToAnyone(newProjectDto());
+    associateProjectToQualitGate(associatedProject.getId());
+
+    Association result = underTest.find(
+      builder()
+        .gateId(Long.toString(qGate.getId()))
+        .build());
+
+    Map<Long, ProjectQgateAssociation> projectsById = projectsById(result.projects());
+    assertThat(projectsById).hasSize(2);
+
+    verifyProject(projectsById.get(associatedProject.getId()), true, associatedProject.name());
+    verifyProject(projectsById.get(unassociatedProject.getId()), false, unassociatedProject.name());
+  }
+
+  @Test
+  public void return_only_associated_project() throws Exception {
+    ComponentDto associatedProject = insertProjectAuthorizedToAnyone(newProjectDto());
+    insertProjectAuthorizedToAnyone(newProjectDto());
+    associateProjectToQualitGate(associatedProject.getId());
+
+    Association result = underTest.find(
+      builder()
+        .membership(IN)
+        .gateId(Long.toString(qGate.getId()))
+        .build());
+
+    Map<Long, ProjectQgateAssociation> projectsById = projectsById(result.projects());
+    assertThat(projectsById).hasSize(1);
+    verifyProject(projectsById.get(associatedProject.getId()), true, associatedProject.name());
+  }
+
+  @Test
+  public void return_only_unassociated_project() throws Exception {
+    ComponentDto associatedProject = insertProjectAuthorizedToAnyone(newProjectDto());
+    ComponentDto unassociatedProject = insertProjectAuthorizedToAnyone(newProjectDto());
+    associateProjectToQualitGate(associatedProject.getId());
+
+    Association result = underTest.find(
+      builder()
+        .membership(OUT)
+        .gateId(Long.toString(qGate.getId()))
+        .build());
+
+    Map<Long, ProjectQgateAssociation> projectsById = projectsById(result.projects());
+    assertThat(projectsById).hasSize(1);
+    verifyProject(projectsById.get(unassociatedProject.getId()), false, unassociatedProject.name());
+  }
+
+  @Test
+  public void return_only_authorized_projects() throws Exception {
+    userSession.login(userDto.getLogin()).setUserId(userDto.getId().intValue());
+    ComponentDto project1 = componentDbTester.insertComponent(newProjectDto());
+    componentDbTester.insertComponent(newProjectDto());
+
+    // User can only see project 1
+    dbClient.roleDao().insertUserRole(dbSession, new UserRoleDto().setUserId(userDto.getId()).setResourceId(project1.getId()).setRole(UserRole.USER));
+    dbTester.commit();
+
+    Association result = underTest.find(
+      builder()
+        .gateId(Long.toString(qGate.getId()))
+        .build());
+
+    verifyProjects(result, project1.getId());
+  }
+
+  @Test
+  public void test_paging() throws Exception {
+    ComponentDto project1 = insertProjectAuthorizedToAnyone(newProjectDto().setName("Project 1"));
+    ComponentDto project2 = insertProjectAuthorizedToAnyone(newProjectDto().setName("Project 2"));
+    ComponentDto project3 = insertProjectAuthorizedToAnyone(newProjectDto().setName("Project 3"));
+    associateProjectToQualitGate(project1.getId());
+
+    // Return partial result on first page
+    verifyPaging(underTest.find(
+      builder().gateId(Long.toString(qGate.getId()))
+        .pageIndex(1)
+        .pageSize(1)
+        .build()),
+      true, project1.getId());
+
+    // Return partial result on second page
+    verifyPaging(underTest.find(
+      builder().gateId(Long.toString(qGate.getId()))
+        .pageIndex(2)
+        .pageSize(1)
+        .build()),
+      true, project2.getId());
+
+    // Return partial result on first page
+    verifyPaging(underTest.find(
+      builder().gateId(Long.toString(qGate.getId()))
+        .pageIndex(1)
+        .pageSize(2)
+        .build()),
+      true, project1.getId(), project2.getId());
+
+    // Return all result on first page
+    verifyPaging(underTest.find(
+      builder().gateId(Long.toString(qGate.getId()))
+        .pageIndex(1)
+        .pageSize(3)
+        .build()),
+      false, project1.getId(), project2.getId(), project3.getId());
+
+    // Return no result as page index is off limit
+    verifyPaging(underTest.find(
+      builder().gateId(Long.toString(qGate.getId()))
+        .pageIndex(3)
+        .pageSize(3)
+        .build()),
+      false);
+  }
+
+  @Test
+  public void fail_on_unknown_quality_gate() throws Exception {
+    expectedException.expect(NotFoundException.class);
+    underTest.find(builder().gateId("123").build());
+  }
+
+  private void verifyProject(ProjectQgateAssociation project, boolean expectedMembership, String expectedName) {
+    assertThat(project.isMember()).isEqualTo(expectedMembership);
+    assertThat(project.name()).isEqualTo(expectedName);
+  }
+
+  private void verifyProjects(Association association, Long... expectedProjectIds) {
+    assertThat(association.projects()).extracting("id").containsOnly(expectedProjectIds);
+  }
+
+  private void verifyPaging(Association association, boolean expectedHasMoreResults, Long... expectedProjectIds) {
+    assertThat(association.hasMoreResults()).isEqualTo(expectedHasMoreResults);
+    assertThat(association.projects()).extracting("id").containsOnly(expectedProjectIds);
+  }
+
+  private void associateProjectToQualitGate(long projectId) {
+    dbClient.propertiesDao().insertProperty(
+      new PropertyDto().setKey(SONAR_QUALITYGATE_PROPERTY)
+        .setResourceId(projectId)
+        .setValue(Long.toString(qGate.getId())));
+    dbTester.commit();
+  }
+
+  private ComponentDto insertProjectAuthorizedToAnyone(ComponentDto project) {
+    componentDbTester.insertComponent(project);
+    dbClient.roleDao().insertGroupRole(dbSession, new GroupRoleDto().setGroupId(null).setResourceId(project.getId()).setRole(UserRole.USER));
+    dbSession.commit();
+    return project;
+  }
+
+  private ComponentDto insertProjectAuthorizedToUser(ComponentDto project, UserDto userDto) {
+    componentDbTester.insertComponent(project);
+    dbClient.roleDao().insertGroupRole(dbSession, new GroupRoleDto().setGroupId(null).setResourceId(project.getId()).setRole(UserRole.USER));
+    dbSession.commit();
+    return project;
+  }
+
+  private static Map<Long, ProjectQgateAssociation> projectsById(List<ProjectQgateAssociation> projects) {
+    return from(projects).uniqueIndex(ProjectToId.INSTANCE);
+  }
+
+  private enum ProjectToId implements Function<ProjectQgateAssociation, Long> {
+    INSTANCE;
+
+    @Override
+    public Long apply(@Nonnull ProjectQgateAssociation input) {
+      return input.id();
+    }
+  }
+}
index 0d541008b5aabdca67d9ccc09f923cc28c6132b6..c984fbe315cae322c3c3041f5e1b2bf2abe51e1e 100644 (file)
  */
 package org.sonar.db.qualitygate;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableMap;
 import java.util.List;
-import java.util.Map;
-import org.apache.ibatis.session.RowBounds;
 import org.apache.ibatis.session.SqlSession;
 import org.sonar.db.Dao;
-import org.sonar.db.MyBatis;
+import org.sonar.db.DbSession;
 
 public class ProjectQgateAssociationDao implements Dao {
 
-  private final MyBatis mybatis;
-
-  public ProjectQgateAssociationDao(MyBatis mybatis) {
-    this.mybatis = mybatis;
-  }
-
-  public List<ProjectQgateAssociationDto> selectProjects(ProjectQgateAssociationQuery query, Long gateId, int offset, int limit) {
-    SqlSession session = mybatis.openSession(false);
-    try {
-      Map<String, Object> params = ImmutableMap.of("query", query, "gateId", gateId.toString());
-      return mapper(session).selectProjects(params, new RowBounds(offset, limit));
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
-  @VisibleForTesting
-  List<ProjectQgateAssociationDto> selectProjects(ProjectQgateAssociationQuery query, Long gateId) {
-    return selectProjects(query, gateId, 0, Integer.MAX_VALUE);
+  public List<ProjectQgateAssociationDto> selectProjects(DbSession dbSession, ProjectQgateAssociationQuery query) {
+    return mapper(dbSession).selectProjects(query);
   }
 
   private static ProjectQgateAssociationMapper mapper(SqlSession session) {
index bdd5a84c1251955c80684175954f64b509ad3562..5b9d9462d2a4d79a7ce540be708fdf532d589284 100644 (file)
 package org.sonar.db.qualitygate;
 
 import java.util.List;
-import java.util.Map;
-import org.apache.ibatis.session.RowBounds;
+import org.apache.ibatis.annotations.Param;
 
 public interface ProjectQgateAssociationMapper {
 
-  List<ProjectQgateAssociationDto> selectProjects(ProjectQgateAssociationQuery query);
+  List<ProjectQgateAssociationDto> selectProjects(@Param("query") ProjectQgateAssociationQuery query);
 
-  List<ProjectQgateAssociationDto> selectProjects(Map<String, Object> params, RowBounds rowBounds);
 }
index bbcf7b52121a4ebb4f990645d79fcf2749420bc6..76f7654ad0bb82bd1e8f86e416b24ee462c5be75 100644 (file)
@@ -10,7 +10,7 @@
       JOIN resource_index ind ON ind.root_project_id=proj.id
     </if>
     LEFT JOIN properties prop ON prop.resource_id=proj.id AND prop.prop_key='sonar.qualitygate' AND prop.text_value LIKE
-    #{gateId}
+    #{query.gateId}
     <where>
       <choose>
         <when test="query.membership() == 'selected'">
index cc83b038bcc96c070b4054009e13189942a4f767..fbf6e2812b02111cca1ecfe0ef78522cc901f64f 100644 (file)
@@ -23,6 +23,7 @@ import java.util.List;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
+import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -33,6 +34,8 @@ public class ProjectQgateAssociationDaoTest {
   @Rule
   public DbTester dbTester = DbTester.create(System2.INSTANCE);
 
+  DbSession dbSession = dbTester.getSession();
+
   ProjectQgateAssociationDao dao = dbTester.getDbClient().projectQgateAssociationDao();
 
   @Test
@@ -40,7 +43,7 @@ public class ProjectQgateAssociationDaoTest {
     dbTester.prepareDbUnit(getClass(), "shared.xml");
 
     ProjectQgateAssociationQuery query = ProjectQgateAssociationQuery.builder().gateId("42").build();
-    List<ProjectQgateAssociationDto> result = dao.selectProjects(query, 42L);
+    List<ProjectQgateAssociationDto> result = dao.selectProjects(dbSession, query);
     assertThat(result).hasSize(5);
   }
 
@@ -48,22 +51,22 @@ public class ProjectQgateAssociationDaoTest {
   public void select_projects_by_query() {
     dbTester.prepareDbUnit(getClass(), "shared.xml");
 
-    assertThat(dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.IN).build(), 42L)).hasSize(3);
-    assertThat(dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.OUT).build(), 42L)).hasSize(2);
+    assertThat(dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.IN).build())).hasSize(3);
+    assertThat(dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.OUT).build())).hasSize(2);
   }
 
   @Test
   public void search_by_project_name() {
     dbTester.prepareDbUnit(getClass(), "shared.xml");
 
-    List<ProjectQgateAssociationDto> result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build(), 42L);
+    List<ProjectQgateAssociationDto> result = dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build());
     assertThat(result).hasSize(1);
 
     assertThat(result.get(0).getName()).isEqualTo("Project One");
 
-    result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build(), 42L);
+    result = dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build());
     assertThat(result).hasSize(1);
-    result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("project").build(), 42L);
+    result = dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("project").build());
     assertThat(result).hasSize(2);
   }
 
@@ -71,7 +74,7 @@ public class ProjectQgateAssociationDaoTest {
   public void should_be_sorted_by_project_name() {
     dbTester.prepareDbUnit(getClass(), "shared.xml");
 
-    List<ProjectQgateAssociationDto> result = dao.selectProjects(ProjectQgateAssociationQuery.builder().gateId("42").build(), 42L);
+    List<ProjectQgateAssociationDto> result = dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").build());
     assertThat(result).hasSize(5);
     assertThat(result.get(0).getName()).isEqualTo("Project Five");
     assertThat(result.get(1).getName()).isEqualTo("Project Four");