]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7254 Replace usage of UserIndex.getByLogin() by UserDao.selectOrFailByLogin()
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 15 Mar 2016 14:51:29 +0000 (15:51 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 21 Mar 2016 14:03:28 +0000 (15:03 +0100)
39 files changed:
server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CreateAction.java
server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/CustomMeasureJsonWriter.java
server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/measure/custom/ws/UpdateAction.java
server/sonar-server/src/main/java/org/sonar/server/startup/FeedUsersLocalStartupTask.java
server/sonar-server/src/main/java/org/sonar/server/user/ws/CreateAction.java
server/sonar-server/src/main/java/org/sonar/server/user/ws/CurrentAction.java
server/sonar-server/src/main/java/org/sonar/server/user/ws/DeactivateAction.java
server/sonar-server/src/main/java/org/sonar/server/user/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/user/ws/UpdateAction.java
server/sonar-server/src/main/java/org/sonar/server/user/ws/UserJsonWriter.java
server/sonar-server/src/main/java/org/sonar/server/ws/JsonWriterUtils.java
server/sonar-server/src/main/resources/org/sonar/server/user/ws/current-example.json
server/sonar-server/src/main/resources/org/sonar/server/user/ws/example-update.json
server/sonar-server/src/main/resources/org/sonar/server/user/ws/search-example.json
server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CreateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/CustomMeasuresWsTest.java
server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/SearchActionTest.java
server/sonar-server/src/test/java/org/sonar/server/measure/custom/ws/UpdateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/CreateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/DeactivateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/SearchActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/UpdateActionTest.java
server/sonar-server/src/test/java/org/sonar/server/user/ws/UsersWsTest.java
server/sonar-server/src/test/resources/org/sonar/server/user/ws/CreateActionTest/create_user.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/CreateActionTest/reactivate_user.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/DeactivateActionTest/deactivate_user.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/SearchActionTest/five_users.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/SearchActionTest/page_one.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/SearchActionTest/page_two.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/SearchActionTest/user_one.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/SearchActionTest/user_with_groups.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/UpdateActionTest/blank_email_is_updated_to_null.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/UpdateActionTest/update_email.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/UpdateActionTest/update_name.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/UpdateActionTest/update_scm_accounts.json
server/sonar-server/src/test/resources/org/sonar/server/user/ws/UpdateActionTest/update_user.json
sonar-db/src/main/java/org/sonar/db/user/UserDao.java
sonar-db/src/test/java/org/sonar/db/user/UserDaoTest.java

index dcf8ca7a28adc108aa7764d2806378141229b670..dd11c0f0c2d0470482c8c3bc09fadf62b4a4d757 100644 (file)
@@ -27,15 +27,13 @@ import org.sonar.api.utils.System2;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.MyBatis;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.db.metric.MetricDto;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.user.UserSession;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndex;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static org.sonar.server.component.ComponentFinder.ParamNames.PROJECT_ID_AND_KEY;
@@ -57,17 +55,15 @@ public class CreateAction implements CustomMeasuresWsAction {
   private final System2 system;
   private final CustomMeasureValidator validator;
   private final CustomMeasureJsonWriter customMeasureJsonWriter;
-  private final UserIndex userIndex;
   private final ComponentFinder componentFinder;
 
   public CreateAction(DbClient dbClient, UserSession userSession, System2 system, CustomMeasureValidator validator, CustomMeasureJsonWriter customMeasureJsonWriter,
-    UserIndex userIndex, ComponentFinder componentFinder) {
+    ComponentFinder componentFinder) {
     this.dbClient = dbClient;
     this.userSession = userSession;
     this.system = system;
     this.validator = validator;
     this.customMeasureJsonWriter = customMeasureJsonWriter;
-    this.userIndex = userIndex;
     this.componentFinder = componentFinder;
   }
 
@@ -120,12 +116,12 @@ public class CreateAction implements CustomMeasuresWsAction {
       checkPermissions(userSession, component);
       checkIsProjectOrModule(component);
       checkMeasureDoesNotExistAlready(dbSession, component, metric);
-      UserDoc user = userIndex.getByLogin(userSession.getLogin());
+      UserDto user = dbClient.userDao().selectOrFailByLogin(dbSession, userSession.getLogin());
       CustomMeasureDto measure = new CustomMeasureDto()
         .setComponentUuid(component.uuid())
         .setMetricId(metric.getId())
         .setDescription(description)
-        .setUserLogin(user.login())
+        .setUserLogin(user.getLogin())
         .setCreatedAt(now)
         .setUpdatedAt(now);
       validator.setMeasureValue(measure, valueAsString, metric);
@@ -136,7 +132,7 @@ public class CreateAction implements CustomMeasuresWsAction {
       customMeasureJsonWriter.write(json, measure, metric, component, user, true, CustomMeasureJsonWriter.OPTIONAL_FIELDS);
       json.close();
     } finally {
-      MyBatis.closeQuietly(dbSession);
+      dbClient.closeSession(dbSession);
     }
   }
 
index 66348531bcfae25d5722b781bb5399fa998e61b0..addd810f4e8557c632ad7070bee7c40a1bcc3dd8 100644 (file)
@@ -27,11 +27,11 @@ import java.util.Map;
 import java.util.Set;
 import javax.annotation.Nullable;
 import org.sonar.api.measures.Metric;
-import org.sonar.api.user.User;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.db.metric.MetricDto;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.metric.ws.MetricJsonWriter;
 import org.sonar.server.user.ws.UserJsonWriter;
 
@@ -59,7 +59,7 @@ public class CustomMeasureJsonWriter {
     this.userJsonWriter = userJsonWriter;
   }
 
-  public void write(JsonWriter json, CustomMeasureDto measure, MetricDto metric, ComponentDto component, User user, boolean isPending, Collection<String> fieldsToReturn) {
+  public void write(JsonWriter json, CustomMeasureDto measure, MetricDto metric, ComponentDto component, UserDto user, boolean isPending, Collection<String> fieldsToReturn) {
     json.beginObject();
     json.prop(FIELD_ID, String.valueOf(measure.getId()));
     writeIfNeeded(json, measureValue(measure, metric), FIELD_VALUE, fieldsToReturn);
@@ -109,7 +109,7 @@ public class CustomMeasureJsonWriter {
     }
   }
 
-  public void write(JsonWriter json, List<CustomMeasureDto> customMeasures, ComponentDto project, Map<Integer, MetricDto> metricsById, Map<String, User> usersByLogin,
+  public void write(JsonWriter json, List<CustomMeasureDto> customMeasures, ComponentDto project, Map<Integer, MetricDto> metricsById, Map<String, UserDto> usersByLogin,
     @Nullable Long lastAnalysisTimestamp, Collection<String> fieldsToReturn) {
     json.name("customMeasures");
     json.beginArray();
index dc5c61e17876c6a61b1e2c976b32fda3b53b34b2..16ed05c32e8676446739b558bc88c65b627ac6c2 100644 (file)
@@ -31,7 +31,6 @@ 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.api.user.User;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
@@ -40,10 +39,10 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.db.metric.MetricDto;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.es.SearchOptions;
 import org.sonar.server.user.UserSession;
-import org.sonar.server.user.index.UserIndex;
 
 import static com.google.common.collect.Sets.newHashSet;
 import static org.sonar.server.component.ComponentFinder.ParamNames.PROJECT_ID_AND_KEY;
@@ -58,14 +57,12 @@ public class SearchAction implements CustomMeasuresWsAction {
   public static final String PARAM_PROJECT_KEY = "projectKey";
 
   private final DbClient dbClient;
-  private final UserIndex userIndex;
   private final CustomMeasureJsonWriter customMeasureJsonWriter;
   private final UserSession userSession;
   private final ComponentFinder componentFinder;
 
-  public SearchAction(DbClient dbClient, UserIndex userIndex, CustomMeasureJsonWriter customMeasureJsonWriter, UserSession userSession, ComponentFinder componentFinder) {
+  public SearchAction(DbClient dbClient, CustomMeasureJsonWriter customMeasureJsonWriter, UserSession userSession, ComponentFinder componentFinder) {
     this.dbClient = dbClient;
-    this.userIndex = userIndex;
     this.customMeasureJsonWriter = customMeasureJsonWriter;
     this.userSession = userSession;
     this.componentFinder = componentFinder;
@@ -107,7 +104,7 @@ public class SearchAction implements CustomMeasuresWsAction {
       Long lastAnalysisDateMs = searchLastSnapshot(dbSession, project);
       List<CustomMeasureDto> customMeasures = searchCustomMeasures(dbSession, project, searchOptions);
       int nbCustomMeasures = countTotalOfCustomMeasures(dbSession, project);
-      Map<String, User> usersByLogin = usersByLogin(customMeasures);
+      Map<String, UserDto> usersByLogin = usersByLogin(dbSession, customMeasures);
       Map<Integer, MetricDto> metricsById = metricsById(dbSession, customMeasures);
 
       writeResponse(response, customMeasures, nbCustomMeasures, project, metricsById, usersByLogin, lastAnalysisDateMs, searchOptions, fieldsToReturn);
@@ -132,7 +129,7 @@ public class SearchAction implements CustomMeasuresWsAction {
   }
 
   private void writeResponse(Response response, List<CustomMeasureDto> customMeasures, int nbCustomMeasures, ComponentDto project, Map<Integer, MetricDto> metricsById,
-                             Map<String, User> usersByLogin, @Nullable Long lastAnalysisDate, SearchOptions searchOptions, List<String> fieldsToReturn) {
+    Map<String, UserDto> usersByLogin, @Nullable Long lastAnalysisDate, SearchOptions searchOptions, List<String> fieldsToReturn) {
     JsonWriter json = response.newJsonWriter();
     json.beginObject();
     customMeasureJsonWriter.write(json, customMeasures, project, metricsById, usersByLogin, lastAnalysisDate, fieldsToReturn);
@@ -146,10 +143,12 @@ public class SearchAction implements CustomMeasuresWsAction {
     return Maps.uniqueIndex(metrics, MetricToIdFunction.INSTANCE);
   }
 
-  private Map<String, User> usersByLogin(List<CustomMeasureDto> customMeasures) {
-    return FluentIterable.from(customMeasures)
+  private Map<String, UserDto> usersByLogin(DbSession dbSession, List<CustomMeasureDto> customMeasures) {
+    List<String> logins = FluentIterable.from(customMeasures)
       .transform(CustomMeasureToUserLoginFunction.INSTANCE)
-      .toMap(new UserLoginToUserFunction());
+      .toList();
+    List<UserDto> userDtos = dbClient.userDao().selectByLogins(dbSession, logins);
+    return FluentIterable.from(userDtos).uniqueIndex(UserDtoToLogin.INSTANCE);
   }
 
   private enum CustomMeasureToUserLoginFunction implements Function<CustomMeasureDto, String> {
@@ -161,10 +160,12 @@ public class SearchAction implements CustomMeasuresWsAction {
     }
   }
 
-  private final class UserLoginToUserFunction implements Function<String, User> {
+  private enum UserDtoToLogin implements Function<UserDto, String> {
+    INSTANCE;
+
     @Override
-    public User apply(@Nonnull String userLogin) {
-      return userIndex.getByLogin(userLogin);
+    public String apply(@Nonnull UserDto input) {
+      return input.getLogin();
     }
   }
 
index 33490bb4845e00d6c4330b352cf83c444310f8d9..1bb074167ed1f20366ab554609316c107077d291 100644 (file)
@@ -23,7 +23,6 @@ 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.api.user.User;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.db.DbClient;
@@ -32,8 +31,8 @@ import org.sonar.db.MyBatis;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.db.metric.MetricDto;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.user.UserSession;
-import org.sonar.server.user.index.UserIndex;
 
 import static org.sonar.server.measure.custom.ws.CustomMeasureValidator.checkPermissions;
 import static org.sonar.server.measure.custom.ws.CustomMeasureValueDescription.measureValueDescription;
@@ -49,16 +48,13 @@ public class UpdateAction implements CustomMeasuresWsAction {
   private final System2 system;
   private final CustomMeasureValidator validator;
   private final CustomMeasureJsonWriter customMeasureJsonWriter;
-  private final UserIndex userIndex;
 
-  public UpdateAction(DbClient dbClient, UserSession userSession, System2 system, CustomMeasureValidator validator, CustomMeasureJsonWriter customMeasureJsonWriter,
-    UserIndex userIndex) {
+  public UpdateAction(DbClient dbClient, UserSession userSession, System2 system, CustomMeasureValidator validator, CustomMeasureJsonWriter customMeasureJsonWriter) {
     this.dbClient = dbClient;
     this.userSession = userSession;
     this.system = system;
     this.validator = validator;
     this.customMeasureJsonWriter = customMeasureJsonWriter;
-    this.userIndex = userIndex;
   }
 
   @Override
@@ -96,11 +92,11 @@ public class UpdateAction implements CustomMeasuresWsAction {
       MetricDto metric = dbClient.metricDao().selectOrFailById(dbSession, customMeasure.getMetricId());
       ComponentDto component = dbClient.componentDao().selectOrFailByUuid(dbSession, customMeasure.getComponentUuid());
       checkPermissions(userSession, component);
-      User user = userIndex.getByLogin(userSession.getLogin());
+      UserDto user = dbClient.userDao().selectOrFailByLogin(dbSession, userSession.getLogin());
 
       setValue(customMeasure, value, metric);
       setDescription(customMeasure, description);
-      customMeasure.setUserLogin(user.login());
+      customMeasure.setUserLogin(user.getLogin());
       customMeasure.setUpdatedAt(system.now());
       dbClient.customMeasureDao().update(dbSession, customMeasure);
       dbSession.commit();
index 7cb080eb22c3e2e8b9ebd58cb1506561c832c4c4..5be1fdc2cc56ec191f1cda0850c8a9349e4c09b5 100644 (file)
@@ -68,44 +68,44 @@ public class FeedUsersLocalStartupTask implements Startable {
 
   @Override
   public void start() {
-    DbSession session = dbClient.openSession(false);
+    DbSession dbSession = dbClient.openSession(false);
     try {
-      if (hasAlreadyBeenExecuted(session)) {
+      if (hasAlreadyBeenExecuted(dbSession)) {
         return;
       }
-      updateUsersLocal(session);
-      markAsExecuted(session);
-      session.commit();
+      updateUsersLocal(dbSession);
+      markAsExecuted(dbSession);
+      dbSession.commit();
 
       if (settings.hasKey(LOCAL_USERS_PROPERTY)) {
         LOG.info("NOTE : The property '{}' is now no more needed, you can safely remove it.", LOCAL_USERS_PROPERTY);
       }
     } finally {
-      dbClient.closeSession(session);
+      dbClient.closeSession(dbSession);
     }
   }
 
-  private void updateUsersLocal(DbSession session) {
+  private void updateUsersLocal(DbSession dbSession) {
     long now = system2.now();
     Set<String> localUsers = new HashSet<>(asList(settings.getStringArray(LOCAL_USERS_PROPERTY)));
     boolean isRealmExist = settings.getString(CORE_AUTHENTICATOR_REALM) != null;
-    for (UserDto user : dbClient.userDao().selectUsers(session, UserQuery.ALL_ACTIVES)) {
+    for (UserDto user : dbClient.userDao().selectUsers(dbSession, UserQuery.ALL_ACTIVES)) {
       if (user.getExternalIdentityProvider().equals(UserUpdater.SQ_AUTHORITY)) {
         user.setLocal(!isRealmExist || localUsers.contains(user.getLogin()));
       } else {
         user.setLocal(false);
       }
       user.setUpdatedAt(now);
-      dbClient.userDao().update(session, user);
+      dbClient.userDao().update(dbSession, user);
     }
   }
 
-  private boolean hasAlreadyBeenExecuted(DbSession session) {
-    return dbClient.loadedTemplateDao().countByTypeAndKey(ONE_SHOT_TASK_TYPE, TEMPLATE_KEY, session) > 0;
+  private boolean hasAlreadyBeenExecuted(DbSession dbSession) {
+    return dbClient.loadedTemplateDao().countByTypeAndKey(ONE_SHOT_TASK_TYPE, TEMPLATE_KEY, dbSession) > 0;
   }
 
-  private void markAsExecuted(DbSession session) {
-    dbClient.loadedTemplateDao().insert(new LoadedTemplateDto(TEMPLATE_KEY, ONE_SHOT_TASK_TYPE), session);
+  private void markAsExecuted(DbSession dbSession) {
+    dbClient.loadedTemplateDao().insert(new LoadedTemplateDto(TEMPLATE_KEY, ONE_SHOT_TASK_TYPE), dbSession);
   }
 
   @Override
index 8fa1cd31447835f903039c14f7630ea5b255450d..78a47459faff7838e35006581a84b50e7ae77d49 100644 (file)
@@ -26,11 +26,12 @@ import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.user.NewUser;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.user.UserUpdater;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndex;
 
 public class CreateAction implements UsersWsAction {
 
@@ -41,14 +42,14 @@ public class CreateAction implements UsersWsAction {
   private static final String PARAM_SCM_ACCOUNTS = "scmAccounts";
   private static final String PARAM_SCM_ACCOUNTS_DEPRECATED = "scm_accounts";
 
-  private final UserIndex index;
+  private final DbClient dbClient;
   private final UserUpdater userUpdater;
   private final I18n i18n;
   private final UserSession userSession;
   private final UserJsonWriter userWriter;
 
-  public CreateAction(UserIndex index, UserUpdater userUpdater, I18n i18n, UserSession userSession, UserJsonWriter userWriter) {
-    this.index = index;
+  public CreateAction(DbClient dbClient, UserUpdater userUpdater, I18n i18n, UserSession userSession, UserJsonWriter userWriter) {
+    this.dbClient = dbClient;
     this.userUpdater = userUpdater;
     this.i18n = i18n;
     this.userSession = userSession;
@@ -107,7 +108,7 @@ public class CreateAction implements UsersWsAction {
   }
 
   private void writeResponse(Response response, String login, boolean isUserReactivated) {
-    UserDoc user = index.getByLogin(login);
+    UserDto user = loadUser(login);
     JsonWriter json = response.newJsonWriter().beginObject();
     writeUser(json, user);
     if (isUserReactivated) {
@@ -116,7 +117,7 @@ public class CreateAction implements UsersWsAction {
     json.endObject().close();
   }
 
-  private void writeUser(JsonWriter json, UserDoc user) {
+  private void writeUser(JsonWriter json, UserDto user) {
     json.name("user");
     userWriter.write(json, user, ImmutableSet.<String>of(), UserJsonWriter.FIELDS);
   }
@@ -129,4 +130,13 @@ public class CreateAction implements UsersWsAction {
     json.endObject();
     json.endArray();
   }
+
+  private UserDto loadUser(String login){
+    DbSession dbSession = dbClient.openSession(false);
+    try {
+      return dbClient.userDao().selectOrFailByLogin(dbSession, login);
+    } finally {
+      dbClient.closeSession(dbSession);
+    }
+  }
 }
index 287273cd5610f3e59b01e4b552f257fd009165f9..d05399763e05cd3153ef2a8c95890310d9b8f872 100644 (file)
@@ -94,6 +94,7 @@ public class CurrentAction implements UsersWsAction {
       if (!isNullOrEmpty(user.getEmail())) {
         json.prop("email", user.getEmail());
       }
+      json.prop("local", user.isLocal());
     }
 
     writeScmAccounts(json, optionalUser);
index f4b252b8ee11e3e215ecc7e15dc873931346a497..e428e7d342681571b9739a1325dd1250e07a0d90 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.server.user.ws;
 
 import com.google.common.collect.Sets;
-import java.util.Arrays;
 import java.util.Set;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
@@ -30,25 +29,25 @@ import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.MyBatis;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.user.UserUpdater;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndex;
+
+import static java.lang.String.format;
+import static java.util.Collections.singletonList;
 
 public class DeactivateAction implements UsersWsAction {
 
   private static final String PARAM_LOGIN = "login";
 
-  private final UserIndex index;
   private final UserUpdater userUpdater;
   private final UserSession userSession;
   private final UserJsonWriter userWriter;
   private final DbClient dbClient;
 
-  public DeactivateAction(UserIndex index, UserUpdater userUpdater, UserSession userSession, UserJsonWriter userWriter, DbClient dbClient) {
-    this.index = index;
+  public DeactivateAction(UserUpdater userUpdater, UserSession userSession, UserJsonWriter userWriter, DbClient dbClient) {
     this.userUpdater = userUpdater;
     this.userSession = userSession;
     this.userWriter = userWriter;
@@ -83,21 +82,24 @@ public class DeactivateAction implements UsersWsAction {
   }
 
   private void writeResponse(Response response, String login) {
-    UserDoc user = index.getByLogin(login);
     JsonWriter json = response.newJsonWriter().beginObject();
-    writeUser(json, user);
+    writeUser(json, login);
     json.endObject().close();
   }
 
-  private void writeUser(JsonWriter json, UserDoc user) {
+  private void writeUser(JsonWriter json, String login) {
     json.name("user");
     Set<String> groups = Sets.newHashSet();
     DbSession dbSession = dbClient.openSession(false);
     try {
-      groups.addAll(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, Arrays.asList(user.login())).get(user.login()));
+      UserDto user = dbClient.userDao().selectByLogin(dbSession, login);
+      if (user == null) {
+        throw new NotFoundException(format("User '%s' doesn't exist", login));
+      }
+      groups.addAll(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(login)).get(login));
+      userWriter.write(json, user, groups, UserJsonWriter.FIELDS);
     } finally {
-      MyBatis.closeQuietly(dbSession);
+      dbClient.closeSession(dbSession);
     }
-    userWriter.write(json, user, groups, UserJsonWriter.FIELDS);
   }
 }
index 9f99a1d8d951d859f0b1f56527b2fb78c5a60053..4aae003f5efc695ded1329c71dcef50ba97d960e 100644 (file)
 package org.sonar.server.user.ws;
 
 import com.google.common.base.Function;
-import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Multimap;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import javax.annotation.Nonnull;
@@ -36,6 +34,7 @@ import org.sonar.api.server.ws.WebService.Param;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.es.SearchOptions;
 import org.sonar.server.es.SearchResult;
 import org.sonar.server.user.index.UserDoc;
@@ -79,36 +78,38 @@ public class SearchAction implements UsersWsAction {
     List<String> fields = request.paramAsStrings(Param.FIELDS);
     SearchResult<UserDoc> result = userIndex.search(request.param(Param.TEXT_QUERY), options);
 
-    Multimap<String, String> groupsByLogin = ArrayListMultimap.create();
-    Map<String, Integer> tokenCountsByLogin = new HashMap<>();
     DbSession dbSession = dbClient.openSession(false);
     try {
-      List<String> logins = Lists.transform(result.getDocs(), new Function<UserDoc, String>() {
-        @Override
-        public String apply(@Nonnull UserDoc input) {
-          return input.login();
-        }
-      });
-      groupsByLogin = dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, logins);
-      tokenCountsByLogin = dbClient.userTokenDao().countTokensByLogins(dbSession, logins);
+      List<String> logins = Lists.transform(result.getDocs(), UserDocToLogin.INSTANCE);
+      Multimap<String, String> groupsByLogin = dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, logins);
+      Map<String, Integer> tokenCountsByLogin = dbClient.userTokenDao().countTokensByLogins(dbSession, logins);
+      JsonWriter json = response.newJsonWriter().beginObject();
+      options.writeJson(json, result.getTotal());
+      List<UserDto> userDtos = dbClient.userDao().selectByOrderedLogins(dbSession, logins);
+      writeUsers(json, userDtos, groupsByLogin, tokenCountsByLogin, fields);
+      json.endObject().close();
     } finally {
       dbClient.closeSession(dbSession);
     }
-
-    JsonWriter json = response.newJsonWriter().beginObject();
-    options.writeJson(json, result.getTotal());
-    writeUsers(json, result, groupsByLogin, tokenCountsByLogin, fields);
-    json.endObject().close();
   }
 
-  private void writeUsers(JsonWriter json, SearchResult<UserDoc> result, Multimap<String, String> groupsByLogin, Map<String, Integer> tokenCountsByLogin,
+  private void writeUsers(JsonWriter json, List<UserDto> userDtos, Multimap<String, String> groupsByLogin, Map<String, Integer> tokenCountsByLogin,
     @Nullable List<String> fields) {
 
     json.name("users").beginArray();
-    for (UserDoc user : result.getDocs()) {
-      Collection<String> groups = groupsByLogin.get(user.login());
-      userWriter.write(json, user, firstNonNull(tokenCountsByLogin.get(user.login()), 0), groups, fields);
+    for (UserDto user : userDtos) {
+      Collection<String> groups = groupsByLogin.get(user.getLogin());
+      userWriter.write(json, user, firstNonNull(tokenCountsByLogin.get(user.getLogin()), 0), groups, fields);
     }
     json.endArray();
   }
+
+  private enum UserDocToLogin implements Function<UserDoc, String> {
+    INSTANCE;
+
+    @Override
+    public String apply(@Nonnull UserDoc input) {
+      return input.login();
+    }
+  }
 }
index 7166a23e9a6cc404979a5afd2bbdd8bd40dc2008..9da94fae484bf5895d48194f3d8947b6f8a91e6e 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.server.user.ws;
 
 import com.google.common.collect.Sets;
-import java.util.Arrays;
 import java.util.Set;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
@@ -29,14 +28,15 @@ import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
-import org.sonar.db.MyBatis;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.user.UpdateUser;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.user.UserUpdater;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndex;
 
 import static com.google.common.base.Strings.emptyToNull;
+import static java.lang.String.format;
+import static java.util.Collections.singletonList;
 
 public class UpdateAction implements UsersWsAction {
 
@@ -46,14 +46,12 @@ public class UpdateAction implements UsersWsAction {
   private static final String PARAM_SCM_ACCOUNTS = "scmAccounts";
   private static final String PARAM_SCM_ACCOUNTS_DEPRECATED = "scm_accounts";
 
-  private final UserIndex index;
   private final UserUpdater userUpdater;
   private final UserSession userSession;
   private final UserJsonWriter userWriter;
   private final DbClient dbClient;
 
-  public UpdateAction(UserIndex index, UserUpdater userUpdater, UserSession userSession, UserJsonWriter userWriter, DbClient dbClient) {
-    this.index = index;
+  public UpdateAction(UserUpdater userUpdater, UserSession userSession, UserJsonWriter userWriter, DbClient dbClient) {
     this.userUpdater = userUpdater;
     this.userSession = userSession;
     this.userWriter = userWriter;
@@ -110,21 +108,24 @@ public class UpdateAction implements UsersWsAction {
   }
 
   private void writeResponse(Response response, String login) {
-    UserDoc user = index.getByLogin(login);
     JsonWriter json = response.newJsonWriter().beginObject();
-    writeUser(json, user);
+    writeUser(json, login);
     json.endObject().close();
   }
 
-  private void writeUser(JsonWriter json, UserDoc user) {
+  private void writeUser(JsonWriter json, String login) {
     json.name("user");
     Set<String> groups = Sets.newHashSet();
     DbSession dbSession = dbClient.openSession(false);
     try {
-      groups.addAll(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, Arrays.asList(user.login())).get(user.login()));
+      UserDto user = dbClient.userDao().selectByLogin(dbSession, login);
+      if (user == null) {
+        throw new NotFoundException(format("User '%s' doesn't exist", login));
+      }
+      groups.addAll(dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, singletonList(login)).get(login));
+      userWriter.write(json, user, groups, UserJsonWriter.FIELDS);
     } finally {
-      MyBatis.closeQuietly(dbSession);
+      dbClient.closeSession(dbSession);
     }
-    userWriter.write(json, user, groups, UserJsonWriter.FIELDS);
   }
 }
index 6958a6aebc16d7bf2128997d02411a66b2fbd485..88abcd1c8c3e8782337936c7164ccbda1df36d7c 100644 (file)
@@ -24,11 +24,10 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Set;
 import javax.annotation.Nullable;
-import org.sonar.api.user.User;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.user.UserSession;
-import org.sonar.server.user.index.UserDoc;
 
 import static org.sonar.server.ws.JsonWriterUtils.isFieldNeeded;
 import static org.sonar.server.ws.JsonWriterUtils.writeIfNeeded;
@@ -42,8 +41,9 @@ public class UserJsonWriter {
   private static final String FIELD_GROUPS = "groups";
   private static final String FIELD_ACTIVE = "active";
   private static final String FIELD_TOKENS_COUNT = "tokensCount";
+  private static final String FIELD_LOCAL = "local";
 
-  public static final Set<String> FIELDS = ImmutableSet.of(FIELD_NAME, FIELD_EMAIL, FIELD_SCM_ACCOUNTS, FIELD_GROUPS, FIELD_ACTIVE);
+  public static final Set<String> FIELDS = ImmutableSet.of(FIELD_NAME, FIELD_EMAIL, FIELD_SCM_ACCOUNTS, FIELD_GROUPS, FIELD_ACTIVE, FIELD_LOCAL);
   private static final Set<String> CONCISE_FIELDS = ImmutableSet.of(FIELD_NAME, FIELD_EMAIL, FIELD_ACTIVE);
 
   private final UserSession userSession;
@@ -55,19 +55,20 @@ public class UserJsonWriter {
   /**
    * Serializes a user to the passed JsonWriter.
    */
-  public void write(JsonWriter json, User user, Collection<String> groups, @Nullable Collection<String> fields) {
+  public void write(JsonWriter json, UserDto user, Collection<String> groups, @Nullable Collection<String> fields) {
     write(json, user, null, groups, fields);
   }
 
   /**
    * Serializes a user to the passed JsonWriter.
    */
-  public void write(JsonWriter json, User user, @Nullable Integer tokensCount, Collection<String> groups, @Nullable Collection<String> fields) {
+  public void write(JsonWriter json, UserDto user, @Nullable Integer tokensCount, Collection<String> groups, @Nullable Collection<String> fields) {
     json.beginObject();
-    json.prop(FIELD_LOGIN, user.login());
-    writeIfNeeded(json, user.name(), FIELD_NAME, fields);
-    writeIfNeeded(json, user.email(), FIELD_EMAIL, fields);
-    writeIfNeeded(json, user.active(), FIELD_ACTIVE, fields);
+    json.prop(FIELD_LOGIN, user.getLogin());
+    writeIfNeeded(json, user.getName(), FIELD_NAME, fields);
+    writeIfNeeded(json, user.getEmail(), FIELD_EMAIL, fields);
+    writeIfNeeded(json, user.isActive(), FIELD_ACTIVE, fields);
+    writeIfNeeded(json, user.isLocal(), FIELD_LOCAL, fields);
     writeGroupsIfNeeded(json, groups, fields);
     writeScmAccountsIfNeeded(json, fields, user);
     writeTokensCount(json, tokensCount);
@@ -75,9 +76,9 @@ public class UserJsonWriter {
   }
 
   /**
-   * A shortcut to {@link #write(JsonWriter, User, Collection, Collection)} with preselected fields and without group information
+   * A shortcut to {@link #write(JsonWriter, UserDto, Collection, Collection)} with preselected fields and without group information
    */
-  public void write(JsonWriter json, @Nullable User user) {
+  public void write(JsonWriter json, @Nullable UserDto user) {
     if (user == null) {
       json.beginObject().endObject();
     } else {
@@ -95,11 +96,11 @@ public class UserJsonWriter {
     }
   }
 
-  private static void writeScmAccountsIfNeeded(JsonWriter json, Collection<String> fields, User user) {
+  private static void writeScmAccountsIfNeeded(JsonWriter json, Collection<String> fields, UserDto user) {
     if (isFieldNeeded(FIELD_SCM_ACCOUNTS, fields)) {
       json.name(FIELD_SCM_ACCOUNTS)
         .beginArray()
-        .values(((UserDoc) user).scmAccounts())
+        .values(user.getScmAccountsAsList())
         .endArray();
     }
   }
index 2a0b62f25a85b11777a35573cdf8b839cd701a74..577204c90a2e79789718474f5cab7b0727733daf 100644 (file)
@@ -30,31 +30,31 @@ public class JsonWriterUtils {
     // Utility class
   }
 
-  public static void writeIfNeeded(JsonWriter json, @Nullable String value, String field, Collection<String> fields) {
+  public static void writeIfNeeded(JsonWriter json, @Nullable String value, String field, @Nullable Collection<String> fields) {
     if (isFieldNeeded(field, fields)) {
       json.prop(field, value);
     }
   }
 
-  public static void writeIfNeeded(JsonWriter json, @Nullable Boolean value, String field, Collection<String> fields) {
+  public static void writeIfNeeded(JsonWriter json, @Nullable Boolean value, String field, @Nullable Collection<String> fields) {
     if (isFieldNeeded(field, fields)) {
       json.prop(field, value);
     }
   }
 
-  public static void writeIfNeeded(JsonWriter json, @Nullable Integer value, String field, Collection<String> fields) {
+  public static void writeIfNeeded(JsonWriter json, @Nullable Integer value, String field, @Nullable Collection<String> fields) {
     if (isFieldNeeded(field, fields)) {
       json.prop(field, value);
     }
   }
 
-  public static void writeIfNeeded(JsonWriter json, @Nullable Long value, String field, Collection<String> fields) {
+  public static void writeIfNeeded(JsonWriter json, @Nullable Long value, String field, @Nullable Collection<String> fields) {
     if (isFieldNeeded(field, fields)) {
       json.prop(field, value);
     }
   }
 
-  public static void writeIfNeeded(JsonWriter json, @Nullable Date value, String field, Collection<String> fields) {
+  public static void writeIfNeeded(JsonWriter json, @Nullable Date value, String field, @Nullable Collection<String> fields) {
     if (isFieldNeeded(field, fields)) {
       json.propDateTime(field, value);
     }
index 76183bfb50e200e01095ea546088d6b7bd8b0e51..4a6ce26ec20cb3cf2ed7c674b2c91f9750cd2696 100644 (file)
@@ -3,6 +3,7 @@
   "login": "obiwan.kenobi",
   "name": "Obiwan Kenobi",
   "email": "obiwan.kenobi@starwars.com",
+  "local": true,
   "scmAccounts": [
     "obiwan:github",
     "obiwan:bitbucket"
index f423f9ee855507a8485b501f17fbb4d8195d7bf1..b4bdfda4fe58594ac5afa5589eec2ade43bd79d3 100644 (file)
@@ -4,6 +4,7 @@
     "name": "Ada Lovelace",
     "email": "ada.lovelace@noteg.com",
     "scmAccounts": ["ada.lovelace"],
-    "active": true
+    "active": true,
+    "local": true
   }
 }
index 9f6ad704d55850de38805e11f603f97afa9f7c44..21b96a064caa22460aaa615f065c3c7d828f847a 100644 (file)
@@ -10,7 +10,8 @@
         "sonar-users",
         "sonar-administrators"
       ],
-      "tokensCount": 1
+      "tokensCount": 1,
+      "local": true
     },
     {
       "login": "sbrandhof",
@@ -24,7 +25,8 @@
       "groups": [
         "sonar-users"
       ],
-      "tokensCount": 3
+      "tokensCount": 3,
+      "local": false
     }
   ]
 }
index dc0f19fea55dafe07c7cbd15350e3f363d662950..977e85895ae81ea2c5ee243fd6bec00743c8b674 100644 (file)
@@ -23,7 +23,6 @@ import java.util.List;
 import org.assertj.core.data.Offset;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
@@ -43,6 +42,7 @@ import org.sonar.db.component.ComponentTesting;
 import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.db.metric.MetricDto;
 import org.sonar.db.metric.MetricTesting;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.exceptions.BadRequestException;
@@ -50,8 +50,6 @@ import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.exceptions.ServerException;
 import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndex;
 import org.sonar.server.user.index.UserIndexDefinition;
 import org.sonar.server.user.ws.UserJsonWriter;
 import org.sonar.server.ws.WsTester;
@@ -66,7 +64,6 @@ import static org.sonar.api.measures.Metric.ValueType.STRING;
 import static org.sonar.api.measures.Metric.ValueType.WORK_DUR;
 import static org.sonar.server.util.TypeValidationsTesting.newFullTypeValidations;
 
-
 public class CreateActionTest {
 
   private static final String DEFAULT_PROJECT_UUID = "project-uuid";
@@ -90,21 +87,20 @@ public class CreateActionTest {
 
   WsTester ws;
 
-  @BeforeClass
-  public static void setUpClass() throws Exception {
-    es.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, new UserDoc()
-      .setLogin("login")
-      .setName("Login")
-      .setEmail("login@login.com")
-      .setActive(true));
-  }
-
   @Before
   public void setUp() {
     ws = new WsTester(new CustomMeasuresWs(new CreateAction(dbClient, userSession, System2.INSTANCE, new CustomMeasureValidator(newFullTypeValidations()),
-      new CustomMeasureJsonWriter(new UserJsonWriter(userSession)), new UserIndex(es.client()), new ComponentFinder(dbClient))));
+      new CustomMeasureJsonWriter(new UserJsonWriter(userSession)), new ComponentFinder(dbClient))));
     db.truncateTables();
     userSession.login("login").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    db.getDbClient().userDao().insert(dbSession, new UserDto()
+      .setLogin("login")
+      .setName("Login")
+      .setEmail("login@login.com")
+      .setActive(true)
+      );
+    dbSession.commit();
   }
 
   @After
@@ -499,14 +495,14 @@ public class CreateActionTest {
     return ws.newPostRequest(CustomMeasuresWs.ENDPOINT, CreateAction.ACTION);
   }
 
-  private MetricDto insertMetric(ValueType metricType){
+  private MetricDto insertMetric(ValueType metricType) {
     MetricDto metric = MetricTesting.newMetricDto().setEnabled(true).setValueType(metricType.name()).setKey("metric-key");
     dbClient.metricDao().insert(dbSession, metric);
     dbSession.commit();
     return metric;
   }
 
-  private void insertProject(String projectUuid){
+  private void insertProject(String projectUuid) {
     dbClient.componentDao().insert(dbSession, ComponentTesting.newProjectDto(projectUuid).setKey(DEFAULT_PROJECT_KEY));
     dbSession.commit();
   }
index d2795519be3cbcf77f00d522c6c99c72c76dab06..aa2e19ca01467250e19af7b7cd8c8f0aa1ac0268 100644 (file)
@@ -26,7 +26,6 @@ import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.user.UserSession;
-import org.sonar.server.user.index.UserIndex;
 import org.sonar.server.ws.WsTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -42,8 +41,8 @@ public class CustomMeasuresWsTest {
     UserSession userSession = mock(UserSession.class);
     ws = new WsTester(new CustomMeasuresWs(
       new DeleteAction(dbClient, userSession),
-      new CreateAction(dbClient, userSession, System2.INSTANCE, mock(CustomMeasureValidator.class), mock(CustomMeasureJsonWriter.class), mock(UserIndex.class), mock(ComponentFinder.class)),
-      new UpdateAction(dbClient, userSession, System2.INSTANCE, mock(CustomMeasureValidator.class), mock(CustomMeasureJsonWriter.class), mock(UserIndex.class))
+      new CreateAction(dbClient, userSession, System2.INSTANCE, mock(CustomMeasureValidator.class), mock(CustomMeasureJsonWriter.class), mock(ComponentFinder.class)),
+      new UpdateAction(dbClient, userSession, System2.INSTANCE, mock(CustomMeasureValidator.class), mock(CustomMeasureJsonWriter.class))
     ));
   }
 
index 609262302a126faa2847560c77561d485ec70b83..052d91d92df1a2bf9c4bd47e8d9fdf87543debfc 100644 (file)
@@ -21,9 +21,7 @@ package org.sonar.server.measure.custom.ws;
 
 import java.util.Date;
 import org.apache.commons.lang.StringUtils;
-import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
@@ -38,22 +36,17 @@ import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDao;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
-import org.sonar.db.component.SnapshotDao;
 import org.sonar.db.component.SnapshotTesting;
-import org.sonar.db.measure.custom.CustomMeasureDao;
 import org.sonar.db.measure.custom.CustomMeasureDto;
-import org.sonar.db.metric.MetricDao;
 import org.sonar.db.metric.MetricDto;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndex;
 import org.sonar.server.user.index.UserIndexDefinition;
 import org.sonar.server.user.ws.UserJsonWriter;
 import org.sonar.server.ws.WsTester;
@@ -81,34 +74,25 @@ public class SearchActionTest {
   public static EsTester es = new EsTester().addDefinitions(new UserIndexDefinition(new Settings()));
 
   WsTester ws;
-  DbClient dbClient;
-  DbSession dbSession;
+  DbClient dbClient = db.getDbClient();
+  DbSession dbSession = db.getSession();
   ComponentDto defaultProject;
 
-  @BeforeClass
-  public static void setUpClass() throws Exception {
-    es.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, new UserDoc()
-      .setLogin("login")
-      .setName("Login")
-      .setEmail("login@login.com")
-      .setActive(true));
-  }
-
   @Before
   public void setUp() {
-    dbClient = new DbClient(db.database(), db.myBatis(), new CustomMeasureDao(), new ComponentDao(), new MetricDao(), new SnapshotDao());
-    dbSession = dbClient.openSession(false);
     db.truncateTables();
     CustomMeasureJsonWriter customMeasureJsonWriter = new CustomMeasureJsonWriter(new UserJsonWriter(userSessionRule));
-    UserIndex userIndex = new UserIndex(es.client());
-    ws = new WsTester(new CustomMeasuresWs(new SearchAction(dbClient, userIndex, customMeasureJsonWriter, userSessionRule, new ComponentFinder(dbClient))));
+    ws = new WsTester(new CustomMeasuresWs(new SearchAction(dbClient, customMeasureJsonWriter, userSessionRule, new ComponentFinder(dbClient))));
     defaultProject = insertDefaultProject();
     userSessionRule.login("login").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-  }
 
-  @After
-  public void tearDown() {
-    dbSession.close();
+    db.getDbClient().userDao().insert(dbSession, new UserDto()
+      .setLogin("login")
+      .setName("Login")
+      .setEmail("login@login.com")
+      .setActive(true)
+      );
+    dbSession.commit();
   }
 
   @Test
@@ -301,7 +285,8 @@ public class SearchActionTest {
   }
 
   private static MetricDto newCustomMetric(String metricKey) {
-    return newMetricDto().setEnabled(true).setUserManaged(true).setKey(metricKey).setDomain(metricKey + "-domain").setShortName(metricKey + "-name").setValueType(ValueType.STRING.name());
+    return newMetricDto().setEnabled(true).setUserManaged(true).setKey(metricKey).setDomain(metricKey + "-domain").setShortName(metricKey + "-name")
+      .setValueType(ValueType.STRING.name());
   }
 
   private CustomMeasureDto insertCustomMeasure(int id, MetricDto metric) {
index fafb7305e0fbfaface64fd0a8df7299ef0f74ef7..be6c67d4f67ec68fe0523fb886d8c3309686f03d 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.server.measure.custom.ws;
 
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
@@ -38,13 +37,12 @@ import org.sonar.db.component.ComponentTesting;
 import org.sonar.db.measure.custom.CustomMeasureDto;
 import org.sonar.db.metric.MetricDto;
 import org.sonar.db.metric.MetricTesting;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.ServerException;
 import org.sonar.server.exceptions.UnauthorizedException;
 import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.user.index.UserDoc;
-import org.sonar.server.user.index.UserIndex;
 import org.sonar.server.user.index.UserIndexDefinition;
 import org.sonar.server.user.ws.UserJsonWriter;
 import org.sonar.server.ws.WsTester;
@@ -59,7 +57,6 @@ import static org.sonar.server.measure.custom.ws.UpdateAction.PARAM_ID;
 import static org.sonar.server.measure.custom.ws.UpdateAction.PARAM_VALUE;
 import static org.sonar.server.util.TypeValidationsTesting.newFullTypeValidations;
 
-
 public class UpdateActionTest {
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
@@ -74,22 +71,20 @@ public class UpdateActionTest {
   System2 system = mock(System2.class);
   WsTester ws;
 
-  @BeforeClass
-  public static void setUpClass() throws Exception {
-    es.putDocuments(UserIndexDefinition.INDEX, UserIndexDefinition.TYPE_USER, new UserDoc()
-      .setLogin("login")
-      .setName("Login")
-      .setEmail("login@login.com")
-      .setActive(true));
-  }
-
   @Before
   public void setUp() {
     CustomMeasureValidator validator = new CustomMeasureValidator(newFullTypeValidations());
 
-    ws = new WsTester(new CustomMeasuresWs(new UpdateAction(dbClient, userSessionRule, system, validator, new CustomMeasureJsonWriter(new UserJsonWriter(userSessionRule)),
-      new UserIndex(es.client()))));
+    ws = new WsTester(new CustomMeasuresWs(new UpdateAction(dbClient, userSessionRule, system, validator, new CustomMeasureJsonWriter(new UserJsonWriter(userSessionRule)))));
     userSessionRule.login("login").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+    db.getDbClient().userDao().insert(dbSession, new UserDto()
+      .setLogin("login")
+      .setName("Login")
+      .setEmail("login@login.com")
+      .setActive(true)
+      );
+    dbSession.commit();
   }
 
   @Test
index 7f3671be323c4b09d7a2577aeb77ccf25805905d..7a902e3a544feb2adc3e67d2ea93c4f33f4eb591 100644 (file)
@@ -98,11 +98,10 @@ public class CreateActionTest {
 
     userIndexer = (UserIndexer) new UserIndexer(dbClient, esTester.client()).setEnabled(true);
     index = new UserIndex(esTester.client());
-    tester = new WsTester(new UsersWs(new CreateAction(index,
+    tester = new WsTester(new UsersWs(new CreateAction(dbClient,
       new UserUpdater(mock(NewUserNotifier.class), settings, dbClient, userIndexer, system2, mock(SecurityRealmFactory.class)),
       i18n, userSessionRule, new UserJsonWriter(userSessionRule))));
     controller = tester.controller("api/users");
-
   }
 
   @After
index e1c4cdd4c4784c0a46b6b067e8ee5de7499fa2ae..9522200a5dec5d9620081b429cae52e41ca239ff 100644 (file)
@@ -52,7 +52,6 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.sonar.db.user.UserTokenTesting.newUserToken;
 
-
 public class DeactivateActionTest {
 
   static final Settings settings = new Settings();
@@ -84,11 +83,10 @@ public class DeactivateActionTest {
 
     userIndexer = (UserIndexer) new UserIndexer(dbClient, esTester.client()).setEnabled(true);
     index = new UserIndex(esTester.client());
-    ws = new WsTester(new UsersWs(new DeactivateAction(index,
+    ws = new WsTester(new UsersWs(new DeactivateAction(
       new UserUpdater(mock(NewUserNotifier.class), settings, dbClient, userIndexer, system2, mock(SecurityRealmFactory.class)), userSessionRule,
       new UserJsonWriter(userSessionRule), dbClient)));
     controller = ws.controller("api/users");
-
   }
 
   @Test
index d9bf93548c78add844cbbd3b03ceedbe686883b8..86c377eb49f84066c8dfe91c7fb89666e2936455 100644 (file)
@@ -191,6 +191,7 @@ public class SearchActionTest {
         .setLogin(login)
         .setName(name)
         .setScmAccounts(scmAccounts)
+        .setLocal(true)
         .setUpdatedAt(createdAt)));
 
       users[index] = new UserDoc()
index f25623df45512fa71290ba466f06f2322017c80e..12de6a3be89b9e2e5ccff6f03d821fb2338a055c 100644 (file)
@@ -31,19 +31,15 @@ import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
-import org.sonar.db.user.GroupDao;
 import org.sonar.db.user.GroupDto;
-import org.sonar.db.user.GroupMembershipDao;
-import org.sonar.db.user.UserDao;
 import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserGroupDao;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.user.NewUserNotifier;
 import org.sonar.server.user.SecurityRealmFactory;
 import org.sonar.server.user.UserUpdater;
-import org.sonar.server.user.index.UserIndex;
 import org.sonar.server.user.index.UserIndexDefinition;
 import org.sonar.server.user.index.UserIndexer;
 import org.sonar.server.ws.WsTester;
@@ -56,43 +52,36 @@ public class UpdateActionTest {
 
   static final Settings settings = new Settings().setProperty("sonar.defaultGroup", "sonar-users");
 
+  System2 system2 = new System2();
+
   @Rule
-  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+  public DbTester dbTester = DbTester.create(system2);
   @ClassRule
   public static final EsTester esTester = new EsTester().addDefinitions(new UserIndexDefinition(settings));
   @Rule
   public final UserSessionRule userSessionRule = UserSessionRule.standalone().login("admin")
     .setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
 
-  WebService.Controller controller;
+  DbClient dbClient = dbTester.getDbClient();
 
-  WsTester tester;
+  DbSession session = dbTester.getSession();
 
-  UserIndex index;
+  WebService.Controller controller;
 
-  DbClient dbClient;
+  WsTester tester;
 
   UserIndexer userIndexer;
 
-  DbSession session;
-
   @Before
   public void setUp() {
     dbTester.truncateTables();
     esTester.truncateIndices();
 
-    System2 system2 = new System2();
-    UserDao userDao = new UserDao(dbTester.myBatis(), system2);
-    UserGroupDao userGroupDao = new UserGroupDao();
-    GroupDao groupDao = new GroupDao(system2);
-    dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), userDao, userGroupDao, groupDao, new GroupMembershipDao(dbTester.myBatis()));
-    session = dbClient.openSession(false);
-    groupDao.insert(session, new GroupDto().setName("sonar-users"));
+    dbClient.groupDao().insert(session, new GroupDto().setName("sonar-users"));
     session.commit();
 
     userIndexer = (UserIndexer) new UserIndexer(dbClient, esTester.client()).setEnabled(true);
-    index = new UserIndex(esTester.client());
-    tester = new WsTester(new UsersWs(new UpdateAction(index,
+    tester = new WsTester(new UsersWs(new UpdateAction(
       new UserUpdater(mock(NewUserNotifier.class), settings, dbClient, userIndexer, system2, mock(SecurityRealmFactory.class)), userSessionRule,
       new UserJsonWriter(userSessionRule), dbClient)));
     controller = tester.controller("api/users");
@@ -184,6 +173,13 @@ public class UpdateActionTest {
       .assertJson(getClass(), "update_scm_accounts.json");
   }
 
+  @Test(expected = NotFoundException.class)
+  public void fail_on_unknown_user() throws Exception {
+    tester.newPostRequest("api/users", "update")
+      .setParam("login", "john")
+      .execute();
+  }
+
   private void createUser() {
     dbClient.userDao().insert(session, new UserDto()
       .setEmail("john@email.com")
index bb6d4fa06e42408d094aea511fef984faf10c72f..58c2963e3896949e783eb587b2eafe57809c5e73 100644 (file)
@@ -41,10 +41,10 @@ public class UsersWsTest {
   @Before
   public void setUp() {
     WsTester tester = new WsTester(new UsersWs(
-      new CreateAction(mock(UserIndex.class), mock(UserUpdater.class), mock(I18n.class), userSessionRule, mock(UserJsonWriter.class)),
-      new UpdateAction(mock(UserIndex.class), mock(UserUpdater.class), userSessionRule, mock(UserJsonWriter.class), mock(DbClient.class)),
+      new CreateAction(mock(DbClient.class), mock(UserUpdater.class), mock(I18n.class), userSessionRule, mock(UserJsonWriter.class)),
+      new UpdateAction(mock(UserUpdater.class), userSessionRule, mock(UserJsonWriter.class), mock(DbClient.class)),
       new CurrentAction(userSessionRule, mock(org.sonar.db.DbClient.class)),
-      new DeactivateAction(mock(UserIndex.class), mock(UserUpdater.class), userSessionRule, mock(UserJsonWriter.class), mock(DbClient.class)),
+      new DeactivateAction(mock(UserUpdater.class), userSessionRule, mock(UserJsonWriter.class), mock(DbClient.class)),
       new ChangePasswordAction(mock(UserUpdater.class), userSessionRule),
       new SearchAction(mock(UserIndex.class), mock(DbClient.class), mock(UserJsonWriter.class))));
     controller = tester.controller("api/users");
index 0feda7c9c1cdc10449ea7300dfb07f06123c249e..1e04312feaaf2010303d4db153b49a7591eb85d4 100644 (file)
@@ -4,6 +4,7 @@
     "name": "John",
     "email": "john@email.com",
     "scmAccounts": ["jn"],
-    "active": true
+    "active": true,
+    "local": true
   }
 }
index 43f484c95a41a12c522b7e337c325934989b973c..b9b4bd50809b6317d18bfb10a88b920dff8f9991 100644 (file)
@@ -4,7 +4,8 @@
     "name": "John",
     "email": "john@email.com",
     "scmAccounts": ["jn"],
-    "active": true
+    "active": true,
+    "local": true
   },
   "infos": [
     {
index 97cd22324f8fc4e6dddb4e70ffaecf2c0c295a26..f5e9eac1f29e6e11028be64a498d8e9021023918 100644 (file)
@@ -3,6 +3,7 @@
     "login": "john",
     "name": "John",
     "scmAccounts": [],
-    "active": false
+    "active": false,
+    "local": true
   }
 }
index 53f48b5066c88526ad01c3b404fe8970a875fa51..960c322ab49e7430e983e86bd5bb39b21e6f5f44 100644 (file)
@@ -10,7 +10,8 @@
       "scmAccounts": [
         "user-0"
       ],
-      "tokensCount": 0
+      "tokensCount": 0,
+      "local": true
     },
     {
       "login": "user-1",
@@ -19,7 +20,8 @@
       "scmAccounts": [
         "user-1"
       ],
-      "tokensCount": 1
+      "tokensCount": 1,
+      "local": true
     },
     {
       "login": "user-2",
@@ -28,7 +30,8 @@
       "scmAccounts": [
         "user-2"
       ],
-      "tokensCount": 2
+      "tokensCount": 2,
+      "local": true
     },
     {
       "login": "user-3",
@@ -37,7 +40,8 @@
       "scmAccounts": [
         "user-3"
       ],
-      "tokensCount": 3
+      "tokensCount": 3,
+      "local": true
     },
     {
       "login": "user-4",
@@ -46,7 +50,8 @@
       "scmAccounts": [
         "user-4"
       ],
-      "tokensCount": 4
+      "tokensCount": 4,
+      "local": true
     }
   ]
 }
index 3ea6c0bc02016416a9c37d1dd6918f1edeebe659..0ecf67664bb68491f5da95ad5c6884505a838396 100644 (file)
@@ -9,7 +9,8 @@
       "email": "user-0@mail.com",
       "scmAccounts": [
         "user-0"
-      ]
+      ],
+      "local": true
     },
     {
       "login": "user-1",
@@ -17,7 +18,8 @@
       "email": "user-1@mail.com",
       "scmAccounts": [
         "user-1"
-      ]
+      ],
+      "local": true
     },
     {
       "login": "user-2",
@@ -25,7 +27,8 @@
       "email": "user-2@mail.com",
       "scmAccounts": [
         "user-2"
-      ]
+      ],
+      "local": true
     },
     {
       "login": "user-3",
@@ -33,7 +36,8 @@
       "email": "user-3@mail.com",
       "scmAccounts": [
         "user-3"
-      ]
+      ],
+      "local": true
     },
     {
       "login": "user-4",
@@ -41,7 +45,8 @@
       "email": "user-4@mail.com",
       "scmAccounts": [
         "user-4"
-      ]
+      ],
+      "local": true
     }
   ]
 }
index 143a32adafe947a81cf77aaf73710cc6ecfd0a33..43af76c6b1104dfed82c0ca64b0ce8ebb2728d93 100644 (file)
@@ -9,7 +9,8 @@
       "email": "user-5@mail.com",
       "scmAccounts": [
         "user-5"
-      ]
+      ],
+      "local": true
     },
     {
       "login": "user-6",
@@ -17,7 +18,8 @@
       "email": "user-6@mail.com",
       "scmAccounts": [
         "user-6"
-      ]
+      ],
+      "local": true
     },
     {
       "login": "user-7",
@@ -25,7 +27,8 @@
       "email": "user-7@mail.com",
       "scmAccounts": [
         "user-7"
-      ]
+      ],
+      "local": true
     },
     {
       "login": "user-8",
@@ -33,7 +36,8 @@
       "email": "user-8@mail.com",
       "scmAccounts": [
         "user-8"
-      ]
+      ],
+      "local": true
     },
     {
       "login": "user-9",
@@ -41,7 +45,8 @@
       "email": "user-9@mail.com",
       "scmAccounts": [
         "user-9"
-      ]
+      ],
+      "local": true
     }
   ]
 }
index 1fc903157128b15e0f7e552f96e775ccf2b7c772..6839d14f0f0d60ac0f367633e46eddbec6f3d73b 100644 (file)
@@ -9,7 +9,8 @@
       "email": "user@mail.com",
       "active": true,
       "scmAccounts": ["user1"],
-      "tokensCount": 0
+      "tokensCount": 0,
+      "local": true
     }
   ]
 }
index 6b2d6543f65393ad1b5e3c8310b3cb1304a80c66..a0a2c157a7b409632fe4f5726da771e419ee9fbf 100644 (file)
@@ -10,7 +10,8 @@
       "scmAccounts": [
         "user-0"
       ],
-      "groups": ["sonar-admins", "sonar-users"]
+      "groups": ["sonar-admins", "sonar-users"],
+      "local": true
     }
   ]
 }
index 32461ebcf9a83dafbc26376a07d3bdc0ee2412d7..01183a602fee1135c88c06f8d939a55c4c50c165 100644 (file)
@@ -6,6 +6,7 @@
     "active": true,
     "scmAccounts": [
       "jn"
-    ]
+    ],
+    "local": true
   }
 }
index f0d7b9297ee541f043c753a7a6178620a739db34..74c6d7e9ceaff2ef2911f24bab3275f022b845c7 100644 (file)
@@ -6,6 +6,7 @@
     "active": true,
     "scmAccounts": [
       "jn"
-    ]
+    ],
+    "local": true
   }
 }
index 7293894355708b4331fdf3dd71c89105c7e07e40..4e5717b8cc25527eb84510b842d0a6bab7c6831c 100644 (file)
@@ -4,6 +4,7 @@
     "name": "Jon Snow",
     "email": "jon.snow@thegreatw.all",
     "scmAccounts": ["jon.snow"],
-    "active": true
+    "active": true,
+    "local": true
   }
 }
index d5119727b487e38707846afeee762aea2ca645ff..5d0eada9cc7f1af3232df65b9ed6137685f5e12b 100644 (file)
 package org.sonar.db.user;
 
 import com.google.common.base.Function;
+import com.google.common.base.Predicates;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import org.apache.ibatis.session.SqlSession;
@@ -33,6 +36,8 @@ import org.sonar.db.DbSession;
 import org.sonar.db.MyBatis;
 import org.sonar.db.RowNotFoundException;
 
+import static com.google.common.collect.FluentIterable.from;
+
 public class UserDao implements Dao {
 
   private final MyBatis mybatis;
@@ -94,6 +99,17 @@ public class UserDao implements Dao {
     }
   }
 
+  /**
+   * Gets a list users by their logins. The result does NOT contain {@code null} values for users not found, so
+   * the size of result may be less than the number of keys.
+   * A single user is returned if input keys contain multiple occurrences of a key.
+   * <p>Contrary to {@link #selectByLogins(DbSession, Collection)}, results are in the same order as input keys.</p>
+   */
+  public List<UserDto> selectByOrderedLogins(DbSession session, Collection<String> logins) {
+    List<UserDto> unordered = selectByLogins(session, logins);
+    return from(logins).transform(new LoginToUser(unordered)).filter(Predicates.notNull()).toList();
+  }
+
   private static class SelectByLogins implements Function<List<String>, List<UserDto>> {
     private final UserMapper mapper;
 
@@ -188,4 +204,19 @@ public class UserDao implements Dao {
   protected UserMapper mapper(DbSession session) {
     return session.getMapper(UserMapper.class);
   }
+
+  private static class LoginToUser implements Function<String, UserDto> {
+    private final Map<String, UserDto> map = new HashMap<>();
+
+    private LoginToUser(Collection<UserDto> unordered) {
+      for (UserDto dto : unordered) {
+        map.put(dto.getLogin(), dto);
+      }
+    }
+
+    @Override
+    public UserDto apply(@Nonnull String login) {
+      return map.get(login);
+    }
+  }
 }
index 09f42002021157ec898de6715fdf98009907e03f..6afef4c64b3e751284ad830c5dee7a9d4bf67c11 100644 (file)
@@ -51,6 +51,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.sonar.db.user.GroupMembershipQuery.IN;
 import static org.sonar.db.user.GroupMembershipQuery.builder;
+import static org.sonar.db.user.UserTesting.newUserDto;
 
 
 public class UserDaoTest {
@@ -112,6 +113,21 @@ public class UserDaoTest {
     assertThat(users).isEmpty();
   }
 
+  @Test
+  public void selectByOrderedLogins() {
+    underTest.insert(session, newUserDto().setLogin("U1").setActive(true));
+    underTest.insert(session, newUserDto().setLogin("U2").setActive(true));
+    session.commit();
+
+    Iterable<UserDto> users = underTest.selectByOrderedLogins(session, asList("U1", "U2", "U3"));
+    assertThat(users).extracting("login").containsExactly("U1", "U2");
+
+    users = underTest.selectByOrderedLogins(session, asList("U2", "U3", "U1"));
+    assertThat(users).extracting("login").containsExactly("U2", "U1");
+
+    assertThat(underTest.selectByOrderedLogins(session, Collections.<String>emptyList())).isEmpty();
+  }
+
   @Test
   public void selectUsersByQuery_all() {
     db.prepareDbUnit(getClass(), "selectUsersByQuery.xml");
@@ -447,7 +463,7 @@ public class UserDaoTest {
   }
 
   private UserDto newUser(boolean active){
-    UserDto dto = UserTesting.newUserDto().setActive(active);
+    UserDto dto = newUserDto().setActive(active);
     underTest.insert(session, dto);
     return dto;
   }