]> source.dussan.org Git - sonarqube.git/commitdiff
[SONAR-18964] make query parameters lastConnectedAfter, lastConnectedBefore, slLastCo...
authorSteve Marion <steve.marion@sonarsource.com>
Wed, 12 Apr 2023 15:45:26 +0000 (17:45 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 12 Apr 2023 20:03:18 +0000 (20:03 +0000)
server/sonar-webserver-webapi/src/it/java/org/sonar/server/user/ws/SearchActionIT.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/SearchAction.java

index 7ce5deac9906615230c891a6518c954a938eb1f2..db71e878feaab3ee2bbcef705f3393967e2532f1 100644 (file)
 package org.sonar.server.user.ws;
 
 import java.time.Instant;
+import java.time.OffsetDateTime;
 import java.time.temporal.ChronoUnit;
 import java.util.Set;
 import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import org.assertj.core.api.InstanceOfAssertFactories;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.server.ws.WebService;
@@ -34,6 +37,7 @@ import org.sonar.db.scim.ScimUserDao;
 import org.sonar.db.user.GroupDto;
 import org.sonar.db.user.UserDto;
 import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ServerException;
 import org.sonar.server.issue.AvatarResolverImpl;
 import org.sonar.server.management.ManagedInstanceService;
 import org.sonar.server.tester.UserSessionRule;
@@ -50,6 +54,7 @@ import static java.util.function.Function.identity;
 import static java.util.stream.Collectors.toMap;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.assertj.core.api.Assertions.tuple;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -510,18 +515,35 @@ public class SearchActionIT {
       .extracting(User::getLogin)
       .containsExactlyInAnyOrder(user.getLogin());
 
-    assertUserWithFilter("lastConnectedAfter", lastConnection.minus(1, ChronoUnit.DAYS), user.getLogin(), true);
-    assertUserWithFilter("lastConnectedAfter", lastConnection.plus(1, ChronoUnit.DAYS), user.getLogin(), false);
-    assertUserWithFilter("lastConnectedBefore", lastConnection.minus(1, ChronoUnit.DAYS), user.getLogin(), false);
-    assertUserWithFilter("lastConnectedBefore", lastConnection.plus(1, ChronoUnit.DAYS), user.getLogin(), true);
+    assertUserWithFilter(SearchAction.LAST_CONNECTION_DATE_FROM, lastConnection.minus(1, ChronoUnit.DAYS), user.getLogin(), true);
+    assertUserWithFilter(SearchAction.LAST_CONNECTION_DATE_FROM, lastConnection.plus(1, ChronoUnit.DAYS), user.getLogin(), false);
+    assertUserWithFilter(SearchAction.LAST_CONNECTION_DATE_TO, lastConnection.minus(1, ChronoUnit.DAYS), user.getLogin(), false);
+    assertUserWithFilter(SearchAction.LAST_CONNECTION_DATE_TO, lastConnection.plus(1, ChronoUnit.DAYS), user.getLogin(), true);
 
-    assertUserWithFilter("slLastConnectedAfter", lastConnection.minus(1, ChronoUnit.DAYS), user.getLogin(), true);
-    assertUserWithFilter("slLastConnectedAfter", lastConnection.plus(1, ChronoUnit.DAYS), user.getLogin(), false);
-    assertUserWithFilter("slLastConnectedBefore", lastConnection.minus(1, ChronoUnit.DAYS), user.getLogin(), false);
-    assertUserWithFilter("slLastConnectedBefore", lastConnection.plus(1, ChronoUnit.DAYS), user.getLogin(), true);
+    assertUserWithFilter(SearchAction.SONAR_LINT_LAST_CONNECTION_DATE_FROM, lastConnection.minus(1, ChronoUnit.DAYS), user.getLogin(), true);
+    assertUserWithFilter(SearchAction.SONAR_LINT_LAST_CONNECTION_DATE_FROM, lastConnection.plus(1, ChronoUnit.DAYS), user.getLogin(), false);
+    assertUserWithFilter(SearchAction.SONAR_LINT_LAST_CONNECTION_DATE_TO, lastConnection.minus(1, ChronoUnit.DAYS), user.getLogin(), false);
+    assertUserWithFilter(SearchAction.SONAR_LINT_LAST_CONNECTION_DATE_TO, lastConnection.plus(1, ChronoUnit.DAYS), user.getLogin(), true);
 
-    assertUserWithFilter("slLastConnectedAfter", lastConnection, user.getLogin(), true);
-    assertUserWithFilter("slLastConnectedBefore", lastConnection, user.getLogin(), true);
+    assertUserWithFilter(SearchAction.SONAR_LINT_LAST_CONNECTION_DATE_FROM, lastConnection, user.getLogin(), true);
+    assertUserWithFilter(SearchAction.SONAR_LINT_LAST_CONNECTION_DATE_TO, lastConnection, user.getLogin(), true);
+  }
+
+  @Test
+  public void search_whenNotAdmin_shouldThrowForbidden() {
+    userSession.logIn();
+
+    Stream.of(SearchAction.LAST_CONNECTION_DATE_FROM, SearchAction.LAST_CONNECTION_DATE_TO,
+        SearchAction.SONAR_LINT_LAST_CONNECTION_DATE_FROM, SearchAction.SONAR_LINT_LAST_CONNECTION_DATE_TO)
+      .map(param -> ws.newRequest().setParam(param, formatDateTime(OffsetDateTime.now())))
+      .forEach(SearchActionIT::assertForbiddenException);
+  }
+
+  private static void assertForbiddenException(TestRequest testRequest) {
+    assertThatThrownBy(() -> testRequest.executeProtobuf(SearchWsResponse.class))
+      .asInstanceOf(InstanceOfAssertFactories.type(ServerException.class))
+      .extracting(ServerException::httpCode)
+      .isEqualTo(403);
   }
 
   private void assertUserWithFilter(String field, Instant filterValue, String userLogin, boolean isExpectedToBeThere) {
index 358efd5315eb4825d7b3cc4cd72969e9a50b029b..1f83f093fdec1d45ed47513f56180b6755b9a7d1 100644 (file)
@@ -73,10 +73,10 @@ public class SearchAction implements UsersWsAction {
 
 
   private static final int MAX_PAGE_SIZE = 500;
-  private static final String LAST_CONNECTION_DATE_FROM = "lastConnectedAfter";
-  private static final String LAST_CONNECTION_DATE_TO = "lastConnectedBefore";
-  private static final String SONAR_LINT_LAST_CONNECTION_DATE_FROM = "slLastConnectedAfter";
-  private static final String SONAR_LINT_LAST_CONNECTION_DATE_TO = "slLastConnectedBefore";
+  static final String LAST_CONNECTION_DATE_FROM = "lastConnectedAfter";
+  static final String LAST_CONNECTION_DATE_TO = "lastConnectedBefore";
+  static final String SONAR_LINT_LAST_CONNECTION_DATE_FROM = "slLastConnectedAfter";
+  static final String SONAR_LINT_LAST_CONNECTION_DATE_TO = "slLastConnectedBefore";
   private final UserSession userSession;
   private final DbClient dbClient;
   private final AvatarResolver avatarResolver;
@@ -108,9 +108,9 @@ public class SearchAction implements UsersWsAction {
       .setSince("3.6")
       .setChangelog(
         new Change("10.1", "New optional parameters " + SONAR_LINT_LAST_CONNECTION_DATE_FROM +
-          " and " + SONAR_LINT_LAST_CONNECTION_DATE_TO + " to filter users by SonarLint last connection date"),
+          " and " + SONAR_LINT_LAST_CONNECTION_DATE_TO + " to filter users by SonarLint last connection date. Only available with Administer System permission."),
         new Change("10.1", "New optional parameters " + LAST_CONNECTION_DATE_FROM +
-          " and " + LAST_CONNECTION_DATE_TO + " to filter users by SonarQube last connection date"),
+          " and " + LAST_CONNECTION_DATE_TO + " to filter users by SonarQube last connection date. Only available with Administer System permission."),
         new Change("10.1", "New field 'sonarLintLastConnectionDate' is added to response"),
         new Change("10.0", "'q' parameter values is now always performing a case insensitive match"),
         new Change("10.0", "New parameter 'managed' to optionally search by managed status"),
@@ -204,6 +204,12 @@ public class SearchAction implements UsersWsAction {
 
   private UserQuery buildUserQuery(SearchRequest request) {
     UserQuery.UserQueryBuilder builder = UserQuery.builder();
+    if(!userSession.isSystemAdministrator()) {
+      request.getLastConnectionDateFrom().ifPresent(v -> throwForbiddenFor(LAST_CONNECTION_DATE_FROM));
+      request.getLastConnectionDateTo().ifPresent(v -> throwForbiddenFor(LAST_CONNECTION_DATE_TO));
+      request.getSonarLintLastConnectionDateFrom().ifPresent(v -> throwForbiddenFor(SONAR_LINT_LAST_CONNECTION_DATE_FROM));
+      request.getSonarLintLastConnectionDateTo().ifPresent(v -> throwForbiddenFor(SONAR_LINT_LAST_CONNECTION_DATE_TO));
+    }
     request.getLastConnectionDateFrom().ifPresent(builder::lastConnectionDateFrom);
     request.getLastConnectionDateTo().ifPresent(builder::lastConnectionDateTo);
     request.getSonarLintLastConnectionDateFrom().ifPresent(builder::sonarLintLastConnectionDateFrom);
@@ -224,6 +230,10 @@ public class SearchAction implements UsersWsAction {
       .build();
   }
 
+  private static void throwForbiddenFor(String parameterName) {
+    throw new ServerException(403, "parameter " + parameterName + " requires Administer System permission.");
+  }
+
   private List<UserDto> findUsersAndSortByLogin(SearchRequest request, DbSession dbSession, UserQuery userQuery) {
     return dbClient.userDao().selectUsers(dbSession, userQuery, request.getPage(), request.getPageSize())
       .stream()