Skip to content

Commit

Permalink
updated query engine to support polymorphic queries used in security …
Browse files Browse the repository at this point in the history
…impl. MID-1881
  • Loading branch information
1azyman committed May 12, 2014
1 parent c5af1c6 commit 7e448e7
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 28 deletions.
Expand Up @@ -181,7 +181,7 @@ private MenuBarItem createConfigurationItems() {
configuration.addMenuItem(new MenuItem(createStringResource("PageAdmin.menu.top.configuration.development"), true, null, null));
configuration.addMenuItem(new MenuItem(createStringResource("PageAdmin.menu.top.configuration.shadowsDetails"), PageAccounts.class));
configuration.addMenuItem(new MenuItem(createStringResource("PageAdmin.menu.top.configuration.internals"), PageInternals.class));
configuration.addMenuItem(new MenuItem(createStringResource("PageAdmin.menu.top.configuration.expressionEvaluator"), PageDashboard.class));
// configuration.addMenuItem(new MenuItem(createStringResource("PageAdmin.menu.top.configuration.expressionEvaluator"), PageDashboard.class));
configuration.addMenuItem(new MenuItem(null));
configuration.addMenuItem(new MenuItem(createStringResource("PageAdmin.menu.top.configuration.about"), PageAbout.class));

Expand Down
Expand Up @@ -19,6 +19,7 @@
import com.evolveum.midpoint.prism.Objectable;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.match.MatchingRuleRegistry;
import com.evolveum.midpoint.util.DebugUtil;

import javax.xml.namespace.QName;

Expand Down Expand Up @@ -59,6 +60,7 @@ public String debugDump() {
@Override
public String debugDump(int indent) {
StringBuilder sb = new StringBuilder();
DebugUtil.indentDebugDump(sb, indent);
sb.append("TYPE: ");
sb.append(type.getLocalPart());

Expand Down
Expand Up @@ -623,7 +623,7 @@ public void test205AutzJackObjectFilterModifyCaribbeanfRole() throws Exception {
assertDeleteDeny();
}

@Test(enabled=false) // MID-1881
@Test
public void test207AutzJackObjectFilterCaribbeanRole() throws Exception {
final String TEST_NAME = "test207AutzJackObjectFilterCaribbeanfRole";
TestUtil.displayTestTile(this, TEST_NAME);
Expand Down
Expand Up @@ -31,8 +31,10 @@
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.query.*;
import com.evolveum.midpoint.repo.sql.data.common.*;
import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString;
import com.evolveum.midpoint.repo.sql.data.common.type.RObjectExtensionType;
import com.evolveum.midpoint.repo.sql.query.QueryDefinitionRegistry;
import com.evolveum.midpoint.repo.sql.query.restriction.Restriction;
import com.evolveum.midpoint.repo.sql.type.XMLGregorianCalendarType;

import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
Expand Down Expand Up @@ -415,7 +417,6 @@ public void queryUserByFullName() throws Exception {

@Test
public void queryUserSubstringFullName() throws Exception {
LOGGER.info("===[{}]===", new Object[]{"queryUserSubstringFullName"});
Session session = open();

try {
Expand All @@ -439,7 +440,6 @@ public void queryUserSubstringFullName() throws Exception {

@Test
public void queryUserByName() throws Exception {
LOGGER.info("===[{}]===", new Object[]{"queryUserByName"});
Session session = open();

try {
Expand Down Expand Up @@ -525,7 +525,6 @@ public void queryAccountByAttributesAndResourceRef() throws Exception {

@Test
public void queryUserAccountRef() throws Exception {
LOGGER.info("===[{}]===", new Object[]{"queryUserAccountRef"});
Session session = open();
try {
Criteria main = session.createCriteria(RUser.class, "u");
Expand Down Expand Up @@ -1345,4 +1344,103 @@ public void test360queryMetadataTimestamp() throws Exception {
close(session);
}
}

@Test
public void test370queryObjectypeByTypeAndLocality() throws Exception {
Session session = open();
try {
Criteria main = session.createCriteria(RObject.class, "o");
ProjectionList projections = Projections.projectionList();
addFullObjectProjectionList("o", projections, false);
main.setProjection(projections);

Conjunction c = Restrictions.conjunction();
main.add(c);
c.add(Restrictions.eq("o." + RObject.F_OBJECT_TYPE_CLASS, RObjectType.USER));
c.add(Restrictions.and(Restrictions.eq("o.locality.orig", "Caribbean"),
Restrictions.eq("o.locality.norm", "caribbean")));

String expected = HibernateToSqlTranslator.toSql(main);

TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE);
EqualsFilter eq = EqualsFilter.createEqual(new ItemPath(OrgType.F_LOCALITY), OrgType.class, prismContext,
new PolyString("Caribbean", "caribbean"));
AndFilter and = AndFilter.createAnd(type, eq);

String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(and));

LOGGER.info("exp. query>\n{}\nreal query>\n{}", new Object[]{expected, real});
AssertJUnit.assertEquals(expected, real);
} finally {
close(session);
}
}

@Test
public void test380queryObjectypeByTypeAndExtensionAttribute() throws Exception {
Session session = open();
try {
Criteria main = session.createCriteria(RObject.class, "o");
ProjectionList projections = Projections.projectionList();
addFullObjectProjectionList("o", projections, false);
main.setProjection(projections);

Conjunction c = Restrictions.conjunction();
main.add(c);
c.add(Restrictions.eq("o." + RObject.F_OBJECT_TYPE_CLASS, RObjectType.USER));

Conjunction c2 = Restrictions.conjunction();
main.createCriteria("strings", "s", JoinType.LEFT_OUTER_JOIN);
c2.add(Restrictions.eq("s.ownerType", RObjectExtensionType.EXTENSION));
c2.add(Restrictions.eq("s.name", new QName("http://example.com/p", "weapon")));
c2.add(Restrictions.eq("s.value", "some weapon name"));
c.add(c2);

String expected = HibernateToSqlTranslator.toSql(main);

TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE);
EqualsFilter eq = EqualsFilter.createEqual(
new ItemPath(ObjectType.F_EXTENSION, new QName("http://example.com/p", "weapon")),
UserType.class, prismContext, "some weapon name");
AndFilter and = AndFilter.createAnd(type, eq);

String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(and));

LOGGER.info("exp. query>\n{}\nreal query>\n{}", new Object[]{expected, real});
AssertJUnit.assertEquals(expected, real);
} finally {
close(session);
}
}

@Test
public void test390queryObjectypeByTypeAndReference() throws Exception {
Session session = open();
try {
Criteria main = session.createCriteria(RObject.class, "o");
ProjectionList projections = Projections.projectionList();
addFullObjectProjectionList("o", projections, false);
main.setProjection(projections);

Conjunction c = Restrictions.conjunction();
main.add(c);
c.add(Restrictions.eq("o." + RObject.F_OBJECT_TYPE_CLASS, RObjectType.USER));

Criteria refs = main.createCriteria("linkRef", "l", JoinType.LEFT_OUTER_JOIN);
c.add(Restrictions.and(Restrictions.eq("l.targetOid", "123")));

String expected = HibernateToSqlTranslator.toSql(main);

TypeFilter type = TypeFilter.createType(UserType.COMPLEX_TYPE);
RefFilter ref = RefFilter.createReferenceEqual(UserType.F_LINK_REF, UserType.class, prismContext, "123");
AndFilter and = AndFilter.createAnd(type, ref);

String real = getInterpretedQuery(session, ObjectType.class, ObjectQuery.createObjectQuery(and));

LOGGER.info("exp. query>\n{}\nreal query>\n{}", new Object[]{expected, real});
AssertJUnit.assertEquals(expected, real);
} finally {
close(session);
}
}
}
Expand Up @@ -249,12 +249,13 @@ public <T extends ObjectFilter> Restriction findAndCreateRestriction(T filter, Q
throws QueryException {

for (Restriction restriction : AVAILABLE_RESTRICTIONS) {
if (!restriction.canHandle(filter, context)) {
Restriction<T> res = restriction.cloneInstance();
res.setContext(context);

if (!res.canHandle(filter, context)) {
continue;
}

Restriction<T> res = restriction.cloneInstance();
res.setContext(context);
res.setParent(parent);
res.setQuery(query);

Expand Down
Expand Up @@ -64,7 +64,7 @@ public boolean canHandle(ObjectFilter filter, QueryContext context) throws Query
ValueFilter valFilter = (ValueFilter) filter;
ItemPath fullPath = valFilter.getFullPath();

List<Definition> defPath = createDefinitionPath(fullPath, context);
List<Definition> defPath = createDefinitionPath(fullPath);
return containsAnyDefinition(defPath)
|| (fullPath.first().equals(new NameItemPathSegment(ObjectType.F_EXTENSION)))
|| (fullPath.first().equals(new NameItemPathSegment(ShadowType.F_ATTRIBUTES)));
Expand Down
Expand Up @@ -24,13 +24,16 @@
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.prism.query.*;
import com.evolveum.midpoint.repo.sql.data.common.enums.SchemaEnum;
import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType;
import com.evolveum.midpoint.repo.sql.query.QueryContext;
import com.evolveum.midpoint.repo.sql.query.QueryDefinitionRegistry;
import com.evolveum.midpoint.repo.sql.query.QueryException;
import com.evolveum.midpoint.repo.sql.query.QueryInterpreter;
import com.evolveum.midpoint.repo.sql.query.definition.*;
import com.evolveum.midpoint.repo.sql.query.matcher.Matcher;
import com.evolveum.midpoint.repo.sql.util.ClassMapper;
import com.evolveum.midpoint.repo.sql.util.RUtil;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
Expand Down Expand Up @@ -86,12 +89,52 @@ public Criterion interpret(T filter) throws QueryException {

public abstract Criterion interpretInternal(T filter) throws QueryException;

protected <T extends Definition> T findProperDefinition(ItemPath path, Class<T> clazz) {
QueryContext context = getContext();
QueryDefinitionRegistry registry = QueryDefinitionRegistry.getInstance();
if (!ObjectType.class.equals(context.getType())) {
return registry.findDefinition(context.getType(), path, clazz);
}

//we should try to find property in descendant classes
for (RObjectType type : RObjectType.values()) {
ObjectTypes ot = ClassMapper.getObjectTypeForHQLType(type);

Definition def = registry.findDefinition(ot.getClassDefinition(), path, clazz);
if (def != null) {
return (T) def;
}
}

return null;
}

protected EntityDefinition findProperEntityDefinition(ItemPath path) {
QueryContext context = getContext();
QueryDefinitionRegistry registry = QueryDefinitionRegistry.getInstance();
if (!ObjectType.class.equals(context.getType())) {
return registry.findDefinition(context.getType(), null, EntityDefinition.class);
}

EntityDefinition entity = null;
// we should try to find property in descendant classes
for (RObjectType type : RObjectType.values()) {
ObjectTypes ot = ClassMapper.getObjectTypeForHQLType(type);

entity = registry.findDefinition(ot.getClassDefinition(), null, EntityDefinition.class);
Definition def = entity.findDefinition(path, Definition.class);
if (def != null) {
break;
}
}

return entity;
}

//todo reimplement, use DefinitionHandlers or maybe another great concept
private void updateQueryContext(ItemPath path) throws QueryException {
LOGGER.trace("Updating query context based on path {}", new Object[]{path.toString()});
Class<? extends ObjectType> type = getContext().getType();
QueryDefinitionRegistry registry = QueryDefinitionRegistry.getInstance();
EntityDefinition definition = registry.findDefinition(type, null, EntityDefinition.class);
EntityDefinition definition = findProperEntityDefinition(path);

List<ItemPathSegment> segments = path.getSegments();

Expand Down Expand Up @@ -171,16 +214,14 @@ private void updateQueryContext(ItemPath path) throws QueryException {
*/
private Criterion createVirtualCriterion(ItemPath path) throws QueryException {
LOGGER.trace("Scanning path for virtual definitions to create criteria {}", new Object[]{path.toString()});
QueryContext context = getContext();
Class<? extends ObjectType> type = context.getType();
QueryDefinitionRegistry registry = QueryDefinitionRegistry.getInstance();
EntityDefinition definition = registry.findDefinition(type, null, EntityDefinition.class);

EntityDefinition definition = findProperEntityDefinition(path);

List<Criterion> criterions = new ArrayList<Criterion>();

List<ItemPathSegment> segments = path.getSegments();

List<ItemPathSegment> propPathSegments = new ArrayList<ItemPathSegment>();

ItemPath propPath;
for (ItemPathSegment segment : segments) {
QName qname = ItemPath.getName(segment);
Expand Down Expand Up @@ -365,15 +406,13 @@ protected Criterion createCriterion(String propertyName, Object value, ValueFilt
return matcher.match(operation, propertyName, value, matchingRule);
}

protected List<Definition> createDefinitionPath(ItemPath path, QueryContext context) throws QueryException {
protected List<Definition> createDefinitionPath(ItemPath path) throws QueryException {
List<Definition> definitions = new ArrayList<Definition>();
if (path == null) {
return definitions;
}

QueryDefinitionRegistry registry = QueryDefinitionRegistry.getInstance();

EntityDefinition lastDefinition = registry.findDefinition(context.getType(), null, EntityDefinition.class);
EntityDefinition lastDefinition = findProperEntityDefinition(path);
for (ItemPathSegment segment : path.getSegments()) {
if (lastDefinition == null) {
break;
Expand Down
Expand Up @@ -20,10 +20,13 @@
import com.evolveum.midpoint.prism.path.ItemPathSegment;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.ValueFilter;
import com.evolveum.midpoint.repo.sql.data.common.other.RObjectType;
import com.evolveum.midpoint.repo.sql.query.QueryException;
import com.evolveum.midpoint.repo.sql.query.QueryContext;
import com.evolveum.midpoint.repo.sql.query.QueryDefinitionRegistry;
import com.evolveum.midpoint.repo.sql.query.definition.*;
import com.evolveum.midpoint.repo.sql.util.ClassMapper;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
Expand Down Expand Up @@ -54,6 +57,16 @@ public boolean canHandle(ObjectFilter filter, QueryContext context) throws Query
ItemPath fullPath = valFilter.getFullPath();

PropertyDefinition def = registry.findDefinition(context.getType(), fullPath, PropertyDefinition.class);
if (ObjectType.class.equals(context.getType()) && def == null) {
//we should try to find property in descendant classes
for (RObjectType type : RObjectType.values()) {
ObjectTypes ot = ClassMapper.getObjectTypeForHQLType(type);
def = registry.findDefinition(ot.getClassDefinition(), fullPath, PropertyDefinition.class);
if (def != null) {
break;
}
}
}

return def != null;
}
Expand All @@ -63,9 +76,8 @@ public Criterion interpretInternal(ValueFilter filter)
throws QueryException {
QueryContext context = getContext();

QueryDefinitionRegistry registry = QueryDefinitionRegistry.getInstance();
ItemPath fullPath = filter.getFullPath();
PropertyDefinition def = registry.findDefinition(context.getType(), fullPath, PropertyDefinition.class);
PropertyDefinition def = findProperDefinition(fullPath, PropertyDefinition.class);
if (def.isLob()) {
throw new QueryException("Can't query based on clob property value '" + def + "'.");
}
Expand All @@ -89,9 +101,7 @@ public Criterion interpretInternal(ValueFilter filter)
private String createPropertyNamePrefix(ItemPath path) throws QueryException {
StringBuilder sb = new StringBuilder();

Class<? extends ObjectType> type = getContext().getType();
QueryDefinitionRegistry registry = QueryDefinitionRegistry.getInstance();
EntityDefinition definition = registry.findDefinition(type, null, EntityDefinition.class);
EntityDefinition definition = findProperEntityDefinition(path);

List<ItemPathSegment> segments = path.getSegments();
for (ItemPathSegment segment : segments) {
Expand Down
Expand Up @@ -89,7 +89,6 @@ public ReferenceRestriction cloneInstance() {
private String createPropertyNamePrefix(RefFilter filter) throws QueryException {
QueryContext context = getContext();

// ItemPath path = RUtil.createFullPath(filter);
ItemPath path = filter.getFullPath();

StringBuilder sb = new StringBuilder();
Expand All @@ -99,7 +98,7 @@ private String createPropertyNamePrefix(RefFilter filter) throws QueryException
sb.append('.');
}

List<Definition> definitions = createDefinitionPath(path, context);
List<Definition> definitions = createDefinitionPath(path);
ReferenceDefinition refDefinition = getReferenceDefinition(definitions, filter);
if (refDefinition.isEmbedded()) {
sb.append(refDefinition.getJpaName());
Expand Down

0 comments on commit 7e448e7

Please sign in to comment.