Skip to content

Commit

Permalink
[SYNCOPE-1779] Restore querying by values with underscore in equals e…
Browse files Browse the repository at this point in the history
…xpressions (#561)
  • Loading branch information
ilgrosso committed Dec 5, 2023
1 parent a0d2dda commit 2d2e5ed
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,10 @@ protected static AttrCond createAttrCond(final String schema) {
protected static String getValue(final SearchCondition<SearchBean> sc) {
String value = SearchUtils.toSqlWildcardString(
URLDecoder.decode(sc.getStatement().getValue().toString(), StandardCharsets.UTF_8), false);
if (value.indexOf('%') == -1) {
value = value.replaceAll("\\\\_", "_");
}

// see SYNCOPE-1321
if (TIMEZONE.matcher(value).matches()) {
char[] valueAsArray = value.toCharArray();
valueAsArray[valueAsArray.length - 5] = '+';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,19 @@ public void issueSYNCOPE1779() {
String fiql = new UserFiqlSearchConditionBuilder().is("username").equalToIgnoreCase("ros_*").query();
assertEquals("username=~ros_*", fiql);

AttrCond attrCond = new AnyCond(AttrCond.Type.ILIKE);
attrCond.setSchema("username");
attrCond.setExpression("ros\\_%");
SearchCond leaf = SearchCond.getLeaf(attrCond);
AnyCond anyCond = new AnyCond(AttrCond.Type.ILIKE);
anyCond.setSchema("username");
anyCond.setExpression("ros\\_%");
SearchCond leaf = SearchCond.getLeaf(anyCond);

assertEquals(leaf, SearchCondConverter.convert(VISITOR, fiql));

fiql = "name==_018c34a9-f86b-75cf-855b-a3915cc5ff44";

anyCond = new AnyCond(AttrCond.Type.EQ);
anyCond.setSchema("name");
anyCond.setExpression("_018c34a9-f86b-75cf-855b-a3915cc5ff44");
leaf = SearchCond.getLeaf(anyCond);

assertEquals(leaf, SearchCondConverter.convert(VISITOR, fiql));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ protected StringBuilder buildDescendantQuery(
append(')');

if (keyword != null) {
queryString.append(" AND LOWER(e.name) LIKE ?").append(setParameter(parameters, keyword));
queryString.append(" AND LOWER(e.name) LIKE ?").
append(setParameter(parameters, "%" + keyword.replaceAll("_", "\\\\_").toLowerCase() + "%"));
}

return queryString;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
Expand Down Expand Up @@ -61,6 +62,21 @@ public static String getAuditIndex(final String domain) {
return domain.toLowerCase() + "_audit";
}

protected static final char[] ELASTICSEARCH_REGEX_CHARS = new char[] {
'.', '?', '+', '*', '|', '{', '}', '[', ']', '(', ')', '"', '\\', '&' };

public static String escapeForLikeRegex(final char c) {
StringBuilder output = new StringBuilder();

if (ArrayUtils.contains(ELASTICSEARCH_REGEX_CHARS, c)) {
output.append('\\');
}

output.append(c);

return output.toString();
}

protected final UserDAO userDAO;

protected final GroupDAO groupDAO;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.syncope.common.lib.SyncopeClientException;
Expand Down Expand Up @@ -88,21 +87,6 @@
*/
public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {

protected static final char[] ELASTICSEARCH_REGEX_CHARS = new char[] {
'.', '?', '+', '*', '|', '{', '}', '[', ']', '(', ')', '"', '\\', '&' };

protected static String escapeForLikeRegex(final char c) {
StringBuilder output = new StringBuilder();

if (ArrayUtils.contains(ELASTICSEARCH_REGEX_CHARS, c)) {
output.append('\\');
}

output.append(c);

return output.toString();
}

protected final ElasticsearchClient client;

protected final int indexMaxResultWindow;
Expand Down Expand Up @@ -565,7 +549,7 @@ protected Query fillAttrQuery(
append(Character.toUpperCase(c)).
append(']');
} else {
output.append(escapeForLikeRegex(c));
output.append(ElasticsearchUtils.escapeForLikeRegex(c));
}
}
query = new Query.Builder().regexp(QueryBuilders.regexp().
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,24 @@ protected Query buildDescendantQuery(final String base, final String keyword) {
return prefix;
}

StringBuilder output = new StringBuilder();
for (char c : keyword.toLowerCase().toCharArray()) {
if (c == '%') {
output.append(".*");
} else if (Character.isLetter(c)) {
output.append('[').
append(c).
append(Character.toUpperCase(c)).
append(']');
} else {
output.append(ElasticsearchUtils.escapeForLikeRegex(c));
}
}

return new Query.Builder().bool(QueryBuilders.bool().must(
prefix,
new Query.Builder().wildcard(QueryBuilders.wildcard().
field("name").value(keyword.replace("%", "*").toLowerCase()).build()).
new Query.Builder().regexp(QueryBuilders.regexp().
field("name").value(output.toString()).build()).
build()).build()).
build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
Expand Down Expand Up @@ -61,6 +62,21 @@ public static String getAuditIndex(final String domain) {
return domain.toLowerCase() + "_audit";
}

protected static final char[] ELASTICSEARCH_REGEX_CHARS = new char[] {
'.', '?', '+', '*', '|', '{', '}', '[', ']', '(', ')', '"', '\\', '&' };

public static String escapeForLikeRegex(final char c) {
StringBuilder output = new StringBuilder();

if (ArrayUtils.contains(ELASTICSEARCH_REGEX_CHARS, c)) {
output.append('\\');
}

output.append(c);

return output.toString();
}

protected final UserDAO userDAO;

protected final GroupDAO groupDAO;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.syncope.common.lib.SyncopeClientException;
Expand Down Expand Up @@ -88,21 +87,6 @@
*/
public class OpenSearchAnySearchDAO extends AbstractAnySearchDAO {

protected static final char[] OPENSEARCH_REGEX_CHARS = new char[] {
'.', '?', '+', '*', '|', '{', '}', '[', ']', '(', ')', '"', '\\', '&' };

protected static String escapeForLikeRegex(final char c) {
StringBuilder output = new StringBuilder();

if (ArrayUtils.contains(OPENSEARCH_REGEX_CHARS, c)) {
output.append('\\');
}

output.append(c);

return output.toString();
}

protected final OpenSearchClient client;

protected final int indexMaxResultWindow;
Expand Down Expand Up @@ -565,7 +549,7 @@ protected Query fillAttrQuery(
append(Character.toUpperCase(c)).
append(']');
} else {
output.append(escapeForLikeRegex(c));
output.append(OpenSearchUtils.escapeForLikeRegex(c));
}
}
query = new Query.Builder().regexp(QueryBuilders.regexp().
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,24 @@ protected Query buildDescendantQuery(final String base, final String keyword) {
return prefix;
}

StringBuilder output = new StringBuilder();
for (char c : keyword.toLowerCase().toCharArray()) {
if (c == '%') {
output.append(".*");
} else if (Character.isLetter(c)) {
output.append('[').
append(c).
append(Character.toUpperCase(c)).
append(']');
} else {
output.append(OpenSearchUtils.escapeForLikeRegex(c));
}
}

return new Query.Builder().bool(QueryBuilders.bool().must(
prefix,
new Query.Builder().wildcard(QueryBuilders.wildcard().
field("name").value(keyword.replace("%", "*").toLowerCase()).build()).
new Query.Builder().regexp(QueryBuilders.regexp().
field("name").value(output.toString()).build()).
build()).build()).
build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,28 @@ public void issueSYNCOPE1779() {
assertEquals(2, users.getResult().size());

users.getResult().forEach(u -> USER_SERVICE.delete(u.getKey()));

// 4. create any object with underscore
AnyObjectTO printer = createAnyObject(
new AnyObjectCR.Builder(SyncopeConstants.ROOT_REALM, PRINTER, "_syncope1779").build()).getEntity();

// 5. search for printer
if (IS_EXT_SEARCH_ENABLED) {
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
// ignore
}
}

PagedResult<AnyObjectTO> printers = ANY_OBJECT_SERVICE.search(
new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
fiql("$type==PRINTER;name==_syncope1779").
build());
assertEquals(1, printers.getResult().size());
assertEquals(printer.getKey(), printers.getResult().get(0).getKey());

printers.getResult().forEach(u -> ANY_OBJECT_SERVICE.delete(u.getKey()));
}

@Test
Expand Down

0 comments on commit 2d2e5ed

Please sign in to comment.