]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8059 WS api/user_groups/users searches users by name, login and email 1616/head
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Wed, 1 Feb 2017 17:46:37 +0000 (18:46 +0100)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Thu, 2 Feb 2017 15:09:52 +0000 (16:09 +0100)
server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UsersAction.java
server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UsersActionTest.java
server/sonar-server/src/test/resources/org/sonar/server/usergroups/ws/UsersActionTest/all.json
server/sonar-server/src/test/resources/org/sonar/server/usergroups/ws/UsersActionTest/all_ada.json
sonar-db/src/main/java/org/sonar/db/user/UserMembershipQuery.java
sonar-db/src/main/resources/org/sonar/db/user/GroupMembershipMapper.xml
sonar-db/src/test/java/org/sonar/db/user/GroupMembershipDaoTest.java
sonar-db/src/test/resources/org/sonar/db/user/GroupMembershipDaoTest/shared_plus_empty_group.xml

index 9f74f59add6dca09a34682442ede4a2acd62dcdd..126f26871782bb698db8d0eefd3496808f91afd9 100644 (file)
@@ -56,35 +56,6 @@ public class UsersAction implements UserGroupsWsAction {
     this.support = support;
   }
 
-  private static void writeMembers(JsonWriter json, List<UserMembershipDto> users) {
-    json.name("users").beginArray();
-    for (UserMembershipDto user : users) {
-      json.beginObject()
-        .prop(FIELD_LOGIN, user.getLogin())
-        .prop(FIELD_NAME, user.getName())
-        .prop(FIELD_SELECTED, user.getGroupId() != null)
-        .endObject();
-    }
-    json.endArray();
-  }
-
-  private static void writePaging(JsonWriter json, Paging paging) {
-    json.prop(Param.PAGE, paging.pageIndex())
-      .prop(Param.PAGE_SIZE, paging.pageSize())
-      .prop("total", paging.total());
-  }
-
-  private static String getMembership(String selected) {
-    SelectionMode selectionMode = SelectionMode.fromParam(selected);
-    String membership = GroupMembershipQuery.ANY;
-    if (SelectionMode.SELECTED == selectionMode) {
-      membership = GroupMembershipQuery.IN;
-    } else if (SelectionMode.DESELECTED == selectionMode) {
-      membership = GroupMembershipQuery.OUT;
-    }
-    return membership;
-  }
-
   @Override
   public void define(NewController context) {
     NewAction action = context.createAction("users")
@@ -128,4 +99,33 @@ public class UsersAction implements UserGroupsWsAction {
       json.endObject().close();
     }
   }
+
+  private static void writeMembers(JsonWriter json, List<UserMembershipDto> users) {
+    json.name("users").beginArray();
+    for (UserMembershipDto user : users) {
+      json.beginObject()
+        .prop(FIELD_LOGIN, user.getLogin())
+        .prop(FIELD_NAME, user.getName())
+        .prop(FIELD_SELECTED, user.getGroupId() != null)
+        .endObject();
+    }
+    json.endArray();
+  }
+
+  private static void writePaging(JsonWriter json, Paging paging) {
+    json.prop(Param.PAGE, paging.pageIndex())
+      .prop(Param.PAGE_SIZE, paging.pageSize())
+      .prop("total", paging.total());
+  }
+
+  private static String getMembership(String selected) {
+    SelectionMode selectionMode = SelectionMode.fromParam(selected);
+    String membership = GroupMembershipQuery.ANY;
+    if (SelectionMode.SELECTED == selectionMode) {
+      membership = GroupMembershipQuery.IN;
+    } else if (SelectionMode.DESELECTED == selectionMode) {
+      membership = GroupMembershipQuery.OUT;
+    }
+    return membership;
+  }
 }
index 1adda704f6ad311c3e4b6749029cc6b3c2f46783..99e92aa08a5cb92ad013cf31c822ae45454a4bf4 100644 (file)
@@ -116,7 +116,7 @@ public class UsersActionTest {
   @Test
   public void return_members_by_group_id() throws Exception {
     GroupDto group = db.users().insertGroup();
-    UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada").setName("Ada Lovelace"));
+    UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada.login").setName("Ada Lovelace"));
     db.users().insertMember(group, user1);
     db.users().insertUser(newUserDto().setLogin("grace").setName("Grace Hopper"));
     loginAsAdminOnDefaultOrganization();
@@ -132,7 +132,7 @@ public class UsersActionTest {
   public void references_group_by_its_name() throws Exception {
     OrganizationDto org = db.organizations().insert();
     GroupDto group = db.users().insertGroup(org, "the-group");
-    UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada").setName("Ada Lovelace"));
+    UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada.login").setName("Ada Lovelace"));
     db.users().insertMember(group, user1);
     db.users().insertUser(newUserDto().setLogin("grace").setName("Grace Hopper"));
     loginAsAdmin(org);
@@ -148,7 +148,7 @@ public class UsersActionTest {
   @Test
   public void references_group_in_default_organization_by_its_name() throws Exception {
     GroupDto group = db.users().insertGroup();
-    UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada").setName("Ada Lovelace"));
+    UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada.login").setName("Ada Lovelace"));
     db.users().insertMember(group, user1);
     db.users().insertUser(newUserDto().setLogin("grace").setName("Grace Hopper"));
     loginAsAdminOnDefaultOrganization();
@@ -169,9 +169,7 @@ public class UsersActionTest {
     db.users().insertMember(group, graceHopper);
     loginAsAdminOnDefaultOrganization();
 
-    String response = newUsersRequest()
-      .setParam(PARAM_GROUP_ID, group.getId().toString())
-      .execute().outputAsString();
+    String response = newUsersRequest().setParam(PARAM_GROUP_ID, group.getId().toString()).execute().outputAsString();
 
     assertThat(response).contains("Ada Lovelace", "Grace Hopper");
   }
@@ -236,10 +234,10 @@ public class UsersActionTest {
   }
 
   @Test
-  public void filtering() throws Exception {
+  public void filtering_by_name_email_and_login() throws Exception {
     GroupDto group = db.users().insertGroup();
-    UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada").setName("Ada Lovelace"));
-    db.users().insertUser(newUserDto().setLogin("grace").setName("Grace Hopper"));
+    UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada.login").setName("Ada Lovelace").setEmail("ada@email.com"));
+    db.users().insertUser(newUserDto().setLogin("grace").setName("Grace Hopper").setEmail("grace@hopper.com"));
     db.users().insertMember(group, user1);
     loginAsAdminOnDefaultOrganization();
 
@@ -250,9 +248,18 @@ public class UsersActionTest {
       .execute()
       .assertJson(getClass(), "all.json");
 
-    newUsersRequest()
-      .setParam("id", group.getId().toString())
-      .setParam("q", "love")
+    newUsersRequest().setParam("id", group.getId().toString())
+      .setParam("q", ".logi")
+      .execute()
+      .assertJson(getClass(), "all_ada.json");
+
+    newUsersRequest().setParam("id", group.getId().toString())
+      .setParam("q", "OvE")
+      .execute()
+      .assertJson(getClass(), "all_ada.json");
+
+    newUsersRequest().setParam("id", group.getId().toString())
+      .setParam("q", "mail")
       .execute()
       .assertJson(getClass(), "all_ada.json");
   }
index 8f0e903fdb967917609246b61af59a5dae7672e7..b0d9576da28f68335c5b99eb1060b9ac081d3897 100644 (file)
@@ -2,7 +2,7 @@
   "p": 1,
   "total": 2,
   "users": [
-    {"login": "ada", "name": "Ada Lovelace", "selected": true},
+    {"login": "ada.login", "name": "Ada Lovelace", "selected": true},
     {"login": "grace", "name": "Grace Hopper", "selected": false}
   ]
-}
\ No newline at end of file
+}
index cb5b2a66035b25e47a49008cf011ced55aa1077b..802c557b1fa8ce46ac82f553e764f1d7c2a9843f 100644 (file)
@@ -2,6 +2,10 @@
   "p": 1,
   "total": 1,
   "users": [
-    {"login": "ada", "name": "Ada Lovelace", "selected": true}
+    {
+      "login": "ada.login",
+      "name": "Ada Lovelace",
+      "selected": true
+    }
   ]
-}
\ No newline at end of file
+}
index 7847fe265c4b46bd86dfcc1c33058e9487e5c856..7bcb8920a968a6da3eff629497dc80a6ada30d8b 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.db.user;
 
 import com.google.common.collect.ImmutableSet;
+import java.util.Locale;
 import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
@@ -28,6 +29,8 @@ import org.apache.commons.lang.StringUtils;
 import static com.google.common.base.MoreObjects.firstNonNull;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.sonar.db.DatabaseUtils.buildLikeValue;
+import static org.sonar.db.WildcardPosition.BEFORE_AND_AFTER;
 
 public class UserMembershipQuery {
 
@@ -46,6 +49,7 @@ public class UserMembershipQuery {
 
   // for internal use in MyBatis
   final String memberSearchSql;
+  final String memberSearchSqlLowercase;
 
   // max results per page
   private final int pageSize;
@@ -57,22 +61,12 @@ public class UserMembershipQuery {
     this.groupId = builder.groupId;
     this.membership = builder.membership;
     this.memberSearch = builder.memberSearch;
-    this.memberSearchSql = memberSearchToSql(memberSearch);
-
+    this.memberSearchSql = memberSearch == null ? null : buildLikeValue(memberSearch, BEFORE_AND_AFTER);
+    this.memberSearchSqlLowercase = memberSearchSql == null ? null : memberSearchSql.toLowerCase(Locale.ENGLISH);
     this.pageSize = builder.pageSize;
     this.pageIndex = builder.pageIndex;
   }
 
-  private String memberSearchToSql(@Nullable String s) {
-    String sql = null;
-    if (s != null) {
-      sql = StringUtils.replace(StringUtils.upperCase(s), "%", "/%");
-      sql = StringUtils.replace(sql, "_", "/_");
-      sql = "%" + sql + "%";
-    }
-    return sql;
-  }
-
   public long groupId() {
     return groupId;
   }
@@ -83,7 +77,7 @@ public class UserMembershipQuery {
   }
 
   /**
-   * Search for users names/logins containing a given string
+   * Search for users email, login and name containing a given string
    */
   @CheckForNull
   public String memberSearch() {
index 73d7ee7fa54f4213043a0d9eb28608b62986f403..12ba914eeedbcd0c6c7cc961e63374b6d0fb2d3e 100644 (file)
         </when>
       </choose>
       <if test="query.memberSearch() != null">
-        AND ((UPPER(u.login) LIKE #{query.memberSearchSql} ESCAPE '/') OR (UPPER(u.name) LIKE #{query.memberSearchSql}
-        ESCAPE '/'))
+        AND (
+          lower(u.name) like #{query.memberSearchSqlLowercase} ESCAPE '/'
+          or u.login like #{query.memberSearchSql} ESCAPE '/'
+          or u.email like #{query.memberSearchSql} ESCAPE '/' )
       </if>
       AND u.active=${_true}
     </where>
index d2842e9967fec11da6b8682b9cd1506b40e1ed99..aa144a4791635cc6aa6b85101607f13b9e8dc38d 100644 (file)
@@ -126,7 +126,7 @@ public class GroupMembershipDaoTest {
     List<UserMembershipDto> result = underTest.selectMembers(dbTester.getSession(), UserMembershipQuery.builder().groupId(100L).memberSearch("admin").build(), 0, 10);
     assertThat(result).hasSize(2);
 
-    assertThat(result.get(0).getName()).isEqualTo("Admin");
+    assertThat(result.get(0).getName()).isEqualTo("Admin name");
     assertThat(result.get(1).getName()).isEqualTo("Not Admin");
 
     result = underTest.selectMembers(dbTester.getSession(), UserMembershipQuery.builder().groupId(100L).memberSearch("not").build(), 0, 10);
@@ -134,15 +134,18 @@ public class GroupMembershipDaoTest {
   }
 
   @Test
-  public void search_by_login_or_name_with_capitalization() {
+  public void search_by_login_name_or_email() {
     dbTester.prepareDbUnit(getClass(), "shared_plus_empty_group.xml");
 
-    List<UserMembershipDto> result = underTest.selectMembers(dbTester.getSession(), UserMembershipQuery.builder().groupId(100L).memberSearch("admin").build(), 0, 10);
-    assertThat(result).hasSize(2);
+    // search is case insensitive only on name
+    List<UserMembershipDto> result = underTest.selectMembers(dbTester.getSession(), UserMembershipQuery.builder().groupId(100L).memberSearch("NaMe").build(), 0, 10);
+    assertThat(result).hasSize(1);
 
-    result = underTest.selectMembers(dbTester.getSession(), UserMembershipQuery.builder().groupId(100L).memberSearch("AdMiN").build(), 0, 10);
-    assertThat(result).hasSize(2);
+    result = underTest.selectMembers(dbTester.getSession(), UserMembershipQuery.builder().groupId(100L).memberSearch("login").build(), 0, 10);
+    assertThat(result).hasSize(1);
 
+    result = underTest.selectMembers(dbTester.getSession(), UserMembershipQuery.builder().groupId(100L).memberSearch("email").build(), 0, 10);
+    assertThat(result).hasSize(1);
   }
 
   @Test
@@ -151,7 +154,7 @@ public class GroupMembershipDaoTest {
 
     List<UserMembershipDto> result = underTest.selectMembers(dbTester.getSession(), UserMembershipQuery.builder().groupId(100L).build(), 0, 10);
     assertThat(result).hasSize(2);
-    assertThat(result.get(0).getName()).isEqualTo("Admin");
+    assertThat(result.get(0).getName()).isEqualTo("Admin name");
     assertThat(result.get(1).getName()).isEqualTo("Not Admin");
   }
 
@@ -161,7 +164,7 @@ public class GroupMembershipDaoTest {
 
     List<UserMembershipDto> result = underTest.selectMembers(dbTester.getSession(), UserMembershipQuery.builder().groupId(100L).build(), 0, 2);
     assertThat(result).hasSize(2);
-    assertThat(result.get(0).getName()).isEqualTo("Admin");
+    assertThat(result.get(0).getName()).isEqualTo("Admin name");
     assertThat(result.get(1).getName()).isEqualTo("Not Admin");
 
     result = underTest.selectMembers(dbTester.getSession(), UserMembershipQuery.builder().groupId(100L).build(), 1, 2);
index 3d65a44cbad261b0673bd629b74dfa5899046da5..a475bba797f0c68b90255676d0f7cf7627afdaf7 100644 (file)
                 group_id="101"/>
 
   <users id="200"
-         login="admin"
-         name="Admin"
+         login="admin login"
+         name="Admin name"
+         email="admin@email.com"
          active="[true]"
          is_root="[false]"/>
   <users id="201"
          login="not.admin"
          name="Not Admin"
+         email="not admin"
          active="[true]"
          is_root="[false]"/>
   <users id="202"