You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2022/05/24 06:37:50 UTC
[syncope] branch master updated: [SYNCOPE-1679] Adding support for $auxClasses (#347)
This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/master by this push:
new ccb30f53bd [SYNCOPE-1679] Adding support for $auxClasses (#347)
ccb30f53bd is described below
commit ccb30f53bdb9bf46daafb1052495149aeefee648
Author: Francesco Chicchiriccò <il...@users.noreply.github.com>
AuthorDate: Tue May 24 08:37:46 2022 +0200
[SYNCOPE-1679] Adding support for $auxClasses (#347)
---
.../console/panels/search/AbstractSearchPanel.java | 20 +++++-
.../panels/search/AnyObjectSearchPanel.java | 1 +
.../console/panels/search/GroupSearchPanel.java | 1 +
.../client/console/panels/search/SearchClause.java | 1 +
.../console/panels/search/SearchClausePanel.java | 13 +++-
.../client/console/panels/search/SearchUtils.java | 11 ++++
.../console/panels/search/UserSearchPanel.java | 5 +-
.../search/AbstractFiqlSearchConditionBuilder.java | 40 +++++++++---
.../syncope/common/lib/search/SpecialAttr.java | 6 +-
.../common/lib/search/SyncopeFiqlParser.java | 20 ++----
.../lib/search/SyncopeFiqlSearchCondition.java | 1 -
.../syncope/common/lib/search/SyncopeProperty.java | 50 +++++++++++++--
.../persistence/api/dao/search/AuxClassCond.java | 74 ++++++++++++++++++++++
.../persistence/api/search/SearchCondVisitor.java | 7 ++
.../api/search/FilterConverterTest.java | 20 ++++++
.../api/search/SearchCondConverterTest.java | 13 ++++
.../persistence/jpa/dao/PGJPAJSONAnySearchDAO.java | 25 ++++++++
.../src/main/resources/myjson/views.xml | 18 ++++++
.../src/main/resources/pgjsonb/views.xml | 18 ++++++
.../core/persistence/jpa/dao/JPAAnySearchDAO.java | 28 ++++++++
.../core/persistence/jpa/dao/SearchSupport.java | 4 ++
.../src/main/resources/sqlserver_views.xml | 18 ++++++
core/persistence-jpa/src/main/resources/views.xml | 18 ++++++
.../core/persistence/jpa/inner/AnySearchTest.java | 11 ++++
.../elasticsearch/client/ElasticsearchUtils.java | 2 +
.../jpa/dao/ElasticsearchAnySearchDAO.java | 13 ++++
.../org/apache/syncope/fit/core/SearchITCase.java | 18 +++++-
src/main/asciidoc/reference-guide/usage/core.adoc | 7 ++
28 files changed, 427 insertions(+), 36 deletions(-)
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AbstractSearchPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AbstractSearchPanel.java
index 5cf2392356..1b624b5e6d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AbstractSearchPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AbstractSearchPanel.java
@@ -22,13 +22,16 @@ import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.client.console.SyncopeWebApplication;
import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
import org.apache.syncope.client.console.rest.GroupRestClient;
import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.search.SearchableFields;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
import org.apache.syncope.common.lib.to.PlainSchemaTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.IdRepoEntitlement;
@@ -51,6 +54,8 @@ public abstract class AbstractSearchPanel extends Panel {
protected IModel<Map<String, PlainSchemaTO>> anames;
+ protected IModel<List<String>> auxClassNames;
+
protected IModel<List<String>> resourceNames;
protected IModel<List<SearchClause.Type>> types;
@@ -159,7 +164,7 @@ public abstract class AbstractSearchPanel extends Panel {
required,
types,
builder.customizer,
- anames, dnames, groupInfo, roleNames, privilegeNames, resourceNames);
+ anames, dnames, groupInfo, roleNames, privilegeNames, auxClassNames, resourceNames);
if (enableSearch) {
searchClausePanel.enableSearch(builder.resultContainer);
@@ -195,6 +200,19 @@ public abstract class AbstractSearchPanel extends Panel {
}
};
+ auxClassNames = new LoadableDetachableModel<>() {
+
+ private static final long serialVersionUID = 5275935387613157437L;
+
+ @Override
+ protected List<String> load() {
+ return AnyTypeClassRestClient.list().stream().
+ filter(c -> c.getInUseByTypes().isEmpty()).
+ map(AnyTypeClassTO::getKey).
+ collect(Collectors.toList());
+ }
+ };
+
resourceNames = new LoadableDetachableModel<>() {
private static final long serialVersionUID = 5275935387613157437L;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSearchPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSearchPanel.java
index 80235038aa..282059878f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSearchPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSearchPanel.java
@@ -112,6 +112,7 @@ public class AnyObjectSearchPanel extends AbstractSearchPanel {
List<SearchClause.Type> result = new ArrayList<>();
result.add(SearchClause.Type.ATTRIBUTE);
result.add(SearchClause.Type.GROUP_MEMBERSHIP);
+ result.add(SearchClause.Type.AUX_CLASS);
result.add(SearchClause.Type.RESOURCE);
result.add(SearchClause.Type.RELATIONSHIP);
return result;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSearchPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSearchPanel.java
index b912f238b7..a7ae709ad6 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSearchPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSearchPanel.java
@@ -66,6 +66,7 @@ public class GroupSearchPanel extends AbstractSearchPanel {
protected List<SearchClause.Type> load() {
List<SearchClause.Type> result = new ArrayList<>();
result.add(SearchClause.Type.ATTRIBUTE);
+ result.add(SearchClause.Type.AUX_CLASS);
result.add(SearchClause.Type.RESOURCE);
result.add(SearchClause.Type.GROUP_MEMBER);
return result;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClause.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClause.java
index 69f2d153c5..1c84c5a301 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClause.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClause.java
@@ -41,6 +41,7 @@ public final class SearchClause implements Serializable {
GROUP_MEMBER,
ROLE_MEMBERSHIP,
PRIVILEGE,
+ AUX_CLASS,
RESOURCE,
RELATIONSHIP,
CUSTOM;
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
index 79fdac669a..1996a97693 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchClausePanel.java
@@ -150,6 +150,8 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
private final IModel<List<String>> privilegeNames;
+ private final IModel<List<String>> auxClassNames;
+
private final IModel<List<String>> resourceNames;
private IModel<SearchClause> clause;
@@ -183,6 +185,7 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
final Pair<IModel<List<String>>, IModel<Integer>> groupInfo,
final IModel<List<String>> roleNames,
final IModel<List<String>> privilegeNames,
+ final IModel<List<String>> auxClassNames,
final IModel<List<String>> resourceNames) {
super(id, name, clause);
@@ -197,6 +200,7 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
this.groupInfo = groupInfo;
this.roleNames = roleNames;
this.privilegeNames = privilegeNames;
+ this.auxClassNames = auxClassNames;
this.resourceNames = resourceNames;
searchButton = new AjaxLink<>("search") {
@@ -239,6 +243,7 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
case ATTRIBUTE:
return List.of(SearchClause.Comparator.values());
+ case AUX_CLASS:
case ROLE_MEMBERSHIP:
case PRIVILEGE:
case GROUP_MEMBERSHIP:
@@ -293,6 +298,10 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
return privilegeNames.getObject().stream().
sorted().collect(Collectors.toList());
+ case AUX_CLASS:
+ return auxClassNames.getObject().stream().
+ sorted().collect(Collectors.toList());
+
case RESOURCE:
return resourceNames.getObject().stream().
sorted().collect(Collectors.toList());
@@ -647,6 +656,7 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
property.setModelObject(StringUtils.EMPTY);
break;
+ case AUX_CLASS:
case RESOURCE:
value.setEnabled(false);
value.setModelObject(StringUtils.EMPTY);
@@ -759,6 +769,7 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
}
break;
+ case AUX_CLASS:
case ROLE_MEMBERSHIP:
case PRIVILEGE:
case RESOURCE:
@@ -1026,7 +1037,7 @@ public class SearchClausePanel extends FieldPanel<SearchClause> {
public FieldPanel<SearchClause> clone() {
SearchClausePanel panel = new SearchClausePanel(
getId(), name, null, required, types, customizer, anames, dnames, groupInfo,
- roleNames, privilegeNames, resourceNames);
+ roleNames, privilegeNames, auxClassNames, resourceNames);
panel.setReadOnly(this.isReadOnly());
panel.setRequired(this.isRequired());
if (searchButton.isEnabled()) {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchUtils.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchUtils.java
index 57e8a60389..89efc1de18 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchUtils.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/SearchUtils.java
@@ -149,6 +149,9 @@ public final class SearchUtils implements Serializable {
} else if (SpecialAttr.GROUPS.toString().equals(property)) {
clause.setType(SearchClause.Type.GROUP_MEMBERSHIP);
clause.setProperty(value);
+ } else if (SpecialAttr.AUX_CLASSES.toString().equals(property)) {
+ clause.setType(SearchClause.Type.AUX_CLASS);
+ clause.setProperty(value);
} else if (SpecialAttr.RESOURCES.toString().equals(property)) {
clause.setType(SearchClause.Type.RESOURCE);
clause.setProperty(value);
@@ -277,6 +280,14 @@ public final class SearchUtils implements Serializable {
}
break;
+ case AUX_CLASS:
+ if (StringUtils.isNotBlank(clause.getProperty())) {
+ condition = clause.getComparator() == SearchClause.Comparator.EQUALS
+ ? builder.hasAuxClasses(clause.getProperty())
+ : builder.hasNotAuxClasses(clause.getProperty());
+ }
+ break;
+
case RESOURCE:
if (StringUtils.isNotBlank(clause.getProperty())) {
condition = clause.getComparator() == SearchClause.Comparator.EQUALS
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSearchPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSearchPanel.java
index 9b38f4d0fa..47b2a0e41a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSearchPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSearchPanel.java
@@ -71,8 +71,8 @@ public class UserSearchPanel extends AnyObjectSearchPanel {
@Override
protected List<String> load() {
return ApplicationRestClient.list().stream().
- flatMap(application -> application.getPrivileges().stream()).
- map(EntityTO::getKey).collect(Collectors.toList());
+ flatMap(application -> application.getPrivileges().stream()).
+ map(EntityTO::getKey).collect(Collectors.toList());
}
};
}
@@ -84,6 +84,7 @@ public class UserSearchPanel extends AnyObjectSearchPanel {
result.add(SearchClause.Type.ROLE_MEMBERSHIP);
result.add(SearchClause.Type.PRIVILEGE);
result.add(SearchClause.Type.GROUP_MEMBERSHIP);
+ result.add(SearchClause.Type.AUX_CLASS);
result.add(SearchClause.Type.RESOURCE);
result.add(SearchClause.Type.RELATIONSHIP);
return result;
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AbstractFiqlSearchConditionBuilder.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AbstractFiqlSearchConditionBuilder.java
index 7f36d562d7..fbeb54a36a 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AbstractFiqlSearchConditionBuilder.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/AbstractFiqlSearchConditionBuilder.java
@@ -82,6 +82,14 @@ public abstract class AbstractFiqlSearchConditionBuilder<
notInDynRealms(dynRealm, moreDynRealms);
}
+ public C hasAuxClasses(final String auxClass, final String... moreAuxClasses) {
+ return newBuilderInstance().is(SpecialAttr.AUX_CLASSES.toString()).hasAuxClasses(auxClass, moreAuxClasses);
+ }
+
+ public C hasNotAuxClasses(final String auxClass, final String... moreAuxClasses) {
+ return newBuilderInstance().is(SpecialAttr.AUX_CLASSES.toString()).hasNotAuxClasses(auxClass, moreAuxClasses);
+ }
+
public C hasResources(final String resource, final String... moreResources) {
return newBuilderInstance().is(SpecialAttr.RESOURCES.toString()).hasResources(resource, moreResources);
}
@@ -121,6 +129,16 @@ public abstract class AbstractFiqlSearchConditionBuilder<
return (C) this;
}
+ @Override
+ public C equalToIgnoreCase(final String value, final String... moreValues) {
+ return condition(SyncopeFiqlParser.IEQ, value, (Object[]) moreValues);
+ }
+
+ @Override
+ public C notEqualTolIgnoreCase(final String literalOrPattern) {
+ return condition(SyncopeFiqlParser.NIEQ, literalOrPattern);
+ }
+
@Override
public C nullValue() {
return condition(FiqlParser.EQ, SpecialAttr.NULL);
@@ -132,25 +150,27 @@ public abstract class AbstractFiqlSearchConditionBuilder<
}
@Override
- public C hasResources(final String resource, final String... moreResources) {
- this.result = SpecialAttr.RESOURCES.toString();
- return condition(FiqlParser.EQ, resource, (Object[]) moreResources);
+ public C hasAuxClasses(final String auxClass, final String... moreAuxClasses) {
+ this.result = SpecialAttr.AUX_CLASSES.toString();
+ return condition(FiqlParser.EQ, auxClass, (Object[]) moreAuxClasses);
}
@Override
- public C hasNotResources(final String resource, final String... moreResources) {
- this.result = SpecialAttr.RESOURCES.toString();
- return condition(FiqlParser.NEQ, resource, (Object[]) moreResources);
+ public C hasNotAuxClasses(final String auxClass, final String... moreAuxClasses) {
+ this.result = SpecialAttr.AUX_CLASSES.toString();
+ return condition(FiqlParser.NEQ, auxClass, (Object[]) moreAuxClasses);
}
@Override
- public C equalToIgnoreCase(final String value, final String... moreValues) {
- return condition(SyncopeFiqlParser.IEQ, value, (Object[]) moreValues);
+ public C hasResources(final String resource, final String... moreResources) {
+ this.result = SpecialAttr.RESOURCES.toString();
+ return condition(FiqlParser.EQ, resource, (Object[]) moreResources);
}
@Override
- public C notEqualTolIgnoreCase(final String literalOrPattern) {
- return condition(SyncopeFiqlParser.NIEQ, literalOrPattern);
+ public C hasNotResources(final String resource, final String... moreResources) {
+ this.result = SpecialAttr.RESOURCES.toString();
+ return condition(FiqlParser.NEQ, resource, (Object[]) moreResources);
}
@Override
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java
index e6d34140be..3bd37291bc 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SpecialAttr.java
@@ -22,7 +22,7 @@ import java.util.Arrays;
import java.util.Optional;
public enum SpecialAttr {
-
+
/**
* Applies to users, groups and any objects.
*/
@@ -31,6 +31,10 @@ public enum SpecialAttr {
* Applies to any objects.
*/
TYPE("$type"),
+ /**
+ * Applies to users, groups and any objects.
+ */
+ AUX_CLASSES("$auxClasses"),
/**
* Applies to users, groups and any objects.
*/
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeFiqlParser.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeFiqlParser.java
index e7e0191a75..01f01c8c2b 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeFiqlParser.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeFiqlParser.java
@@ -19,10 +19,10 @@
package org.apache.syncope.common.lib.search;
import java.util.Map;
+import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
-
import org.apache.cxf.jaxrs.ext.search.ConditionType;
import org.apache.cxf.jaxrs.ext.search.SearchBean;
import org.apache.cxf.jaxrs.ext.search.SearchCondition;
@@ -77,18 +77,13 @@ public class SyncopeFiqlParser<T> extends FiqlParser<T> {
throw new SearchParseException("Not a comparison expression: " + expr);
}
- String name = unwrapSetter(propertyName);
-
- name = getActualSetterName(name);
- TypeInfoObject castedValue = parseType(propertyName, name, value);
- if (castedValue != null) {
- return new SyncopeComparison(name, operator, castedValue);
- } else {
- return null;
- }
- } else {
- throw new SearchParseException("Not a comparison expression: " + expr);
+ String name = getActualSetterName(unwrapSetter(propertyName));
+ return Optional.ofNullable(parseType(propertyName, name, value)).
+ map(typeInfoObject -> new SyncopeComparison(name, operator, typeInfoObject)).
+ orElse(null);
}
+
+ throw new SearchParseException("Not a comparison expression: " + expr);
}
private class SyncopeComparison implements ASTNode<T> {
@@ -148,5 +143,4 @@ public class SyncopeFiqlParser<T> extends FiqlParser<T> {
}
}
}
-
}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeFiqlSearchCondition.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeFiqlSearchCondition.java
index 41e0bacff2..31fe477c68 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeFiqlSearchCondition.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeFiqlSearchCondition.java
@@ -55,5 +55,4 @@ public class SyncopeFiqlSearchCondition<T> extends SimpleSearchCondition<T> {
public String getOperator() {
return operator;
}
-
}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeProperty.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeProperty.java
index e792826d6c..3b40a90b8c 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeProperty.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/search/SyncopeProperty.java
@@ -28,7 +28,8 @@ import org.apache.cxf.jaxrs.ext.search.client.Property;
*/
public interface SyncopeProperty<C extends SyncopeCompleteCondition<?, ?>> extends Property {
- /** Is textual property equal to (ignoring case) given literal or matching given pattern?
+ /**
+ * Is textual property equal to (ignoring case) given literal or matching given pattern?
*
* @param value first value
* @param moreValues more values
@@ -36,26 +37,48 @@ public interface SyncopeProperty<C extends SyncopeCompleteCondition<?, ?>> exten
*/
C equalToIgnoreCase(String value, String... moreValues);
- /** Is textual property different (ignoring case) than given literal or not matching given pattern?
+ /**
+ * Is textual property different (ignoring case) than given literal or not matching given pattern?
*
* @param literalOrPattern The literal or Pattern String
* @return updated condition
*/
C notEqualTolIgnoreCase(String literalOrPattern);
- /** Is property null?
+ /**
+ * Is property null?
*
* @return updated condition
*/
C nullValue();
- /** Is property not null?
+ /**
+ * Is property not null?
*
* @return updated condition
*/
C notNullValue();
- /** Is user, group or any object owning given resource(s)?
+ /**
+ * Has user, group or any object assigned the given auxiliary class(es)?
+ *
+ * @param auxClass first auxiliary class
+ * @param moreAuxClasses more auxiliary classes
+ * @return updated condition
+ */
+ C hasAuxClasses(String auxClass, String... moreAuxClasses);
+
+ /**
+ * Has user, group or any object not assigned the given auxiliary class(es)?
+ *
+ * @param auxClass first auxiliary class
+ * @param moreAuxClasses more auxiliary classes
+ * @return updated condition
+ */
+ C hasNotAuxClasses(String auxClass, String... moreAuxClasses);
+
+ /**
+ * Is user, group or any object owning given resource(s)?
*
* @param resource first resource
* @param moreResources more resources
@@ -63,7 +86,8 @@ public interface SyncopeProperty<C extends SyncopeCompleteCondition<?, ?>> exten
*/
C hasResources(String resource, String... moreResources);
- /** Is user, group or any object not owning given resource(s)?
+ /**
+ * Is user, group or any object not owning given resource(s)?
*
* @param resource first resource
* @param moreResources more resources
@@ -71,7 +95,21 @@ public interface SyncopeProperty<C extends SyncopeCompleteCondition<?, ?>> exten
*/
C hasNotResources(String resource, String... moreResources);
+ /**
+ * Is user, group or any object in the given dynamic realm(s)?
+ *
+ * @param dynRealm first dynamic realm
+ * @param moreDynRealms more dynamic realms
+ * @return updated condition
+ */
C inDynRealms(String dynRealm, String... moreDynRealms);
+ /**
+ * Is user, group or any object not in the given dynamic realm(s)?
+ *
+ * @param dynRealm first dynamic realm
+ * @param moreDynRealms more dynamic realms
+ * @return updated condition
+ */
C notInDynRealms(String dynRealm, String... moreDynRealms);
}
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AuxClassCond.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AuxClassCond.java
new file mode 100644
index 0000000000..b479fd43b8
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/AuxClassCond.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.api.dao.search;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+public class AuxClassCond extends AbstractSearchCond {
+
+ private static final long serialVersionUID = 4298076973281246633L;
+
+ private String auxClass;
+
+ public String getAuxClass() {
+ return auxClass;
+ }
+
+ public void setAuxClass(final String auxClass) {
+ this.auxClass = auxClass;
+ }
+
+ @Override
+ public boolean isValid() {
+ return auxClass != null;
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder().
+ append(auxClass).
+ build();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final AuxClassCond other = (AuxClassCond) obj;
+ return new EqualsBuilder().
+ append(auxClass, other.auxClass).
+ build();
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this).
+ append(auxClass).
+ build();
+ }
+}
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
index 011627e68c..ddd027d027 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
@@ -41,6 +41,7 @@ import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
+import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
import org.apache.syncope.core.persistence.api.dao.search.PrivilegeCond;
@@ -151,6 +152,12 @@ public class SearchCondVisitor extends AbstractSearchConditionVisitor<SearchBean
leaf = SearchCond.getLeaf(typeCond);
break;
+ case AUX_CLASSES:
+ AuxClassCond auxClassCond = new AuxClassCond();
+ auxClassCond.setAuxClass(value);
+ leaf = SearchCond.getLeaf(auxClassCond);
+ break;
+
case RESOURCES:
ResourceCond resourceCond = new ResourceCond();
resourceCond.setResourceKey(value);
diff --git a/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/FilterConverterTest.java b/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/FilterConverterTest.java
index 84f73d846f..353ae27bb7 100644
--- a/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/FilterConverterTest.java
+++ b/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/FilterConverterTest.java
@@ -192,6 +192,26 @@ public class FilterConverterTest {
}
}
+ @Test
+ public void hasAuxClasses() {
+ try {
+ FilterConverter.convert(SpecialAttr.AUX_CLASSES + "==clazz1");
+ fail();
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.InvalidSearchParameters, e.getType());
+ }
+ }
+
+ @Test
+ public void hasNotAuxClasses() {
+ try {
+ FilterConverter.convert(SpecialAttr.AUX_CLASSES + "!=clazz1");
+ fail();
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.InvalidSearchParameters, e.getType());
+ }
+ }
+
@Test
public void hasResources() {
try {
diff --git a/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/SearchCondConverterTest.java b/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/SearchCondConverterTest.java
index 111aa6774b..7bee68e818 100644
--- a/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/SearchCondConverterTest.java
+++ b/core/persistence-api/src/test/java/org/apache/syncope/core/persistence/api/search/SearchCondConverterTest.java
@@ -33,6 +33,7 @@ import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
+import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
import org.apache.syncope.core.persistence.api.dao.search.PrivilegeCond;
@@ -226,6 +227,18 @@ public class SearchCondConverterTest {
assertEquals(leaf, SearchCondConverter.convert(VISITOR, fiql));
}
+ @Test
+ public void auxClasses() {
+ String fiql = new UserFiqlSearchConditionBuilder().hasAuxClasses("clazz1").query();
+ assertEquals(SpecialAttr.AUX_CLASSES + "==clazz1", fiql);
+
+ AuxClassCond cond = new AuxClassCond();
+ cond.setAuxClass("clazz1");
+ SearchCond leaf = SearchCond.getLeaf(cond);
+
+ assertEquals(leaf, SearchCondConverter.convert(VISITOR, fiql));
+ }
+
@Test
public void resources() {
String fiql = new UserFiqlSearchConditionBuilder().hasResources("resource-ldap").query();
diff --git a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
index 3a4191d766..24e8f8b6ce 100644
--- a/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
+++ b/core/persistence-jpa-json/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAJSONAnySearchDAO.java
@@ -43,6 +43,7 @@ import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
+import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
@@ -297,6 +298,30 @@ public class PGJPAJSONAnySearchDAO extends JPAAnySearchDAO {
return query.toString();
}
+ @Override
+ protected String getQuery(
+ final AuxClassCond cond,
+ final boolean not,
+ final List<Object> parameters,
+ final SearchSupport svs) {
+
+ StringBuilder query = new StringBuilder();
+
+ if (not) {
+ query.append("id NOT IN (");
+ } else {
+ query.append("id IN (");
+ }
+
+ query.append("SELECT DISTINCT any_id FROM ").
+ append(svs.auxClass().name).
+ append(" WHERE anyTypeClass_id=?").
+ append(setParameter(parameters, cond.getAuxClass())).
+ append(')');
+
+ return query.toString();
+ }
+
@Override
protected String getQuery(
final RoleCond cond,
diff --git a/core/persistence-jpa-json/src/main/resources/myjson/views.xml b/core/persistence-jpa-json/src/main/resources/myjson/views.xml
index 8e7da4d7ea..1744dc06d9 100644
--- a/core/persistence-jpa-json/src/main/resources/myjson/views.xml
+++ b/core/persistence-jpa-json/src/main/resources/myjson/views.xml
@@ -96,6 +96,12 @@ under the License.
FROM DynRoleMembers drm, SyncopeRole_Privilege rp
WHERE drm.role_id = rp.role_id
</entry>
+ <entry key="user_search_auxClass">
+ CREATE VIEW user_search_auxClass AS
+
+ SELECT st.user_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM SyncopeUser_AnyTypeClass st
+ </entry>
<entry key="user_search_resource">
CREATE VIEW user_search_resource AS
@@ -140,6 +146,12 @@ under the License.
FROM AMembership m, SyncopeGroup g
WHERE m.group_id = g.id
</entry>
+ <entry key="anyObject_search_auxClass">
+ CREATE VIEW anyObject_search_auxClass AS
+
+ SELECT st.anyObject_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM AnyObject_AnyTypeClass st
+ </entry>
<entry key="anyObject_search_resource">
CREATE VIEW anyObject_search_resource AS
@@ -171,6 +183,12 @@ under the License.
attrUniqueValue JSON PATH '$.uniqueValue')
) AS attrs
</entry>
+ <entry key="group_search_auxClass">
+ CREATE VIEW group_search_auxClass AS
+
+ SELECT st.group_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM SyncopeGroup_AnyTypeClass st
+ </entry>
<entry key="group_search_resource">
CREATE VIEW group_search_resource AS
diff --git a/core/persistence-jpa-json/src/main/resources/pgjsonb/views.xml b/core/persistence-jpa-json/src/main/resources/pgjsonb/views.xml
index e360813225..e25da2f66f 100644
--- a/core/persistence-jpa-json/src/main/resources/pgjsonb/views.xml
+++ b/core/persistence-jpa-json/src/main/resources/pgjsonb/views.xml
@@ -80,6 +80,12 @@ under the License.
FROM DynRoleMembers drm, SyncopeRole_Privilege rp
WHERE drm.role_id = rp.role_id
</entry>
+ <entry key="user_search_auxClass">
+ CREATE VIEW user_search_auxClass AS
+
+ SELECT st.user_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM SyncopeUser_AnyTypeClass st
+ </entry>
<entry key="user_search_resource">
CREATE VIEW user_search_resource AS
@@ -108,6 +114,12 @@ under the License.
FROM AMembership m, SyncopeGroup g
WHERE m.group_id = g.id
</entry>
+ <entry key="anyObject_search_auxClass">
+ CREATE VIEW anyObject_search_auxClass AS
+
+ SELECT st.anyObject_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM AnyObject_AnyTypeClass st
+ </entry>
<entry key="anyObject_search_resource">
CREATE VIEW anyObject_search_resource AS
@@ -123,6 +135,12 @@ under the License.
</entry>
<!-- group -->
+ <entry key="group_search_auxClass">
+ CREATE VIEW group_search_auxClass AS
+
+ SELECT st.group_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM SyncopeGroup_AnyTypeClass st
+ </entry>
<entry key="group_search_resource">
CREATE VIEW group_search_resource AS
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
index 08374986bf..f7dacda6fd 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
@@ -51,6 +51,7 @@ import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
+import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
import org.apache.syncope.core.persistence.api.dao.search.PrivilegeCond;
@@ -542,6 +543,9 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
filter(leaf -> AnyTypeKind.ANY_OBJECT == svs.anyTypeKind).
ifPresent(leaf -> query.append(getQuery(leaf, not, parameters, svs)));
+ cond.getLeaf(AuxClassCond.class).
+ ifPresent(leaf -> query.append(getQuery(leaf, not, parameters, svs)));
+
cond.getLeaf(RelationshipTypeCond.class).
filter(leaf -> AnyTypeKind.GROUP != svs.anyTypeKind).
ifPresent(leaf -> query.append(getQuery(leaf, not, parameters, svs)));
@@ -639,6 +643,30 @@ public class JPAAnySearchDAO extends AbstractAnySearchDAO {
return query.toString();
}
+ protected String getQuery(
+ final AuxClassCond cond,
+ final boolean not,
+ final List<Object> parameters,
+ final SearchSupport svs) {
+
+ StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
+ append(svs.field().name).append(" WHERE ");
+
+ if (not) {
+ query.append("any_id NOT IN (");
+ } else {
+ query.append("any_id IN (");
+ }
+
+ query.append("SELECT DISTINCT any_id FROM ").
+ append(svs.auxClass().name).
+ append(" WHERE anyTypeClass_id=?").
+ append(setParameter(parameters, cond.getAuxClass())).
+ append(')');
+
+ return query.toString();
+ }
+
protected String getQuery(
final RelationshipTypeCond cond,
final boolean not,
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
index db48343ada..936315574d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/SearchSupport.java
@@ -150,6 +150,10 @@ public class SearchSupport {
return new SearchView("svdrealm", JPADynRealmDAO.DYNMEMB_TABLE);
}
+ public SearchView auxClass() {
+ return new SearchView("svac", field().name + "_auxClass");
+ }
+
public SearchView resource() {
return new SearchView("svr", field().name + "_resource");
}
diff --git a/core/persistence-jpa/src/main/resources/sqlserver_views.xml b/core/persistence-jpa/src/main/resources/sqlserver_views.xml
index 529901ece9..83dd7873a6 100644
--- a/core/persistence-jpa/src/main/resources/sqlserver_views.xml
+++ b/core/persistence-jpa/src/main/resources/sqlserver_views.xml
@@ -111,6 +111,12 @@ under the License.
FROM DynRoleMembers drm, SyncopeRole_Privilege rp
WHERE drm.role_id = rp.role_id
</entry>
+ <entry key="user_search_auxClass">
+ CREATE VIEW user_search_auxClass AS
+
+ SELECT st.user_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM SyncopeUser_AnyTypeClass st
+ </entry>
<entry key="user_search_resource">
CREATE VIEW user_search_resource AS
@@ -170,6 +176,12 @@ under the License.
FROM AMembership m, SyncopeGroup g
WHERE m.group_id = g.id
</entry>
+ <entry key="anyObject_search_auxClass">
+ CREATE VIEW anyObject_search_auxClass AS
+
+ SELECT st.anyObject_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM AnyObject_AnyTypeClass st
+ </entry>
<entry key="anyObject_search_resource">
CREATE VIEW anyObject_search_resource AS
@@ -216,6 +228,12 @@ under the License.
FROM GPlainAttrValue uav, GPlainAttr ua
WHERE uav.attribute_id = ua.id
</entry>
+ <entry key="group_search_auxClass">
+ CREATE VIEW group_search_auxClass AS
+
+ SELECT st.group_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM SyncopeGroup_AnyTypeClass st
+ </entry>
<entry key="group_search_resource">
CREATE VIEW group_search_resource AS
diff --git a/core/persistence-jpa/src/main/resources/views.xml b/core/persistence-jpa/src/main/resources/views.xml
index f1e8a603d6..e242f0ff92 100644
--- a/core/persistence-jpa/src/main/resources/views.xml
+++ b/core/persistence-jpa/src/main/resources/views.xml
@@ -111,6 +111,12 @@ under the License.
FROM DynRoleMembers drm, SyncopeRole_Privilege rp
WHERE drm.role_id = rp.role_id
</entry>
+ <entry key="user_search_auxClass">
+ CREATE VIEW user_search_auxClass AS
+
+ SELECT st.user_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM SyncopeUser_AnyTypeClass st
+ </entry>
<entry key="user_search_resource">
CREATE VIEW user_search_resource AS
@@ -170,6 +176,12 @@ under the License.
FROM AMembership m, SyncopeGroup g
WHERE m.group_id = g.id
</entry>
+ <entry key="anyObject_search_auxClass">
+ CREATE VIEW anyObject_search_auxClass AS
+
+ SELECT st.anyObject_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM AnyObject_AnyTypeClass st
+ </entry>
<entry key="anyObject_search_resource">
CREATE VIEW anyObject_search_resource AS
@@ -216,6 +228,12 @@ under the License.
FROM GPlainAttrValue uav, GPlainAttr ua
WHERE uav.attribute_id = ua.id
</entry>
+ <entry key="group_search_auxClass">
+ CREATE VIEW group_search_auxClass AS
+
+ SELECT st.group_id AS any_id, st.anyTypeClass_id AS anyTypeClass_id
+ FROM SyncopeGroup_AnyTypeClass st
+ </entry>
<entry key="group_search_resource">
CREATE VIEW group_search_resource AS
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
index e4dad5d2f4..926ce35b01 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
@@ -52,6 +52,7 @@ import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
+import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
import org.apache.syncope.core.persistence.api.dao.search.PrivilegeCond;
import org.apache.syncope.core.persistence.api.dao.search.RelationshipTypeCond;
@@ -361,6 +362,16 @@ public class AnySearchTest extends AbstractTest {
assertEquals(1, users.size());
}
+ @Test
+ public void searchByAuxClass() {
+ AuxClassCond ac = new AuxClassCond();
+ ac.setAuxClass("csv");
+
+ List<Group> groups = searchDAO.search(SearchCond.getLeaf(ac), AnyTypeKind.GROUP);
+ assertNotNull(groups);
+ assertEquals(2, groups.size());
+ }
+
@Test
public void searchByResource() {
ResourceCond ws2 = new ResourceCond();
diff --git a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java
index 54d238519e..a95d09162c 100644
--- a/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java
+++ b/ext/elasticsearch/client-elasticsearch/src/main/java/org/apache/syncope/ext/elasticsearch/client/ElasticsearchUtils.java
@@ -32,6 +32,7 @@ import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
import org.apache.syncope.core.persistence.api.entity.PlainAttr;
import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
import org.apache.syncope.core.persistence.api.entity.Privilege;
@@ -139,6 +140,7 @@ public class ElasticsearchUtils {
builder.put("lastModifier", any.getLastModifier());
builder.put("lastChangeContext", any.getLastChangeContext());
builder.put("status", any.getStatus());
+ builder.put("auxClasses", any.getAuxClasses().stream().map(AnyTypeClass::getKey).collect(Collectors.toList()));
builder.put("resources", resources);
builder.put("dynRealms", dynRealms);
diff --git a/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java b/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
index ad7dd141b3..7bc554eab0 100644
--- a/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
+++ b/ext/elasticsearch/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/ElasticsearchAnySearchDAO.java
@@ -58,6 +58,7 @@ import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond;
import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
+import org.apache.syncope.core.persistence.api.dao.search.AuxClassCond;
import org.apache.syncope.core.persistence.api.dao.search.DynRealmCond;
import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
@@ -371,6 +372,12 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
orElse(null);
}
+ if (query == null) {
+ query = cond.getLeaf(AuxClassCond.class).
+ map(this::getQuery).
+ orElse(null);
+ }
+
if (query == null) {
query = cond.getLeaf(ResourceCond.class).
map(this::getQuery).
@@ -503,6 +510,12 @@ public class ElasticsearchAnySearchDAO extends AbstractAnySearchDAO {
build();
}
+ protected Query getQuery(final AuxClassCond cond) {
+ return new Query.Builder().term(QueryBuilders.term().
+ field("auxClasses").value(FieldValue.of(cond.getAuxClass())).build()).
+ build();
+ }
+
protected Query getQuery(final ResourceCond cond) {
return new Query.Builder().term(QueryBuilders.term().
field("resources").value(FieldValue.of(cond.getResourceKey())).build()).
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
index 6ccc7a7f68..8d9bcddfd8 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
@@ -256,7 +256,23 @@ public class SearchITCase extends AbstractITCase {
}
@Test
- public void searchUserByResourceName() {
+ public void searchByAuxClass() {
+ PagedResult<GroupTO> matchingGroups = groupService.search(
+ new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
+ fiql(SyncopeClient.getGroupSearchConditionBuilder().
+ hasAuxClasses("csv").query()).
+ build());
+ assertNotNull(matchingGroups);
+ assertFalse(matchingGroups.getResult().isEmpty());
+
+ assertTrue(matchingGroups.getResult().stream().
+ anyMatch(group -> "0626100b-a4ba-4e00-9971-86fad52a6216".equals(group.getKey())));
+ assertTrue(matchingGroups.getResult().stream().
+ anyMatch(group -> "ba9ed509-b1f5-48ab-a334-c8530a6422dc".equals(group.getKey())));
+ }
+
+ @Test
+ public void searchByResource() {
PagedResult<UserTO> matchingUsers = userService.search(
new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
fiql(SyncopeClient.getUserSearchConditionBuilder().
diff --git a/src/main/asciidoc/reference-guide/usage/core.adoc b/src/main/asciidoc/reference-guide/usage/core.adoc
index 3ae7fe1d9c..f4e85db687 100644
--- a/src/main/asciidoc/reference-guide/usage/core.adoc
+++ b/src/main/asciidoc/reference-guide/usage/core.adoc
@@ -454,6 +454,13 @@ lastLoginDate=ge=2016-03-02 15:21:22
----
====
+.Auxiliary Any Type class assignment
+====
+----
+$auxClasses==csv
+----
+====
+
.Resource assignment match
====
----