diff --git a/modules/global/src/com/haulmont/cuba/core/global/Security.java b/modules/global/src/com/haulmont/cuba/core/global/Security.java index 536fab22e1..a149d5593a 100644 --- a/modules/global/src/com/haulmont/cuba/core/global/Security.java +++ b/modules/global/src/com/haulmont/cuba/core/global/Security.java @@ -141,4 +141,6 @@ public interface Security { * Check if there are registered memory constraints of specified {@code operationTypes} for the metaClass or it's original metaClass */ boolean hasInMemoryConstraints(MetaClass metaClass, ConstraintOperationType... operationTypes); + + Object evaluateConstraintScript(Entity entity, String groovyScript); } \ No newline at end of file diff --git a/modules/global/src/com/haulmont/cuba/core/sys/SecurityImpl.java b/modules/global/src/com/haulmont/cuba/core/sys/SecurityImpl.java index 2cbb45a7bc..9a89ce5a76 100644 --- a/modules/global/src/com/haulmont/cuba/core/sys/SecurityImpl.java +++ b/modules/global/src/com/haulmont/cuba/core/sys/SecurityImpl.java @@ -207,13 +207,8 @@ public class SecurityImpl implements Security { String metaClassName = entity.getMetaClass().getName(); String groovyScript = constraint.getGroovyScript(); if (constraint.getCheckType().memory() && StringUtils.isNotBlank(groovyScript)) { - Map context = new HashMap<>(); - context.put("__entity__", metadataTools.deepCopy(entity)); // copy to avoid implicit modification - context.put("parse", new MethodClosure(this, "parseValue")); - context.put("userSession", userSessionSource.getUserSession()); - fillGroovyConstraintsContext(context); try { - Object o = scripting.evaluateGroovy(groovyScript.replace("{E}", "__entity__"), context); + Object o = evaluateConstraintScript(entity, groovyScript); if (Boolean.FALSE.equals(o)) { log.trace("Entity does not match security constraint. Entity class [{}]. Entity [{}]. Constraint [{}].", metaClassName, entity.getId(), constraint.getCheckType()); @@ -228,6 +223,16 @@ public class SecurityImpl implements Security { return true; } + @Override + public Object evaluateConstraintScript(Entity entity, String groovyScript) { + Map context = new HashMap<>(); + context.put("__entity__", metadataTools.deepCopy(entity)); // copy to avoid implicit modification + context.put("parse", new MethodClosure(this, "parseValue")); + context.put("userSession", userSessionSource.getUserSession()); + fillGroovyConstraintsContext(context); + return scripting.evaluateGroovy(groovyScript.replace("{E}", "__entity__"), context); + } + /** * Override if you need specific context variables in Groovy constraints. * diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/edit/ConstraintEditor.java b/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/edit/ConstraintEditor.java index 7c55db93da..2a0f9b8d83 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/edit/ConstraintEditor.java +++ b/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/edit/ConstraintEditor.java @@ -17,6 +17,7 @@ package com.haulmont.cuba.gui.app.security.constraint.edit; +import com.google.common.base.Strings; import com.haulmont.bali.util.Dom4j; import com.haulmont.chile.core.model.MetaClass; import com.haulmont.cuba.core.global.*; @@ -45,6 +46,7 @@ import com.haulmont.cuba.security.entity.ConstraintCheckType; import com.haulmont.cuba.security.entity.ConstraintOperationType; import com.haulmont.cuba.security.entity.FilterEntity; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.exception.ExceptionUtils; import org.dom4j.Element; import javax.inject.Inject; @@ -117,6 +119,9 @@ public class ConstraintEditor extends AbstractEditor { @Inject protected UserManagementService userManagementService; + @Inject + protected Security security; + protected Map entities; protected static final String SESSION_PREFIX = "session$"; @@ -317,12 +322,10 @@ public class ConstraintEditor extends AbstractEditor { } public void testConstraint() { - Constraint constraint = (Constraint) getItem(); + Constraint constraint = getItem(); String entityName = constraint.getEntityName(); if (validateAll()) { String baseQueryString = "select e from " + entityName + " e"; - String resultQueryStr = null; - try { QueryTransformer transformer = QueryTransformerFactory.createTransformer(baseQueryString); if (StringUtils.isNotBlank(constraint.getJoinClause())) { @@ -337,7 +340,6 @@ public class ConstraintEditor extends AbstractEditor { datasource.setQuery(transformer.getResult()); datasource.refresh(); - showNotification(getMessage("notification.success"), NotificationType.HUMANIZED); } catch (JpqlSyntaxException e) { StringBuilder stringBuilder = new StringBuilder(); for (ErrorRec rec : e.getErrorRecs()) { @@ -345,10 +347,35 @@ public class ConstraintEditor extends AbstractEditor { } showMessageDialog(getMessage("notification.error"), formatMessage("notification.syntaxErrors", stringBuilder), MessageType.WARNING_HTML); + return; } catch (Exception e) { + String msg; + Throwable rootCause = ExceptionUtils.getRootCause(e); + if (rootCause == null) + rootCause = e; + if (rootCause instanceof RemoteException) { + List causes = ((RemoteException) rootCause).getCauses(); + RemoteException.Cause cause = causes.get(causes.size() - 1); + msg = cause.getThrowable() != null ? cause.getThrowable().toString() : cause.getClassName() + ": " + cause.getMessage(); + } else { + msg = rootCause.toString(); + } showMessageDialog(getMessage("notification.error"), - formatMessage("notification.runtimeError", resultQueryStr, e.getMessage()), MessageType.WARNING_HTML); + formatMessage("notification.runtimeError", msg), MessageType.WARNING_HTML); + return; } + + if (!Strings.isNullOrEmpty(constraint.getGroovyScript())) { + try { + security.evaluateConstraintScript(metadata.create(entityName), constraint.getGroovyScript()); + } catch (Exception e) { + showMessageDialog(getMessage("notification.error"), + formatMessage("notification.scriptRuntimeError", e.toString()), MessageType.WARNING_HTML); + return; + } + } + + showNotification(getMessage("notification.success"), NotificationType.HUMANIZED); } } } \ No newline at end of file diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/messages.properties b/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/messages.properties index b135166532..f3568801c5 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/messages.properties +++ b/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/messages.properties @@ -48,7 +48,8 @@ code=Code type=Type notification.entityIsEmpty=Please select entity name -notification.syntaxErrors=The following syntax errors found while parsing 'where' and 'join' clauses:
%s -notification.runtimeError=An error occurred while running resulting query
[%s]
%s +notification.syntaxErrors=Syntax errors found while parsing 'where' and 'join' clauses:
%s +notification.runtimeError=An error occurred while running resulting query.

%s +notification.scriptRuntimeError=An error occurred while evaluating Groovy script.

%s notification.error=Error -notification.success=The constraint has been successfully checked +notification.success=The constraint is syntactically correct diff --git a/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/messages_ru.properties b/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/messages_ru.properties index 1409d97067..1e55a597e1 100644 --- a/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/messages_ru.properties +++ b/modules/gui/src/com/haulmont/cuba/gui/app/security/constraint/messages_ru.properties @@ -45,7 +45,8 @@ code=Код type=Тип notification.entityIsEmpty=Пожалуйста выберите имя сущности -notification.syntaxErrors=В операторах Where и Join обнаружены следующие синтаксические ошибки:
%s -notification.runtimeError=При запуске результирующего запроса
[%s] произошла ошибка:
%s +notification.syntaxErrors=В операторах Where и Join обнаружены синтаксические ошибки:
%s +notification.runtimeError=При запуске результирующего запроса произошла ошибка.

%s +notification.scriptRuntimeError=При запуске скрипта Groovy произошла ошибка.

%s notification.error=Ошибка -notification.success=Проверка успешно завершена \ No newline at end of file +notification.success=Ограничение синтаксически корректно \ No newline at end of file