From 31fa5f8a988b99d31e3967087c89645dd8461fea Mon Sep 17 00:00:00 2001 From: technokrat Date: Fri, 25 Sep 2020 12:06:42 +0300 Subject: [PATCH 01/12] Tnms #7817 define version of jackson 2.5.5 which is used in tnms-wfe --- wfe-app/pom.xml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/wfe-app/pom.xml b/wfe-app/pom.xml index 25391afa4a..dfe92141fc 100644 --- a/wfe-app/pom.xml +++ b/wfe-app/pom.xml @@ -25,6 +25,7 @@ 4.2.1 + 2.5.5 false java:global/runawfe/${jar.name}-${project.version}/${bean.name}!${interface.class.name} java:jboss/datasources/ExampleDS @@ -298,6 +299,21 @@ jar 1.1 + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + org.testng From 0df4015988aab214a7e4a79978d44eaec7ab9bf9 Mon Sep 17 00:00:00 2001 From: dataobject Date: Tue, 19 Jan 2021 21:38:17 +0300 Subject: [PATCH 02/12] RM1795 --- .../ru/runa/wfe/office/storage/ConditionProcessor.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wfe-office/src/main/java/ru/runa/wfe/office/storage/ConditionProcessor.java b/wfe-office/src/main/java/ru/runa/wfe/office/storage/ConditionProcessor.java index b30768482c..f97c38f8be 100644 --- a/wfe-office/src/main/java/ru/runa/wfe/office/storage/ConditionProcessor.java +++ b/wfe-office/src/main/java/ru/runa/wfe/office/storage/ConditionProcessor.java @@ -65,7 +65,7 @@ private static void clear() { previousOperator = ""; } - private static String parse(String condition, Map attributes, VariableProvider variableProvider) { + private static String parse(String condition, Map attributes, VariableProvider variableProvider) throws Exception { condition = hideSpacesInAttributeNames(condition); StringBuilder sb = new StringBuilder(); StringTokenizer st = new StringTokenizer(condition); @@ -127,13 +127,16 @@ private static long getTime(String source) { } } - private static StringBuilder appendAttribute(StringBuilder sb, Map variables, String token) { + private static StringBuilder appendAttribute(StringBuilder sb, Map variables, String token) throws Exception { String var = token.substring(1, token.length() - 1); if (variables.keySet().contains(var)) { Object obj = variables.get(var); previousAttributeValue = obj; sb.append(formatParameterValue(obj)); } + else { + throw new Exception("Atttribute " + token + " does not exist."); + } return sb; } From d3b847725093f19134cb4875d916ba99f8a0364f Mon Sep 17 00:00:00 2001 From: Sergey Inyakin Date: Fri, 5 Mar 2021 10:26:17 +0200 Subject: [PATCH 03/12] =?UTF-8?q?#2124=20=D0=9F=D0=B5=D1=80=D0=B5=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA=20=D0=B2=20?= =?UTF-8?q?=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D0=BF?= =?UTF-8?q?=D1=83=D0=BD=D0=BA=D1=82=20=D0=BC=D0=B5=D0=BD=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wfe/security/SecuredObjectFactory.java | 2 + .../runa/wfe/security/SecuredObjectType.java | 2 + .../runa/wfe/security/SecuredSingleton.java | 1 + ...ckSingletonPermissionAndForwardAction.java | 2 + .../ru/runa/common/web/MessagesCommon.java | 2 + .../ru/runa/common/web/tag/TabHeaderTag.java | 6 ++ .../main/webapp/WEB-INF/af/manage_errors.jsp | 83 +++++++++++++++++++ .../main/webapp/WEB-INF/af/manage_system.jsp | 61 -------------- .../webapp/WEB-INF/classes/struts.properties | 1 + .../WEB-INF/classes/struts_ru.properties | 1 + .../src/main/webapp/WEB-INF/struts-config.xml | 6 +- 11 files changed, 104 insertions(+), 63 deletions(-) create mode 100644 wfe-web/src/main/webapp/WEB-INF/af/manage_errors.jsp diff --git a/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectFactory.java b/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectFactory.java index 8b8067a387..0b98382404 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectFactory.java +++ b/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectFactory.java @@ -188,6 +188,8 @@ List getByNames(Set names) { } }); + add(SecuredSingleton.ERRORS); + add(SecuredObjectType.EXECUTOR, new Loader(SecuredObjectType.EXECUTOR) { @Override public SecuredObject findById(Long id) { diff --git a/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectType.java b/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectType.java index 6c6b845c4f..df4ae8bacf 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectType.java +++ b/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectType.java @@ -123,6 +123,8 @@ public boolean equals(Object obj) { public static final SecuredObjectType DEFINITION = new SecuredObjectType("DEFINITION", false); + public static final SecuredObjectType ERRORS = new SecuredObjectType("ERRORS", true); + public static final SecuredObjectType EXECUTOR = new SecuredObjectType("EXECUTOR", false); public static final SecuredObjectType PROCESS = new SecuredObjectType("PROCESS", false); diff --git a/wfe-core/src/main/java/ru/runa/wfe/security/SecuredSingleton.java b/wfe-core/src/main/java/ru/runa/wfe/security/SecuredSingleton.java index f7bbff62a6..81f0c7aae2 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/security/SecuredSingleton.java +++ b/wfe-core/src/main/java/ru/runa/wfe/security/SecuredSingleton.java @@ -57,6 +57,7 @@ public final SecuredObjectType getSecuredObjectType() { // Alphabetically, please: public static final SecuredSingleton BOTSTATIONS = new SecuredSingleton(SecuredObjectType.BOTSTATIONS); + public static final SecuredSingleton ERRORS = new SecuredSingleton(SecuredObjectType.ERRORS); public static final SecuredSingleton RELATIONS = new SecuredSingleton(SecuredObjectType.RELATIONS); public static final SecuredSingleton REPORTS = new SecuredSingleton(SecuredObjectType.REPORTS); public static final SecuredSingleton SYSTEM = new SecuredSingleton(SecuredObjectType.SYSTEM); diff --git a/wfe-web/src/main/java/ru/runa/af/web/action/CheckSingletonPermissionAndForwardAction.java b/wfe-web/src/main/java/ru/runa/af/web/action/CheckSingletonPermissionAndForwardAction.java index fd02bdf21d..0525152312 100644 --- a/wfe-web/src/main/java/ru/runa/af/web/action/CheckSingletonPermissionAndForwardAction.java +++ b/wfe-web/src/main/java/ru/runa/af/web/action/CheckSingletonPermissionAndForwardAction.java @@ -15,6 +15,7 @@ import ru.runa.wfe.service.delegate.Delegates; import ru.runa.wfe.user.User; +import static ru.runa.wfe.security.SecuredObjectType.ERRORS; import static ru.runa.wfe.security.SecuredObjectType.SYSTEM; public class CheckSingletonPermissionAndForwardAction extends ActionBase { @@ -31,6 +32,7 @@ private static class Config { private static final String TAB_FORWARD_NAME_PARAMETER_NAME = "tabForwardName"; private static final HashMap configs = new HashMap() {{ put(SYSTEM, new Config(Permission.READ, "/WEB-INF/af/manage_system.jsp")); + put(ERRORS, new Config(Permission.READ, "/WEB-INF/af/manage_errors.jsp")); }}; @Override diff --git a/wfe-web/src/main/java/ru/runa/common/web/MessagesCommon.java b/wfe-web/src/main/java/ru/runa/common/web/MessagesCommon.java index 9848125a20..57e68b1a1b 100644 --- a/wfe-web/src/main/java/ru/runa/common/web/MessagesCommon.java +++ b/wfe-web/src/main/java/ru/runa/common/web/MessagesCommon.java @@ -23,6 +23,8 @@ public final class MessagesCommon { public static final StrutsMessage MAIN_MENU_ITEM_DATA_SOURCES = new StrutsMessage("manage_data_sources"); // Forward menu (left main menu items) -> System. public static final StrutsMessage MAIN_MENU_ITEM_SYSTEM = new StrutsMessage("manage_system"); + // Forward menu (left main menu items) -> Errors. + public static final StrutsMessage MAIN_MENU_ITEM_ERRORS = new StrutsMessage("manage_errors"); // Forward menu (left main menu items) -> Settings. public static final StrutsMessage MAIN_MENU_ITEM_SETTINGS = new StrutsMessage("manage_settings"); // Forward menu (left main menu items) -> Logs. diff --git a/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java b/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java index c5b0937517..55e240af30 100644 --- a/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java +++ b/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java @@ -67,6 +67,7 @@ public class TabHeaderTag extends TagSupport { FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_DATA_SOURCES, SecuredSingleton.DATASOURCES)); FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_INTERNAL_STORAGE, null, true)); FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_SYSTEM, SecuredSingleton.SYSTEM)); + FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_ERRORS, SecuredSingleton.ERRORS)); FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_SETTINGS, null, true)); FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_LOGS)); FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_OBSERVABLE_TASKS)); @@ -153,6 +154,11 @@ private boolean isMenuForwardVisible(MenuForward menuForward) { && Delegates.getAuthorizationService().isAllowedForAny(getUser(), Permission.VIEW_TASKS, SecuredObjectType.EXECUTOR)) { return true; } + if (menuForward.menuMessage.getKey().equals("manage_errors") + && Delegates.getSystemService().getSystemErrors(getUser()).isEmpty() + && Delegates.getSystemService().getAllProcessErrors(getUser()).isEmpty()) { + return false; + } if (menuForward.object != null) { return Delegates.getAuthorizationService().isAllowed(getUser(), Permission.READ, menuForward.object); } else { diff --git a/wfe-web/src/main/webapp/WEB-INF/af/manage_errors.jsp b/wfe-web/src/main/webapp/WEB-INF/af/manage_errors.jsp new file mode 100644 index 0000000000..bdf55164ad --- /dev/null +++ b/wfe-web/src/main/webapp/WEB-INF/af/manage_errors.jsp @@ -0,0 +1,83 @@ +<%@ page pageEncoding="UTF-8" %> +<%@ page import="ru.runa.common.Version"%> +<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles"%> +<%@ taglib uri="/WEB-INF/wf.tld" prefix="wf" %> +<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%> +<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%> + + + + + + + + + + + +
+ +
+ +
+
+ +
+ +
+
+ > +
+
+ + +
\ No newline at end of file diff --git a/wfe-web/src/main/webapp/WEB-INF/af/manage_system.jsp b/wfe-web/src/main/webapp/WEB-INF/af/manage_system.jsp index 59dc642910..500e009009 100644 --- a/wfe-web/src/main/webapp/WEB-INF/af/manage_system.jsp +++ b/wfe-web/src/main/webapp/WEB-INF/af/manage_system.jsp @@ -28,42 +28,10 @@ editScript($(this).attr("fileName"), "", "", ""); }); }); - $("#systemErrorsButton").click(function() { - if (systemErrorsVisible) { - $("#systemErrorsContentDiv").hide(); - $("#systemErrorsImg").attr("src", "/wfe/images/view_setup_hidden.gif"); - systemErrorsVisible = false; - } else { - $("#systemErrorsContentDiv").show(); - $("#systemErrorsImg").attr("src", "/wfe/images/view_setup_visible.gif"); - systemErrorsVisible = true; - } - }); - $("#processErrorsButton").click(function() { - if (processErrorsVisible) { - $("#processErrorsContentDiv").hide(); - $("#processErrorsImg").attr("src", "/wfe/images/view_setup_hidden.gif"); - processErrorsVisible = false; - } else { - $("#processErrorsContentDiv").show(); - $("#processErrorsImg").attr("src", "/wfe/images/view_setup_visible.gif"); - processErrorsVisible = true; - } - }); - $("div.processErrorsFilter input").change(function() { - var typeLabel = $(this).closest("label").text(); - var tds = $("#processErrorsContentDiv table tr").find("td:eq(0)").filter(":contains(" + typeLabel + ")"); - if ($(this).prop("checked")) { - tds.closest("tr").show(); - } else { - tds.closest("tr").hide(); - } - }); }); - @@ -150,35 +118,6 @@ - - - -
- -
- -
-
- -
- -
-
- > -
diff --git a/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties b/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties index d9c661974d..7b7ef0a2cb 100644 --- a/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties +++ b/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties @@ -428,6 +428,7 @@ manage_settings = Settings manage_data_sources = Data sources manage_system = System +manage_errors = Errors manage_tasks = Task list manage_observable_tasks = Observable tasks diff --git a/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties b/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties index ef820261b5..52d5e881e1 100644 --- a/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties +++ b/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties @@ -425,6 +425,7 @@ manage_settings = \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 manage_data_sources = \u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 manage_system = \u0421\u0438\u0441\u0442\u0435\u043c\u0430 +manage_errors = \u041e\u0448\u0438\u0431\u043a\u0438 manage_tasks = \u0421\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u043d\u0438\u0439 manage_observable_tasks = \u0417\u0430\u0434\u0430\u043d\u0438\u044f \u0441\u043e\u0442\u0440\u0443\u0434\u043d\u0438\u043a\u043e\u0432 diff --git a/wfe-web/src/main/webapp/WEB-INF/struts-config.xml b/wfe-web/src/main/webapp/WEB-INF/struts-config.xml index a8c99ce437..3b682a1566 100644 --- a/wfe-web/src/main/webapp/WEB-INF/struts-config.xml +++ b/wfe-web/src/main/webapp/WEB-INF/struts-config.xml @@ -76,6 +76,7 @@ + @@ -251,8 +252,8 @@ - - + + @@ -681,6 +682,7 @@ parameter="/WEB-INF/af/edit_substitution_criteria.jsp" /> + From aad63d3b2a749de7038d81533f0fc287e45f6439 Mon Sep 17 00:00:00 2001 From: Sergey Inyakin Date: Fri, 5 Mar 2021 13:45:55 +0200 Subject: [PATCH 04/12] #2124 For Administrator Only --- .../ru/runa/common/web/tag/TabHeaderTag.java | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java b/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java index 55e240af30..321758cba5 100644 --- a/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java +++ b/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java @@ -67,7 +67,7 @@ public class TabHeaderTag extends TagSupport { FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_DATA_SOURCES, SecuredSingleton.DATASOURCES)); FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_INTERNAL_STORAGE, null, true)); FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_SYSTEM, SecuredSingleton.SYSTEM)); - FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_ERRORS, SecuredSingleton.ERRORS)); + FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_ERRORS, SecuredSingleton.ERRORS, true)); FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_SETTINGS, null, true)); FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_LOGS)); FORWARDS.add(new MenuForward(MessagesCommon.MAIN_MENU_ITEM_OBSERVABLE_TASKS)); @@ -138,14 +138,18 @@ private User getUser() { private boolean isMenuForwardVisible(MenuForward menuForward) { try { if (menuForward.forAdministratorOnly) { + if (!Delegates.getExecutorService().isAdministrator(getUser())) { + return false; + } if (menuForward.menuMessage.getKey().equals(MessagesCommon.MAIN_MENU_ITEM_INTERNAL_STORAGE.getKey())) { - if (DataSourceStorage.getNames().contains(DataSourceStuff.INTERNAL_STORAGE_DATA_SOURCE_NAME)) { - if (!(DataSourceStorage.getDataSource(DataSourceStuff.INTERNAL_STORAGE_DATA_SOURCE_NAME) instanceof ExcelDataSource)) { - return false; - } - } + return DataSourceStorage.getNames().contains(DataSourceStuff.INTERNAL_STORAGE_DATA_SOURCE_NAME) + && DataSourceStorage.getDataSource(DataSourceStuff.INTERNAL_STORAGE_DATA_SOURCE_NAME) instanceof ExcelDataSource; + } + if (menuForward.menuMessage.getKey().equals(MessagesCommon.MAIN_MENU_ITEM_ERRORS.getKey())) { + return !Delegates.getSystemService().getSystemErrors(getUser()).isEmpty() + && !Delegates.getSystemService().getAllProcessErrors(getUser()).isEmpty(); } - return Delegates.getExecutorService().isAdministrator(getUser()); + return true; } if (menuForward.menuMessage.getKey().equals("view_logs")) { return Delegates.getAuthorizationService().isAllowed(getUser(), Permission.VIEW_LOGS, SecuredSingleton.SYSTEM); @@ -154,11 +158,6 @@ private boolean isMenuForwardVisible(MenuForward menuForward) { && Delegates.getAuthorizationService().isAllowedForAny(getUser(), Permission.VIEW_TASKS, SecuredObjectType.EXECUTOR)) { return true; } - if (menuForward.menuMessage.getKey().equals("manage_errors") - && Delegates.getSystemService().getSystemErrors(getUser()).isEmpty() - && Delegates.getSystemService().getAllProcessErrors(getUser()).isEmpty()) { - return false; - } if (menuForward.object != null) { return Delegates.getAuthorizationService().isAllowed(getUser(), Permission.READ, menuForward.object); } else { From 6712e888e1c6cbaea457217b8c88db8bc46d2014 Mon Sep 17 00:00:00 2001 From: Sergey Inyakin Date: Fri, 5 Mar 2021 18:07:05 +0200 Subject: [PATCH 05/12] =?UTF-8?q?#2124=20=D0=9D=D0=B5=20=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=D1=8C=D0=BD=D0=BE=D0=B5=20=D1=83=D1=81=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/ru/runa/common/web/tag/TabHeaderTag.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java b/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java index 321758cba5..174375bd2d 100644 --- a/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java +++ b/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java @@ -32,6 +32,8 @@ import ru.runa.common.web.Resources; import ru.runa.common.web.StrutsMessage; import ru.runa.common.web.TabHttpSessionHelper; +import ru.runa.wfe.commons.error.ProcessError; +import ru.runa.wfe.commons.error.SystemError; import ru.runa.wfe.commons.web.PortletUrlType; import ru.runa.wfe.datasource.DataSourceStorage; import ru.runa.wfe.datasource.DataSourceStuff; @@ -147,7 +149,7 @@ private boolean isMenuForwardVisible(MenuForward menuForward) { } if (menuForward.menuMessage.getKey().equals(MessagesCommon.MAIN_MENU_ITEM_ERRORS.getKey())) { return !Delegates.getSystemService().getSystemErrors(getUser()).isEmpty() - && !Delegates.getSystemService().getAllProcessErrors(getUser()).isEmpty(); + || !Delegates.getSystemService().getAllProcessErrors(getUser()).isEmpty(); } return true; } From e0513473d5203ed78d39b005dbefea629b5f73cd Mon Sep 17 00:00:00 2001 From: Sergey Inyakin Date: Wed, 10 Mar 2021 20:38:31 +0200 Subject: [PATCH 06/12] =?UTF-8?q?#2124=20=D0=9F=D1=83=D0=BD=D0=BA=D1=82=20?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D1=8E=20"=D0=9E=D1=88=D0=B8=D0=B1=D0=BA?= =?UTF-8?q?=D0=B8"=20=D0=BF=D0=BE=D0=BA=D0=B0=D0=B7=D1=8B=D0=B2=D0=B0?= =?UTF-8?q?=D0=B5=D1=82=D1=81=D1=8F=20=D0=B2=D1=81=D0=B5=D0=B3=D0=B4=D0=B0?= =?UTF-8?q?=20(=D0=B4=D0=BB=D1=8F=20=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=B0=D1=82=D0=BE=D1=80=D0=B0).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/ru/runa/common/web/tag/TabHeaderTag.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java b/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java index 174375bd2d..08bad9a452 100644 --- a/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java +++ b/wfe-web/src/main/java/ru/runa/common/web/tag/TabHeaderTag.java @@ -32,8 +32,6 @@ import ru.runa.common.web.Resources; import ru.runa.common.web.StrutsMessage; import ru.runa.common.web.TabHttpSessionHelper; -import ru.runa.wfe.commons.error.ProcessError; -import ru.runa.wfe.commons.error.SystemError; import ru.runa.wfe.commons.web.PortletUrlType; import ru.runa.wfe.datasource.DataSourceStorage; import ru.runa.wfe.datasource.DataSourceStuff; @@ -147,10 +145,6 @@ private boolean isMenuForwardVisible(MenuForward menuForward) { return DataSourceStorage.getNames().contains(DataSourceStuff.INTERNAL_STORAGE_DATA_SOURCE_NAME) && DataSourceStorage.getDataSource(DataSourceStuff.INTERNAL_STORAGE_DATA_SOURCE_NAME) instanceof ExcelDataSource; } - if (menuForward.menuMessage.getKey().equals(MessagesCommon.MAIN_MENU_ITEM_ERRORS.getKey())) { - return !Delegates.getSystemService().getSystemErrors(getUser()).isEmpty() - || !Delegates.getSystemService().getAllProcessErrors(getUser()).isEmpty(); - } return true; } if (menuForward.menuMessage.getKey().equals("view_logs")) { From 3c69b3e376d957158a950d57bb62823c5902140d Mon Sep 17 00:00:00 2001 From: Vyacheslav Chulkin Date: Tue, 16 Mar 2021 13:57:19 +0300 Subject: [PATCH 07/12] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=20=D0=B7=D0=B0=D0=B3=D0=BE?= =?UTF-8?q?=D0=BB=D0=BE=D0=B2=D0=BE=D0=BA=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8?= =?UTF-8?q?=D1=86=D1=8B=20=D0=B2=20=D0=BE=D1=82=D1=87=D0=B5=D1=82=D0=B0?= =?UTF-8?q?=D1=85=20"=D0=9F=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80?= =?UTF-8?q?=D1=8B,=20=D0=BD=D0=B5=D0=BE=D0=B1=D1=85=D0=BE=D0=B4=D0=B8?= =?UTF-8?q?=D0=BC=D1=8B=D0=B5=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BE=D1=82=D1=87?= =?UTF-8?q?=D1=91=D1=82=D0=B0"=20->=20"=D0=9F=D0=B0=D1=80=D0=B0=D0=BC?= =?UTF-8?q?=D0=B5=D1=82=D1=80=D1=8B=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BE=D1=82?= =?UTF-8?q?=D1=87=D1=91=D1=82=D0=B0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wfe-web/src/main/webapp/WEB-INF/classes/struts.properties | 2 +- wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties b/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties index d9c661974d..23a2f53be6 100644 --- a/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties +++ b/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties @@ -534,7 +534,7 @@ reports.report.variable.position = Position reports.report.variable.required = Required reports.report.variable.type = Type reports.report.variable.username = Visible to user name -reports.report.variables = Parameters, required to build report +reports.report.variables = Parameters for building a report ru.runa.wf.web.actor.does.not.exists.exception = Actor "{0}" does not exist ru.runa.wf.web.group.does.not.exists.exception = Group "{0}" does not exist diff --git a/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties b/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties index ef820261b5..dc54f975b7 100644 --- a/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties +++ b/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties @@ -533,7 +533,7 @@ reports.report.variable.position = \u041f\u043e\u0437\u0438\u0446\u0438\u044f reports.report.variable.required = \u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c reports.report.variable.type = \u0422\u0438\u043f reports.report.variable.username = \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435, \u0432\u0438\u0434\u0438\u043c\u043e\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e -reports.report.variables = \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043e\u0442\u0447\u0451\u0442\u0430 +reports.report.variables = \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043e\u0442\u0447\u0451\u0442\u0430 ru.runa.wf.web.actor.does.not.exists.exception = \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c "{0}" \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 ru.runa.wf.web.group.does.not.exists.exception = \u0413\u0440\u0443\u043f\u043f\u0430 "{0}" \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 From 0cfee67ac4cd8a1c12c10c38268a2599662e3e79 Mon Sep 17 00:00:00 2001 From: Kolesnikov Victor Date: Tue, 16 Mar 2021 15:52:44 +0300 Subject: [PATCH 08/12] RM1746 https://rm.processtech.ru/issues/1746 --- .../runa/wfe/security/SecuredObjectType.java | 4 +-- .../runa/wfe/security/SecuredSingleton.java | 2 +- .../af/web/tag/ManagePermissionsFormTag.java | 36 ++++++++++++++++++- .../webapp/WEB-INF/classes/struts.properties | 13 +++++++ .../WEB-INF/classes/struts_ru.properties | 13 +++++++ wfe-web/src/main/webapp/css/main.css | 7 ++-- 6 files changed, 69 insertions(+), 6 deletions(-) diff --git a/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectType.java b/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectType.java index 6c6b845c4f..eea748c9e8 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectType.java +++ b/wfe-core/src/main/java/ru/runa/wfe/security/SecuredObjectType.java @@ -121,6 +121,8 @@ public boolean equals(Object obj) { public static final SecuredObjectType BOTSTATIONS = new SecuredObjectType("BOTSTATIONS", true); + public static final SecuredObjectType DATASOURCES = new SecuredObjectType("DATASOURCES", true); + public static final SecuredObjectType DEFINITION = new SecuredObjectType("DEFINITION", false); public static final SecuredObjectType EXECUTOR = new SecuredObjectType("EXECUTOR", false); @@ -134,7 +136,5 @@ public boolean equals(Object obj) { public static final SecuredObjectType REPORT = new SecuredObjectType("REPORT", REPORTS); public static final SecuredObjectType SYSTEM = new SecuredObjectType("SYSTEM", true); - - public static final SecuredObjectType DATASOURCES = new SecuredObjectType("DATASOURCES", true); } diff --git a/wfe-core/src/main/java/ru/runa/wfe/security/SecuredSingleton.java b/wfe-core/src/main/java/ru/runa/wfe/security/SecuredSingleton.java index f7bbff62a6..169c9ea795 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/security/SecuredSingleton.java +++ b/wfe-core/src/main/java/ru/runa/wfe/security/SecuredSingleton.java @@ -57,8 +57,8 @@ public final SecuredObjectType getSecuredObjectType() { // Alphabetically, please: public static final SecuredSingleton BOTSTATIONS = new SecuredSingleton(SecuredObjectType.BOTSTATIONS); + public static final SecuredSingleton DATASOURCES = new SecuredSingleton(SecuredObjectType.DATASOURCES); public static final SecuredSingleton RELATIONS = new SecuredSingleton(SecuredObjectType.RELATIONS); public static final SecuredSingleton REPORTS = new SecuredSingleton(SecuredObjectType.REPORTS); public static final SecuredSingleton SYSTEM = new SecuredSingleton(SecuredObjectType.SYSTEM); - public static final SecuredSingleton DATASOURCES = new SecuredSingleton(SecuredObjectType.DATASOURCES); } diff --git a/wfe-web/src/main/java/ru/runa/af/web/tag/ManagePermissionsFormTag.java b/wfe-web/src/main/java/ru/runa/af/web/tag/ManagePermissionsFormTag.java index 2599c28c34..530aee9a44 100644 --- a/wfe-web/src/main/java/ru/runa/af/web/tag/ManagePermissionsFormTag.java +++ b/wfe-web/src/main/java/ru/runa/af/web/tag/ManagePermissionsFormTag.java @@ -18,21 +18,30 @@ package ru.runa.af.web.tag; import com.google.common.base.Predicate; +import com.google.common.base.Strings; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import org.apache.ecs.html.Input; import org.apache.ecs.html.TD; +import org.apache.ecs.wml.A; import org.tldgen.annotations.BodyContent; import ru.runa.af.web.action.UpdatePermissionsAction; import ru.runa.common.web.Commons; +import ru.runa.common.web.Messages; import ru.runa.common.web.MessagesCommon; import ru.runa.common.web.html.PermissionTableBuilder; import ru.runa.common.web.tag.SecuredObjectFormTag2; +import ru.runa.wfe.definition.Deployment; +import ru.runa.wfe.execution.Process; +import ru.runa.wfe.execution.dto.WfProcess; +import ru.runa.wfe.relation.Relation; +import ru.runa.wfe.report.dto.WfReport; import ru.runa.wfe.security.ApplicablePermissions; import ru.runa.wfe.security.Permission; import ru.runa.wfe.security.SecuredObject; import ru.runa.wfe.security.SecuredObjectType; import ru.runa.wfe.service.delegate.Delegates; +import ru.runa.wfe.user.Executor; import ru.runa.wfe.user.SystemExecutors; @org.tldgen.annotations.Tag(bodyContent = BodyContent.JSP, name = "managePermissionsForm") @@ -80,6 +89,31 @@ protected String getSubmitButtonName() { @Override protected String getTitle() { - return MessagesCommon.TITLE_PERMISSION_OWNERS.message(pageContext); + return MessagesCommon.TITLE_PERMISSION_OWNERS.message(pageContext) + securedObjectLabel(getSecuredObject()); + } + + private String securedObjectLabel(SecuredObject so) { + final String linkClass = "permissionLink"; + String type = so.getSecuredObjectType().getName(); + String name = null; + if (so instanceof Deployment) { + Deployment deployment = (Deployment) so; + name = new A("manage_process_definition.do?id=" + deployment.getId()).addElement(deployment.getName()).setClass(linkClass).toString(); + } else if (so instanceof Process) { + WfProcess process = Delegates.getExecutionService().getProcess(getUser(), identifiableId); + A processName = (A) new A("manage_process_definition.do?id=" + process.getDefinitionId()).addElement(process.getName()) + .setClass(linkClass); + A processId = (A) new A("manage_process.do?id=" + identifiableId).addElement(identifiableId.toString()).setClass(linkClass); + name = processName + ", Id: " + processId; + } else if (so instanceof Relation) { + name = ((Relation) so).getName(); + } else if (so instanceof Executor) { + type = so.getClass().getSimpleName(); + name = new A("manage_executor.do?id=" + identifiableId).addElement(((Executor) so).getLabel()).setClass(linkClass).toString(); + } else if (so instanceof WfReport) { + name = ((WfReport) so).getName(); + } + return " (" + Messages.getMessage("secured_object_type." + type.toLowerCase(), pageContext) + (Strings.isNullOrEmpty(name) ? "" : ": " + name) + + ")"; } } diff --git a/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties b/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties index 23a2f53be6..053ecfb7cd 100644 --- a/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties +++ b/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties @@ -717,3 +717,16 @@ view_internal_storage = Internal storage button.view_differences = View differences failed.view_differences = In order to view differences select 2 different versions: left radio for old and right one for new version label.no_differences_found = No difference has been found + +# Secured object specifics +secured_object_type.botstations = Bot stations +secured_object_type.datasources = Data sources +secured_object_type.definition = Process definition +secured_object_type.group = Group +secured_object_type.actor = Actor +secured_object_type.process = Process +secured_object_type.relations = Relations +secured_object_type.relation = Relation +secured_object_type.reports = Reports +secured_object_type.report = Report +secured_object_type.system = System diff --git a/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties b/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties index dc54f975b7..edbee2719c 100644 --- a/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties +++ b/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties @@ -713,3 +713,16 @@ view_internal_storage = \u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u button.view_differences = \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u0438\u044f failed.view_differences = \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u043e\u0442\u043b\u0438\u0447\u0438\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c 2 \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438: \u0441\u043b\u0435\u0432\u0430 - \u0434\u043b\u044f \u0441\u0442\u0430\u0440\u043e\u0439, \u0441\u043f\u0440\u0430\u0432\u0430 - \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0439 label.no_differences_found = \u041c\u0435\u0436\u0434\u0443 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e + +# Secured object specifics +secured_object_type.botstations = \u0411\u043e\u0442-\u0441\u0442\u0430\u043d\u0446\u0438\u0438 +secured_object_type.datasources = \u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 +secured_object_type.definition = \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 +secured_object_type.group = \u0413\u0440\u0443\u043f\u043f\u0430 +secured_object_type.actor = \u0410\u043a\u0442\u043e\u0440 +secured_object_type.process = \u041f\u0440\u043e\u0446\u0435\u0441\u0441 +secured_object_type.relations = \u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f +secured_object_type.relation = \u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 +secured_object_type.reports = \u041e\u0442\u0447\u0451\u0442\u044b +secured_object_type.report = \u041e\u0442\u0447\u0451\u0442 +secured_object_type.system = \u0421\u0438\u0441\u0442\u0435\u043c\u0430 diff --git a/wfe-web/src/main/webapp/css/main.css b/wfe-web/src/main/webapp/css/main.css index 4cd858bbd8..b302deb838 100644 --- a/wfe-web/src/main/webapp/css/main.css +++ b/wfe-web/src/main/webapp/css/main.css @@ -337,7 +337,10 @@ tr.executor_group { #hideSystemMenu.ui-icon-triangle-1-w { background-image: url(images/ui-icons_ffffff_256x240.png); } - td.fontRed { color: red !important; -} \ No newline at end of file +} +a.permissionLink { + background-color: #990000; + color: white; +} From bb253f38e596f851c07b72c2865cb77458c3921e Mon Sep 17 00:00:00 2001 From: Alekseev Mikhail Date: Sun, 21 Mar 2021 12:08:57 +0300 Subject: [PATCH 09/12] =?UTF-8?q?#2003=20=D0=9E=D0=B4=D0=B8=D0=BD=D0=BE?= =?UTF-8?q?=D1=87=D0=BD=D1=8B=D0=B9=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=20?= =?UTF-8?q?=D0=B8=D0=B7=20=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=D1=81=D0=BA=D0=B8=D1=85=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=BD=D1=8B=D1=85.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 5a50d5721454600ef338ffdcf8f9eaa0a7ff1547) --- .../AbstractSelectFromUserTypeList.java | 79 +++++++++++++++++++ .../MultipleSelectFromUserTypeList.java | 69 +--------------- .../SingleSelectFromUserTypeList.java | 11 +++ .../main/resources/ftl.form.components.xml | 1 + .../SingleSelectFromUserTypeList.ftl | 22 ++++++ 5 files changed, 117 insertions(+), 65 deletions(-) create mode 100644 wfe-web/src/main/java/ru/runa/wf/web/ftl/component/AbstractSelectFromUserTypeList.java create mode 100644 wfe-web/src/main/java/ru/runa/wf/web/ftl/component/SingleSelectFromUserTypeList.java create mode 100644 wfe-web/src/main/resources/templates/SingleSelectFromUserTypeList.ftl diff --git a/wfe-web/src/main/java/ru/runa/wf/web/ftl/component/AbstractSelectFromUserTypeList.java b/wfe-web/src/main/java/ru/runa/wf/web/ftl/component/AbstractSelectFromUserTypeList.java new file mode 100644 index 0000000000..a7a90e0097 --- /dev/null +++ b/wfe-web/src/main/java/ru/runa/wf/web/ftl/component/AbstractSelectFromUserTypeList.java @@ -0,0 +1,79 @@ +package ru.runa.wf.web.ftl.component; + +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import ru.runa.wfe.commons.TypeConversionUtil; +import ru.runa.wfe.commons.ftl.FormComponentSubmissionHandler; +import ru.runa.wfe.form.Interaction; +import ru.runa.wfe.var.UserTypeMap; +import ru.runa.wfe.var.VariableDefinition; +import ru.runa.wfe.var.dto.WfVariable; + +public abstract class AbstractSelectFromUserTypeList extends AbstractUserTypeList implements FormComponentSubmissionHandler { + + private static final long serialVersionUID = -7344045578574357126L; + + protected abstract boolean isMultiple(); + + @Override + protected UserTypeListModel parseParameters() { + String inputVariableName = getParameterAsString(0); + WfVariable inputVariable = variableProvider.getVariableNotNull(inputVariableName); + String displayVariableName = getParameterAsString(1); + boolean componentView = getParameterAs(boolean.class, 2); + WfVariable displayVariable = variableProvider.getVariableNotNull(displayVariableName); + List displayFields = getMultipleParameter(3); + return new SelectUserTypeListModel(displayVariable, displayFields, componentView, inputVariable); + } + + @Override + public Map extractVariables(Interaction interaction, VariableDefinition variableDefinition, + Map userInput, Map formatErrors) throws Exception { + Object selected = null; + final String variableName = getVariableNameForSubmissionProcessing(); + final String[] indexes = (String[]) userInput.get(variableName); + if (indexes != null) { + List list = getParameterVariableValueNotNull(List.class, 1); + if (isMultiple()) { + selected = new ArrayList<>(indexes.length); + for (String index : indexes) { + ((List) selected).add(list.get(TypeConversionUtil.convertTo(int.class, index))); + } + } else { + selected = list.get(TypeConversionUtil.convertTo(int.class, indexes[0])); + } + } + final Map result = new HashMap<>(1); + result.put(variableName, selected); + return result; + } + + public class SelectUserTypeListModel extends UserTypeListModel { + private final WfVariable inputVariable; + + public SelectUserTypeListModel(WfVariable variable, List attributeNames, boolean componentView, WfVariable inputVariable) { + super(variable, attributeNames, componentView); + this.inputVariable = inputVariable; + } + + public WfVariable getInputVariable() { + return inputVariable; + } + + public String getChecked(TemplateModel arg0) throws TemplateModelException { + boolean checked = false; + if (isMultiple()) { + final UserTypeMap userTypeMap = (UserTypeMap) BEANS_WRAPPER.unwrap(arg0); + final List selectedList = (List) getInputVariable().getValue(); + checked = selectedList != null && selectedList.contains(userTypeMap); + } + return checked ? "checked='true'" : ""; + } + + } + +} diff --git a/wfe-web/src/main/java/ru/runa/wf/web/ftl/component/MultipleSelectFromUserTypeList.java b/wfe-web/src/main/java/ru/runa/wf/web/ftl/component/MultipleSelectFromUserTypeList.java index 1b1459ee03..0c093e62dc 100644 --- a/wfe-web/src/main/java/ru/runa/wf/web/ftl/component/MultipleSelectFromUserTypeList.java +++ b/wfe-web/src/main/java/ru/runa/wf/web/ftl/component/MultipleSelectFromUserTypeList.java @@ -1,73 +1,12 @@ package ru.runa.wf.web.ftl.component; -import java.util.List; -import java.util.Map; +public class MultipleSelectFromUserTypeList extends AbstractSelectFromUserTypeList { -import ru.runa.wfe.commons.TypeConversionUtil; -import ru.runa.wfe.commons.ftl.FormComponentSubmissionHandler; -import ru.runa.wfe.form.Interaction; -import ru.runa.wfe.var.UserTypeMap; -import ru.runa.wfe.var.VariableDefinition; -import ru.runa.wfe.var.dto.WfVariable; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - -import freemarker.template.TemplateModel; -import freemarker.template.TemplateModelException; - -public class MultipleSelectFromUserTypeList extends AbstractUserTypeList implements FormComponentSubmissionHandler { - private static final long serialVersionUID = 1L; - - @Override - protected UserTypeListModel parseParameters() { - String inputVariableName = getParameterAsString(0); - WfVariable inputVariable = variableProvider.getVariableNotNull(inputVariableName); - String displayVariableName = getParameterAsString(1); - boolean componentView = getParameterAs(boolean.class, 2); - WfVariable displayVariable = variableProvider.getVariableNotNull(displayVariableName); - List displayFields = getMultipleParameter(3); - return new SelectUserTypeListModel(displayVariable, displayFields, componentView, inputVariable); - } + private static final long serialVersionUID = 3883878151144701276L; @Override - public Map extractVariables(Interaction interaction, VariableDefinition variableDefinition, - Map userInput, Map formatErrors) throws Exception { - final Map result = Maps.newHashMap(); - List selected = Lists.newArrayList(); - result.put(getVariableNameForSubmissionProcessing(), selected); - String[] indexes = (String[]) userInput.get(getVariableNameForSubmissionProcessing()); - if (indexes != null) { - List list = getParameterVariableValueNotNull(List.class, 1); - for (String index : indexes) { - selected.add(list.get(TypeConversionUtil.convertTo(int.class, index))); - } - } - return result; - } - - public class SelectUserTypeListModel extends UserTypeListModel { - private final WfVariable inputVariable; - - public SelectUserTypeListModel(WfVariable variable, List attributeNames, boolean componentView, WfVariable inputVariable) { - super(variable, attributeNames, componentView); - this.inputVariable = inputVariable; - } - - public WfVariable getInputVariable() { - return inputVariable; - } - - public String getChecked(TemplateModel arg0) throws TemplateModelException { - UserTypeMap userTypeMap = (UserTypeMap) BEANS_WRAPPER.unwrap(arg0); - List selectedList = (List) getInputVariable().getValue(); - boolean checked = selectedList != null && selectedList.contains(userTypeMap); - if (checked) { - return "checked='true'"; - } - return ""; - } - + protected boolean isMultiple() { + return true; } } diff --git a/wfe-web/src/main/java/ru/runa/wf/web/ftl/component/SingleSelectFromUserTypeList.java b/wfe-web/src/main/java/ru/runa/wf/web/ftl/component/SingleSelectFromUserTypeList.java new file mode 100644 index 0000000000..8419083d8f --- /dev/null +++ b/wfe-web/src/main/java/ru/runa/wf/web/ftl/component/SingleSelectFromUserTypeList.java @@ -0,0 +1,11 @@ +package ru.runa.wf.web.ftl.component; + +public class SingleSelectFromUserTypeList extends AbstractSelectFromUserTypeList { + + private static final long serialVersionUID = 7198988804348108048L; + + @Override + protected boolean isMultiple() { + return false; + } +} diff --git a/wfe-web/src/main/resources/ftl.form.components.xml b/wfe-web/src/main/resources/ftl.form.components.xml index db5fb474e1..c83b5fd4f3 100644 --- a/wfe-web/src/main/resources/ftl.form.components.xml +++ b/wfe-web/src/main/resources/ftl.form.components.xml @@ -31,5 +31,6 @@ + diff --git a/wfe-web/src/main/resources/templates/SingleSelectFromUserTypeList.ftl b/wfe-web/src/main/resources/templates/SingleSelectFromUserTypeList.ftl new file mode 100644 index 0000000000..44144186f4 --- /dev/null +++ b/wfe-web/src/main/resources/templates/SingleSelectFromUserTypeList.ftl @@ -0,0 +1,22 @@ +
+ + + + + <#list model.attributes as attribute> + + + + + + <#list model.variableValue as row> + + + <#list model.attributes as attribute> + + + + + +
${attribute.name}
${model.getValue(row, attribute, row?index)}
+
\ No newline at end of file From 4afc7de736e40605de02a7f58e9c456f4fcb086d Mon Sep 17 00:00:00 2001 From: Kolesnikov Victor Date: Thu, 25 Mar 2021 18:08:41 +0300 Subject: [PATCH 10/12] Rm1158 --- .../handler/sql/AbstractSqlHandler.java | 74 +++++++++++++------ 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/wfe-core/src/main/java/ru/runa/wfe/extension/handler/sql/AbstractSqlHandler.java b/wfe-core/src/main/java/ru/runa/wfe/extension/handler/sql/AbstractSqlHandler.java index 7b381fd65b..00b09042ce 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/extension/handler/sql/AbstractSqlHandler.java +++ b/wfe-core/src/main/java/ru/runa/wfe/extension/handler/sql/AbstractSqlHandler.java @@ -31,11 +31,15 @@ import ru.runa.wfe.user.Actor; import ru.runa.wfe.var.AbstractVariableProvider; import ru.runa.wfe.var.MapDelegableVariableProvider; +import ru.runa.wfe.var.UserType; +import ru.runa.wfe.var.UserTypeMap; +import ru.runa.wfe.var.VariableDefinition; import ru.runa.wfe.var.VariableProvider; import ru.runa.wfe.var.dto.WfVariable; import ru.runa.wfe.var.file.FileVariable; import ru.runa.wfe.var.file.FileVariableImpl; import ru.runa.wfe.var.format.ListFormat; +import ru.runa.wfe.var.format.VariableFormat; public abstract class AbstractSqlHandler extends CommonHandler { @@ -86,30 +90,47 @@ private void executeSqlQueries(VariableProvider variableProvider, Map result = extractResults(variableProvider, resultSet, query); - if (first) { - for (Map.Entry entry : result.entrySet()) { - WfVariable variable = variableProvider.getVariableNotNull(entry.getKey()); - Object variableValue; - if (variable.getDefinition().getFormatNotNull() instanceof ListFormat) { - ArrayList list = new ArrayList(); - list.add(entry.getValue()); - variableValue = list; - } else { - variableValue = entry.getValue(); - } - outputVariables.put(entry.getKey(), variableValue); + String firstResultVariableName = query.getResults().get(0).getVariableName(); + VariableFormat vf = variableProvider.getVariableNotNull(firstResultVariableName).getDefinition().getFormatNotNull(); + if (vf instanceof ListFormat && ((ListFormat) vf).getComponentUserType(0) != null) { + UserType userType = ((ListFormat) vf).getComponentUserType(0); + List result = new ArrayList<>(); + while (resultSet.next()) { + UserTypeMap userTypeMap = new UserTypeMap(userType); + for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) { + String columnName = resultSet.getMetaData().getColumnName(i + 1); + String attributeName = findAttributeByColumnNameIgnoreCase(userType, columnName); + userTypeMap.put(attributeName, resultSet.getObject(columnName)); } - first = false; - } else { - for (Map.Entry entry : result.entrySet()) { - Object object = outputVariables.get(entry.getKey()); - if (!(object instanceof List)) { - throw new Exception("Variable " + entry.getKey() + " expected to have List format"); + result.add(userTypeMap); + } + outputVariables.put(firstResultVariableName, result); + } else { + boolean first = true; + while (resultSet.next()) { + Map result = extractResults(variableProvider, resultSet, query); + if (first) { + for (Map.Entry entry : result.entrySet()) { + WfVariable variable = variableProvider.getVariableNotNull(entry.getKey()); + Object variableValue; + if (variable.getDefinition().getFormatNotNull() instanceof ListFormat) { + ArrayList list = new ArrayList(); + list.add(entry.getValue()); + variableValue = list; + } else { + variableValue = entry.getValue(); + } + outputVariables.put(entry.getKey(), variableValue); + } + first = false; + } else { + for (Map.Entry entry : result.entrySet()) { + Object object = outputVariables.get(entry.getKey()); + if (!(object instanceof List)) { + throw new Exception("Variable " + entry.getKey() + " expected to have List format"); + } + ((List) object).add(entry.getValue()); } - ((List) object).add(entry.getValue()); } } } @@ -214,4 +235,13 @@ private Map extractResults(VariableProvider variableProvider, Re return outputVariables; } + private String findAttributeByColumnNameIgnoreCase(UserType userType, String columnName) throws Exception { + for (VariableDefinition variableDefinition : userType.getAttributes()) { + if (variableDefinition.getName().equalsIgnoreCase(columnName)) { + return variableDefinition.getName(); + } + } + throw new Exception("Attribute not found in user type for column " + columnName); + } + } From 1456620144fe78043e1223b7079e6108b9bcd4fa Mon Sep 17 00:00:00 2001 From: Andrey dPotapov Date: Mon, 29 Mar 2021 13:57:27 +0300 Subject: [PATCH 11/12] Rm2088 --- .../wfe/graph/image/GraphImageBuilder.java | 89 +++++++++++++++---- 1 file changed, 70 insertions(+), 19 deletions(-) diff --git a/wfe-core/src/main/java/ru/runa/wfe/graph/image/GraphImageBuilder.java b/wfe-core/src/main/java/ru/runa/wfe/graph/image/GraphImageBuilder.java index c3a4b7e572..ad874175f4 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/graph/image/GraphImageBuilder.java +++ b/wfe-core/src/main/java/ru/runa/wfe/graph/image/GraphImageBuilder.java @@ -20,10 +20,16 @@ import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + import java.awt.Color; +import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.Map; -import ru.runa.wfe.audit.NodeEnterLog; +import java.util.Set; +import java.util.function.Function; + import ru.runa.wfe.audit.ProcessLogs; import ru.runa.wfe.audit.TaskCreateLog; import ru.runa.wfe.audit.TaskEndLog; @@ -44,6 +50,7 @@ import ru.runa.wfe.lang.Node; import ru.runa.wfe.lang.NodeType; import ru.runa.wfe.lang.ProcessDefinition; +import ru.runa.wfe.lang.SubprocessDefinition; import ru.runa.wfe.lang.SubprocessNode; import ru.runa.wfe.lang.Transition; import ru.runa.wfe.task.TaskDeadlineUtils; @@ -57,11 +64,13 @@ public class GraphImageBuilder { private final Map allNodeFigures = Maps.newHashMap(); private final Map transitionFigures = Maps.newHashMap(); private final Map nodeFigures = Maps.newLinkedHashMap(); + private final Map> allSubprocessNameNodeIds = Maps.newHashMap(); private final boolean smoothTransitions; public GraphImageBuilder(ProcessDefinition processDefinition) { this.processDefinition = processDefinition; this.smoothTransitions = DrawProperties.isSmoothLinesEnabled() && processDefinition.getDeployment().getLanguage() == Language.BPMN2; + fillAllSubprocessNameNodeIds(); } public void setHighlightedToken(Token highlightedToken) { @@ -105,9 +114,7 @@ public byte[] createDiagram(Process process, ProcessLogs logs) throws Exception } } } - NodeEnterLog lastNodeEnterLog = logs.getLastOrNull(NodeEnterLog.class); - String lastSubprocessNodeId = lastNodeEnterLog != null && lastNodeEnterLog.getNodeType() == NodeType.SUBPROCESS ? lastNodeEnterLog - .getNodeId() : null; + final Set activeNodeIds = getActiveNodeIds(process.getRootToken(), new HashSet()); for (TransitionLog transitionLog : logs.getLogs(TransitionLog.class)) { Transition transition = transitionLog.getTransitionOrNull(processDefinition); if (transition != null) { @@ -117,10 +124,10 @@ public byte[] createDiagram(Process process, ProcessLogs logs) throws Exception nodeFigures.put(nodeModelFrom, renderHits); // Mark 'to' block as PASSED AbstractFigure nodeModelTo = allNodeFigures.get(transition.getTo().getTransitionNodeId(true)); - if (lastSubprocessNodeId != null && lastSubprocessNodeId.equals(nodeModelTo.getNode().getNodeId())) { - renderHits = new RenderHits(DrawProperties.getHighlightColor(), true, true); - } nodeFigures.put(nodeModelTo, renderHits); + if (nodeModelTo.getNode() instanceof SubprocessNode) { + fillActiveSubprocess(nodeModelTo, activeNodeIds); + } if (nodeModelTo.getNode() instanceof BoundaryEventContainer) { for (BoundaryEvent boundaryEvent : ((BoundaryEventContainer) nodeModelTo.getNode()).getBoundaryEvents()) { AbstractFigure boundaryEventFigure = allNodeFigures.get(((GraphElement) boundaryEvent).getNodeId()); @@ -136,28 +143,48 @@ public byte[] createDiagram(Process process, ProcessLogs logs) throws Exception transitionFigures.put(transitionFigure, renderHits); } } - fillActiveSubprocesses(process.getRootToken()); + fillTasks(logs); GraphImage graphImage = new GraphImage(processDefinition, transitionFigures, nodeFigures); return graphImage.getImageBytes(); } - private void fillActiveSubprocesses(Token token) { + private Set getActiveNodeIds(Token token, Set activeNodeIds) { + if (token == null) { + return Collections.emptySet(); + } + activeNodeIds.add(token.getNodeId()); for (Token childToken : token.getActiveChildren()) { - fillActiveSubprocesses(childToken); + activeNodeIds = getActiveNodeIds(childToken, activeNodeIds); } - if (processDefinition.getNode(token.getNodeId()) != null && token.getNodeNotNull(processDefinition) instanceof SubprocessNode) { - AbstractFigure node = allNodeFigures.get(token.getNodeNotNull(processDefinition).getNodeId()); - Color color; - if (highlightedToken != null && Objects.equal(highlightedToken.getId(), token.getId())) { - color = DrawProperties.getHighlightColor(); - } else { - color = DrawProperties.getBaseColor(); + return activeNodeIds; + } + + private void fillActiveSubprocess(AbstractFigure nodeModelTo, Set activeNodeIds) { + SubprocessNode subprocessNode = (SubprocessNode) nodeModelTo.getNode(); + Color color = DrawProperties.getHighlightColor(); + boolean isBold = false; + if (!subprocessNode.isEmbedded()) { + String subprocessNodeId = subprocessNode.getNodeId(); + if (activeNodeIds.contains(subprocessNodeId)) { + if (highlightedToken == null || !highlightedToken.getNodeId().equals(subprocessNodeId)) { + color = DrawProperties.getBaseColor(); + } + isBold = true; } - if (node != null) { - nodeFigures.put(node, new RenderHits(color, true, true)); + } else { + if (allSubprocessNameNodeIds.containsKey(subprocessNode.getSubProcessName())) { + Set intersection = allSubprocessNameNodeIds.get(subprocessNode.getSubProcessName()); + intersection.retainAll(activeNodeIds); + if (!intersection.isEmpty()) { + if (highlightedToken == null || !intersection.contains(highlightedToken.getNodeId())) { + color = DrawProperties.getBaseColor(); + } + isBold = true; + } } } + nodeFigures.put(nodeModelTo, new RenderHits(color, true, isBold)); } private void fillTasks(ProcessLogs logs) { @@ -189,4 +216,28 @@ private void fillTasks(ProcessLogs logs) { } } } + + private void fillAllSubprocessNameNodeIds() { + for (SubprocessDefinition subprocessDefinition : processDefinition.getEmbeddedSubprocesses().values()) { + allSubprocessNameNodeIds.computeIfAbsent(subprocessDefinition.getName(), new ComputeEmbeddedProcessNodeIds(subprocessDefinition)); + } + } + + static class ComputeEmbeddedProcessNodeIds implements Function> { + SubprocessDefinition subprocessDefinition; + + ComputeEmbeddedProcessNodeIds(SubprocessDefinition subprocessDefinition) { + this.subprocessDefinition = subprocessDefinition; + } + + @Override + public Set apply(String t) { + Set nodeIds = Sets.newHashSet(); + for (Node innerNode : subprocessDefinition.getNodes(false)) { + nodeIds.add(innerNode.getNodeId()); + } + return nodeIds; + } + } + } From b2c86b404883da7c243b4e4dc83d0382267435cb Mon Sep 17 00:00:00 2001 From: Dofs Serge Date: Mon, 29 Mar 2021 15:13:06 +0300 Subject: [PATCH 12/12] rm362 process definition compatibility check --- .../wfe/InternalApplicationException.java | 2 - .../ru/runa/wfe/commons/SystemProperties.java | 4 + .../wfe/definition/bpmn/BpmnXmlReader.java | 3 +- .../wfe/definition/logic/DefinitionLogic.java | 5 + .../wfe/definition/par/GraphXmlParser.java | 30 ++--- .../wfe/definition/par/ProcessArchive.java | 12 +- .../validation/DefinitionUpdateValidator.java | 10 ++ .../DefinitionUpdateValidatorManager.java | 58 ++++++++++ .../validation/DeploymentUpdateData.java | 22 ++++ ...ocessDefinitionNotCompatibleException.java | 22 ++++ ...odeExistenceDefinitionUpdateValidator.java | 34 ++++++ ...allelGatewayDefinitionUpdateValidator.java | 103 ++++++++++++++++++ .../wfe/execution/logic/ExecutionLogic.java | 9 ++ .../ru/runa/wfe/lang/ProcessDefinition.java | 78 +++++-------- .../runa/wfe/lang/SubprocessDefinition.java | 8 +- wfe-core/src/main/resources/system.properties | 2 + .../common/web/ActionExceptionHelper.java | 11 +- .../ru/runa/common/web/MessagesException.java | 1 + wfe-web/src/main/resources/settingsList.xml | 4 + .../webapp/WEB-INF/classes/struts.properties | 4 +- .../WEB-INF/classes/struts_ru.properties | 3 + 21 files changed, 338 insertions(+), 87 deletions(-) create mode 100644 wfe-core/src/main/java/ru/runa/wfe/definition/validation/DefinitionUpdateValidator.java create mode 100644 wfe-core/src/main/java/ru/runa/wfe/definition/validation/DefinitionUpdateValidatorManager.java create mode 100644 wfe-core/src/main/java/ru/runa/wfe/definition/validation/DeploymentUpdateData.java create mode 100644 wfe-core/src/main/java/ru/runa/wfe/definition/validation/ProcessDefinitionNotCompatibleException.java create mode 100644 wfe-core/src/main/java/ru/runa/wfe/definition/validation/impl/NodeExistenceDefinitionUpdateValidator.java create mode 100644 wfe-core/src/main/java/ru/runa/wfe/definition/validation/impl/ParallelGatewayDefinitionUpdateValidator.java diff --git a/wfe-core/src/main/java/ru/runa/wfe/InternalApplicationException.java b/wfe-core/src/main/java/ru/runa/wfe/InternalApplicationException.java index e429c87507..8d4470c0aa 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/InternalApplicationException.java +++ b/wfe-core/src/main/java/ru/runa/wfe/InternalApplicationException.java @@ -17,14 +17,12 @@ */ package ru.runa.wfe; -import javax.ejb.ApplicationException; /** * Signals about inappropriate application usage. * * @author Dofs */ -@ApplicationException(rollback = true) public class InternalApplicationException extends RuntimeException { private static final long serialVersionUID = 1L; diff --git a/wfe-core/src/main/java/ru/runa/wfe/commons/SystemProperties.java b/wfe-core/src/main/java/ru/runa/wfe/commons/SystemProperties.java index e14479dedc..337bf3fd46 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/commons/SystemProperties.java +++ b/wfe-core/src/main/java/ru/runa/wfe/commons/SystemProperties.java @@ -236,6 +236,10 @@ public static boolean isDefinitionDeploymentWithEmptyCommentsAllowed() { return RESOURCES.getBooleanProperty("definition.comments.empty.allowed", true); } + public static boolean isDefinitionCompatibilityCheckEnabled() { + return RESOURCES.getBooleanProperty("definition.compatibility.check.enabled", true); + } + public static boolean isCheckProcessStartPermissions() { return RESOURCES.getBooleanProperty("check.process.start.permissions", true); } diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/bpmn/BpmnXmlReader.java b/wfe-core/src/main/java/ru/runa/wfe/definition/bpmn/BpmnXmlReader.java index 7787e99189..fe1c469bab 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/definition/bpmn/BpmnXmlReader.java +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/bpmn/BpmnXmlReader.java @@ -420,8 +420,7 @@ private void readTransitions(ProcessDefinition processDefinition, Element proces } Transition transition = new Transition(); transition.setNodeId(id); - GraphElement sourceElement = processDefinition.getGraphElementNotNull(from); - Node source = (Node) sourceElement; + Node source = processDefinition.getNodeNotNull(from); transition.setFrom(source); Node target = processDefinition.getNodeNotNull(to); transition.setTo(target); diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/logic/DefinitionLogic.java b/wfe-core/src/main/java/ru/runa/wfe/definition/logic/DefinitionLogic.java index 9bf2eadf81..406eb453f1 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/definition/logic/DefinitionLogic.java +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/logic/DefinitionLogic.java @@ -25,6 +25,7 @@ import java.util.Date; import java.util.List; import java.util.Map; +import org.springframework.beans.factory.annotation.Autowired; import ru.runa.wfe.InternalApplicationException; import ru.runa.wfe.audit.AdminActionLog; import ru.runa.wfe.audit.ProcessDefinitionDeleteLog; @@ -42,6 +43,7 @@ import ru.runa.wfe.definition.ProcessDefinitionChange; import ru.runa.wfe.definition.dto.WfDefinition; import ru.runa.wfe.definition.par.ProcessArchive; +import ru.runa.wfe.definition.validation.DefinitionUpdateValidatorManager; import ru.runa.wfe.execution.ParentProcessExistsException; import ru.runa.wfe.execution.Process; import ru.runa.wfe.execution.ProcessFilter; @@ -66,6 +68,8 @@ * Created on 15.03.2005 */ public class DefinitionLogic extends WfCommonLogic { + @Autowired + DefinitionUpdateValidatorManager definitionVersionValidatorManager; public WfDefinition deployProcessDefinition(User user, byte[] processArchiveBytes, List categories) { permissionDao.checkAllowed(user, Permission.CREATE_DEFINITION, SecuredSingleton.SYSTEM); @@ -171,6 +175,7 @@ public WfDefinition updateProcessDefinition(User user, Long definitionId, byte[] + " comments. Most likely you try to upload an old version of definition (page update is recommended). "); } } + definitionVersionValidatorManager.validate(getDefinition(deployment.getId()), uploadedDefinition); deployment.setContent(uploadedDefinition.getDeployment().getContent()); deployment.setUpdateDate(new Date()); deployment.setUpdateActor(user.getActor()); diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/par/GraphXmlParser.java b/wfe-core/src/main/java/ru/runa/wfe/definition/par/GraphXmlParser.java index 53bd5dc156..356e817d19 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/definition/par/GraphXmlParser.java +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/par/GraphXmlParser.java @@ -1,13 +1,10 @@ package ru.runa.wfe.definition.par; +import com.google.common.base.Throwables; import java.util.List; - import org.apache.commons.logging.LogFactory; import org.dom4j.Document; import org.dom4j.Element; - -import com.google.common.base.Throwables; - import ru.runa.wfe.commons.xml.XmlUtils; import ru.runa.wfe.definition.FileDataProvider; import ru.runa.wfe.definition.InvalidDefinitionException; @@ -16,7 +13,6 @@ import ru.runa.wfe.lang.Node; import ru.runa.wfe.lang.ProcessDefinition; import ru.runa.wfe.lang.SubprocessDefinition; -import ru.runa.wfe.lang.SwimlaneDefinition; import ru.runa.wfe.lang.Transition; public class GraphXmlParser implements ProcessArchiveParser { @@ -48,21 +44,25 @@ public void readFromArchive(ProcessArchive archive, ProcessDefinition processDef List nodeElements = root.elements(NODE_ELEMENT); for (Element nodeElement : nodeElements) { String nodeId = nodeElement.attributeValue("name"); - GraphElement graphElement = processDefinition.getGraphElementNotNull(nodeId); - graphElement.setGraphConstraints(Integer.parseInt(nodeElement.attributeValue("x")) - xOffset, - Integer.parseInt(nodeElement.attributeValue("y")) - yOffset, Integer.parseInt(nodeElement.attributeValue("width")), - Integer.parseInt(nodeElement.attributeValue("height"))); - Node transitionSource; - if (graphElement instanceof Node) { - boolean minimizedView = Boolean.parseBoolean(nodeElement.attributeValue("minimizedView", "false")); - ((Node) graphElement).setGraphMinimizedView(minimizedView); - transitionSource = (Node) graphElement; + GraphElement graphElement; + Node transitionSource = processDefinition.getNode(nodeId); + if (transitionSource != null) { + graphElement = transitionSource; } else { - if (!(graphElement instanceof SwimlaneDefinition)) { + graphElement = processDefinition.getSwimlaneById(nodeId); + if (graphElement == null) { LogFactory.getLog(getClass()).warn("Ignored graph element " + graphElement + " in " + processDefinition); + continue; } + } + graphElement.setGraphConstraints(Integer.parseInt(nodeElement.attributeValue("x")) - xOffset, + Integer.parseInt(nodeElement.attributeValue("y")) - yOffset, Integer.parseInt(nodeElement.attributeValue("width")), + Integer.parseInt(nodeElement.attributeValue("height"))); + if (transitionSource == null) { continue; } + boolean minimizedView = Boolean.parseBoolean(nodeElement.attributeValue("minimizedView", "false")); + transitionSource.setGraphMinimizedView(minimizedView); List transitionElements = nodeElement.elements(TRANSITION_ELEMENT); for (Element transitionElement : transitionElements) { String transitionName = transitionElement.attributeValue("name"); diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/par/ProcessArchive.java b/wfe-core/src/main/java/ru/runa/wfe/definition/par/ProcessArchive.java index cf96d4b98d..b476c1dd64 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/definition/par/ProcessArchive.java +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/par/ProcessArchive.java @@ -21,6 +21,9 @@ */ package ru.runa.wfe.definition.par; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.io.ByteStreams; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; @@ -30,7 +33,6 @@ import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; - import ru.runa.wfe.commons.ApplicationContextFactory; import ru.runa.wfe.definition.DefinitionArchiveFormatException; import ru.runa.wfe.definition.Deployment; @@ -38,10 +40,6 @@ import ru.runa.wfe.lang.ProcessDefinition; import ru.runa.wfe.lang.SubprocessDefinition; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.io.ByteStreams; - public class ProcessArchive { private final Deployment deployment; public static final List UNSECURED_FILE_NAMES = Lists.newArrayList(); @@ -61,8 +59,8 @@ public class ProcessArchive { processArchiveParsers.add(ApplicationContextFactory.autowireBean(new GraphXmlParser())); processArchiveParsers.add(ApplicationContextFactory.autowireBean(new CommentsParser())); } - private static final Pattern SUBPROCESS_DEFINITION_PATTERN = Pattern.compile(FileDataProvider.SUBPROCESS_DEFINITION_PREFIX + "(\\d*)." - + FileDataProvider.PROCESSDEFINITION_XML_FILE_NAME); + private static final Pattern SUBPROCESS_DEFINITION_PATTERN = Pattern + .compile(FileDataProvider.SUBPROCESS_DEFINITION_PREFIX + "(\\d*)." + FileDataProvider.PROCESSDEFINITION_XML_FILE_NAME); private final Map fileData = Maps.newHashMap(); diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/validation/DefinitionUpdateValidator.java b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/DefinitionUpdateValidator.java new file mode 100644 index 0000000000..105b96ae44 --- /dev/null +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/DefinitionUpdateValidator.java @@ -0,0 +1,10 @@ +package ru.runa.wfe.definition.validation; + +/** + * @author azyablin + */ +public interface DefinitionUpdateValidator { + + void validate(DeploymentUpdateData deploymentUpdateData); + +} diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/validation/DefinitionUpdateValidatorManager.java b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/DefinitionUpdateValidatorManager.java new file mode 100644 index 0000000000..ca821bf66f --- /dev/null +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/DefinitionUpdateValidatorManager.java @@ -0,0 +1,58 @@ +package ru.runa.wfe.definition.validation; + +import java.util.Collections; +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import ru.runa.wfe.commons.SystemProperties; +import ru.runa.wfe.commons.TimeMeasurer; +import ru.runa.wfe.execution.Process; +import ru.runa.wfe.execution.ProcessFilter; +import ru.runa.wfe.execution.dao.ProcessDao; +import ru.runa.wfe.lang.ProcessDefinition; + +/** + * @author azyablin + */ +@Component +public class DefinitionUpdateValidatorManager { + private static final Log log = LogFactory.getLog(DefinitionUpdateValidatorManager.class); + @Autowired + private List validators; + @Autowired + private ProcessDao processDao; + + public void validate(ProcessDefinition oldDefinition, ProcessDefinition newDefinition) { + if (!SystemProperties.isDefinitionCompatibilityCheckEnabled()) { + return; + } + TimeMeasurer timeMeasurer = new TimeMeasurer(log); + timeMeasurer.jobStarted(); + ProcessFilter filter = new ProcessFilter(); + filter.setDefinitionName(oldDefinition.getName()); + filter.setDefinitionVersion(oldDefinition.getDeployment().getVersion()); + filter.setFinished(false); + List processes = processDao.getProcesses(filter); + timeMeasurer.jobEnded("Loading " + processes.size() + " active processes"); + timeMeasurer.jobStarted(); + validate(oldDefinition, newDefinition, processes); + timeMeasurer.jobEnded("Validation of " + oldDefinition); + } + + public void validate(ProcessDefinition oldDefinition, ProcessDefinition newDefinition, Process process) { + if (!SystemProperties.isDefinitionCompatibilityCheckEnabled()) { + return; + } + validate(oldDefinition, newDefinition, Collections.singletonList(process)); + } + + private void validate(ProcessDefinition oldDefinition, ProcessDefinition newDefinition, List processes) { + DeploymentUpdateData deploymentUpdateData = new DeploymentUpdateData(oldDefinition, newDefinition, processes); + for (DefinitionUpdateValidator validator : validators) { + validator.validate(deploymentUpdateData); + } + } + +} diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/validation/DeploymentUpdateData.java b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/DeploymentUpdateData.java new file mode 100644 index 0000000000..9663672a4c --- /dev/null +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/DeploymentUpdateData.java @@ -0,0 +1,22 @@ +package ru.runa.wfe.definition.validation; + +import java.util.List; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import ru.runa.wfe.execution.Process; +import ru.runa.wfe.lang.ProcessDefinition; + +/** + * Contains information about old and new definition for process definition compatibility check. + * + * @author azyablin + */ +@RequiredArgsConstructor +@Getter +@Setter +public class DeploymentUpdateData { + private final ProcessDefinition oldDefinition; + private final ProcessDefinition newDefinition; + private final List processes; +} diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/validation/ProcessDefinitionNotCompatibleException.java b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/ProcessDefinitionNotCompatibleException.java new file mode 100644 index 0000000000..ee17ea5b1e --- /dev/null +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/ProcessDefinitionNotCompatibleException.java @@ -0,0 +1,22 @@ +package ru.runa.wfe.definition.validation; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.ToString; +import ru.runa.wfe.InternalApplicationException; + +/** + * @author azyablin + */ +@RequiredArgsConstructor +@Getter +@ToString +public class ProcessDefinitionNotCompatibleException extends InternalApplicationException { + public static final String NODE_EXISTENCE = "node.existence"; + public static final String PARALLEL_GATEWAY_MISTYPED = "parallel.gateway.mistyped"; + public static final String PARALLEL_GATEWAY_TRANSITIONS = "parallel.gateway.transitions"; + private static final long serialVersionUID = 1L; + private final String type; + private final String[] args; + +} diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/validation/impl/NodeExistenceDefinitionUpdateValidator.java b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/impl/NodeExistenceDefinitionUpdateValidator.java new file mode 100644 index 0000000000..4537ea22f9 --- /dev/null +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/impl/NodeExistenceDefinitionUpdateValidator.java @@ -0,0 +1,34 @@ +package ru.runa.wfe.definition.validation.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import ru.runa.wfe.definition.validation.DefinitionUpdateValidator; +import ru.runa.wfe.definition.validation.DeploymentUpdateData; +import ru.runa.wfe.definition.validation.ProcessDefinitionNotCompatibleException; +import ru.runa.wfe.execution.Token; +import ru.runa.wfe.execution.dao.TokenDao; + +/** + * Checks that all nodes with tokens in active processes exist in new process definition. + * + * @author azyablin + */ +@Component +public class NodeExistenceDefinitionUpdateValidator implements DefinitionUpdateValidator { + @Autowired + TokenDao tokenDao; + + @Override + public void validate(DeploymentUpdateData deploymentUpdateData) { + for (ru.runa.wfe.execution.Process process : deploymentUpdateData.getProcesses()) { + for (Token token : tokenDao.findByProcessAndExecutionStatusIsNotEnded(process)) { + String nodeId = token.getNodeId(); + if (deploymentUpdateData.getNewDefinition().getNode(nodeId) == null) { + throw new ProcessDefinitionNotCompatibleException(ProcessDefinitionNotCompatibleException.NODE_EXISTENCE, + new String[] { nodeId, token.getProcess().getId().toString() }); + } + } + } + } + +} diff --git a/wfe-core/src/main/java/ru/runa/wfe/definition/validation/impl/ParallelGatewayDefinitionUpdateValidator.java b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/impl/ParallelGatewayDefinitionUpdateValidator.java new file mode 100644 index 0000000000..439bdb5c76 --- /dev/null +++ b/wfe-core/src/main/java/ru/runa/wfe/definition/validation/impl/ParallelGatewayDefinitionUpdateValidator.java @@ -0,0 +1,103 @@ +package ru.runa.wfe.definition.validation.impl; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import ru.runa.wfe.definition.Language; +import ru.runa.wfe.definition.validation.DefinitionUpdateValidator; +import ru.runa.wfe.definition.validation.DeploymentUpdateData; +import ru.runa.wfe.definition.validation.ProcessDefinitionNotCompatibleException; +import ru.runa.wfe.execution.Token; +import ru.runa.wfe.execution.dao.TokenDao; +import ru.runa.wfe.lang.Node; +import ru.runa.wfe.lang.Transition; +import ru.runa.wfe.lang.bpmn2.ParallelGateway; + +/** + * Parallel gateway does not work in case of missed token in any of input transition. This validator prevents these errors. + * + * @author azyablin + */ +@Component +public class ParallelGatewayDefinitionUpdateValidator implements DefinitionUpdateValidator { + @Autowired + TokenDao tokenDao; + + @Override + public void validate(DeploymentUpdateData deploymentUpdateData) { + if (deploymentUpdateData.getNewDefinition().getDeployment().getLanguage() != Language.BPMN2) { + return; + } + Set parallelGateways = getParallelGatewaysForCheck(deploymentUpdateData); + for (ParallelGateway parallelGateway : parallelGateways) { + Node newNode = deploymentUpdateData.getNewDefinition().getNode(parallelGateway.getNodeId()); + if (!(newNode instanceof ParallelGateway)) { + throw new ProcessDefinitionNotCompatibleException(ProcessDefinitionNotCompatibleException.PARALLEL_GATEWAY_MISTYPED, + new String[] { parallelGateway.getNodeId() }); + } + if (!areInputTransitionsCompatible(parallelGateway, (ParallelGateway) newNode)) { + throw new ProcessDefinitionNotCompatibleException(ProcessDefinitionNotCompatibleException.PARALLEL_GATEWAY_TRANSITIONS, + new String[] { parallelGateway.getNodeId() }); + } + } + } + + /** + * checks that nodes have not been added or updated in the new definition + * + * @return true if the new definition has no changes + */ + private boolean areInputTransitionsCompatible(ParallelGateway oldNode, ParallelGateway newNode) { + List oldTransitions = oldNode.getArrivingTransitions(); + List newTransitions = newNode.getArrivingTransitions(); + for (Transition newTransition : newTransitions) { + if (!oldTransitions.stream().filter(new Predicate() { + @Override + public boolean test(Transition t) { + return newTransition.getNodeId().equals(t.getNodeId()); + } + }).findFirst().isPresent()) { + return false; + } + } + return true; + } + + /** + * Partial implementation + * + * @return parallel gateways nearby to active nodes only + */ + private Set getParallelGatewaysForCheck(DeploymentUpdateData deploymentUpdateData) { + Set parallelGateways = new HashSet<>(); + Set seenNodes = new HashSet<>(); + for (ru.runa.wfe.execution.Process process : deploymentUpdateData.getProcesses()) { + for (Token token : tokenDao.findByProcessAndExecutionStatusIsNotEnded(process)) { + String nodeId = token.getNodeId(); + Node node = deploymentUpdateData.getOldDefinition().getNodeNotNull(nodeId); + fetchNearestParallelGateways(parallelGateways, seenNodes, node); + } + } + return parallelGateways; + } + + private void fetchNearestParallelGateways(Set parallelGateways, Set seenNodes, Node node) { + if (seenNodes.contains(node)) { + return; + } + seenNodes.add(node); + if (node instanceof ParallelGateway) { + if (node.getArrivingTransitions().size() > 1) { + parallelGateways.add((ParallelGateway) node); + } + return; + } + for (Transition transition : node.getLeavingTransitions()) { + fetchNearestParallelGateways(parallelGateways, seenNodes, transition.getTo()); + } + } + +} diff --git a/wfe-core/src/main/java/ru/runa/wfe/execution/logic/ExecutionLogic.java b/wfe-core/src/main/java/ru/runa/wfe/execution/logic/ExecutionLogic.java index 2e09b295c0..3a4bfad585 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/execution/logic/ExecutionLogic.java +++ b/wfe-core/src/main/java/ru/runa/wfe/execution/logic/ExecutionLogic.java @@ -48,6 +48,7 @@ import ru.runa.wfe.commons.logic.WfCommonLogic; import ru.runa.wfe.definition.DefinitionVariableProvider; import ru.runa.wfe.definition.Deployment; +import ru.runa.wfe.definition.validation.DefinitionUpdateValidatorManager; import ru.runa.wfe.execution.ExecutionContext; import ru.runa.wfe.execution.ExecutionStatus; import ru.runa.wfe.execution.NodeProcess; @@ -114,6 +115,9 @@ public class ExecutionLogic extends WfCommonLogic { private ProcessLogDao processLogDao; @Autowired private JobDao jobDao; + @Autowired + private DefinitionUpdateValidatorManager definitionVersionValidatorManager; + public void cancelProcess(User user, Long processId) throws ProcessDoesNotExistException { ProcessFilter filter = new ProcessFilter(); @@ -349,7 +353,11 @@ public int upgradeProcessesToDefinitionVersion(User user, Long definitionId, Lon "In order to enable process definition version upgrade set property 'upgrade.process.to.definition.version.enabled' to 'true' in system.properties or wfe.custom.system.properties"); } Deployment deployment = deploymentDao.getNotNull(definitionId); + if (Objects.equal(newVersion, deployment.getVersion())) { + return 0; + } Deployment nextDeployment = deploymentDao.findDeployment(deployment.getName(), newVersion); + definitionVersionValidatorManager.validate(getDefinition(deployment.getId()), getDefinition(nextDeployment.getId())); ProcessFilter filter = new ProcessFilter(); filter.setDefinitionName(deployment.getName()); filter.setDefinitionVersion(deployment.getVersion()); @@ -377,6 +385,7 @@ public boolean upgradeProcessToDefinitionVersion(User user, Long processId, Long return false; } Deployment nextDeployment = deploymentDao.findDeployment(deployment.getName(), newDeploymentVersion); + definitionVersionValidatorManager.validate(getDefinition(deployment.getId()), getDefinition(nextDeployment.getId()), process); process.setDeployment(nextDeployment); processDao.update(process); processLogDao.addLog(new AdminActionLog(user.getActor(), AdminActionLog.ACTION_UPGRADE_PROCESS_TO_VERSION, deployment.getVersion(), diff --git a/wfe-core/src/main/java/ru/runa/wfe/lang/ProcessDefinition.java b/wfe-core/src/main/java/ru/runa/wfe/lang/ProcessDefinition.java index d6c647b5c0..4f30d92329 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/lang/ProcessDefinition.java +++ b/wfe-core/src/main/java/ru/runa/wfe/lang/ProcessDefinition.java @@ -50,7 +50,8 @@ public class ProcessDefinition extends GraphElement implements FileDataProvider protected Deployment deployment; protected Map processFiles = Maps.newHashMap(); protected StartNode startNode; - protected final List nodes = Lists.newArrayList(); + protected final List nodesList = Lists.newArrayList(); + protected final Map nodesMap = Maps.newHashMap(); protected final List swimlaneDefinitions = Lists.newArrayList(); protected final Map swimlaneDefinitionsMap = Maps.newHashMap(); protected final Map interactions = Maps.newHashMap(); @@ -304,7 +305,7 @@ public StartNode getStartStateNotNull() { } public List getNodes(boolean withEmbeddedSubprocesses) { - List result = Lists.newArrayList(nodes); + List result = Lists.newArrayList(nodesList); if (withEmbeddedSubprocesses) { for (SubprocessDefinition subprocessDefinition : embeddedSubprocesses.values()) { result.addAll(subprocessDefinition.getNodes(withEmbeddedSubprocesses)); @@ -315,7 +316,10 @@ public List getNodes(boolean withEmbeddedSubprocesses) { public Node addNode(Node node) { Preconditions.checkArgument(node != null, "can't add a null node to a processdefinition"); - nodes.add(node); + nodesList.add(node); + if (nodesMap.put(node.getNodeId(), node) != null) { + throw new InvalidDefinitionException(getName(), "found duplicated node " + node.getNodeId()); + } node.processDefinition = this; if (node instanceof StartNode) { if (startNode != null) { @@ -326,21 +330,18 @@ public Node addNode(Node node) { return node; } - public void removeNode(Node node) { - nodes.remove(node); - } - public Node getNode(String id) { Preconditions.checkNotNull(id); - for (Node node : nodes) { - if (id.equals(node.getNodeId())) { - return node; - } + Node node = nodesMap.get(id); + if (node != null) { + return node; } - for (SubprocessDefinition subprocessDefinition : embeddedSubprocesses.values()) { - Node node = subprocessDefinition.getNode(id); - if (node != null) { - return node; + if (id.startsWith(FileDataProvider.SUBPROCESS_DEFINITION_PREFIX)) { + for (SubprocessDefinition subprocessDefinition : embeddedSubprocesses.values()) { + node = subprocessDefinition.getNode(id); + if (node != null) { + return node; + } } } return null; @@ -355,38 +356,6 @@ public Node getNodeNotNull(String id) { throw new InternalApplicationException("node '" + id + "' not found"); } - public GraphElement getGraphElement(String id) { - for (Node node : nodes) { - if (id.equals(node.getNodeId())) { - return node; - } - Action action = node.getAction(id); - if (action != null) { - return action; - } - } - for (SwimlaneDefinition swimlaneDefinition : swimlaneDefinitions) { - if (id.equals(swimlaneDefinition.getNodeId())) { - return swimlaneDefinition; - } - } - for (SubprocessDefinition subprocessDefinition : embeddedSubprocesses.values()) { - GraphElement graphElement = subprocessDefinition.getGraphElement(id); - if (graphElement != null) { - return graphElement; - } - } - return null; - } - - public GraphElement getGraphElementNotNull(String id) { - GraphElement graphElement = getGraphElement(id); - if (graphElement == null) { - throw new InternalApplicationException("element '" + id + "' not found"); - } - return graphElement; - } - @Override public GraphElement getParentElement() { return null; @@ -411,6 +380,15 @@ public SwimlaneDefinition getSwimlane(String swimlaneName) { return swimlaneDefinitionsMap.get(swimlaneName); } + public SwimlaneDefinition getSwimlaneById(String id) { + for (SwimlaneDefinition swimlaneDefinition : swimlaneDefinitions) { + if (Objects.equal(id, swimlaneDefinition.getNodeId())) { + return swimlaneDefinition; + } + } + return null; + } + public SwimlaneDefinition getSwimlaneNotNull(String swimlaneName) { SwimlaneDefinition swimlaneDefinition = getSwimlane(swimlaneName); if (swimlaneDefinition == null) { @@ -446,7 +424,7 @@ public void addEmbeddedSubprocess(SubprocessDefinition subprocessDefinition) { public List getEmbeddedSubprocessNodeIds() { List result = Lists.newArrayList(); - for (Node node : nodes) { + for (Node node : nodesList) { if (node instanceof SubprocessNode && ((SubprocessNode) node).isEmbedded()) { result.add(node.getNodeId()); } @@ -455,7 +433,7 @@ public List getEmbeddedSubprocessNodeIds() { } public String getEmbeddedSubprocessNodeId(String subprocessName) { - for (Node node : nodes) { + for (Node node : nodesList) { if (node instanceof SubprocessNode) { SubprocessNode subprocessNode = (SubprocessNode) node; if (subprocessNode.isEmbedded() && Objects.equal(subprocessName, subprocessNode.getSubProcessName())) { @@ -504,7 +482,7 @@ public SubprocessDefinition getEmbeddedSubprocessByNameNotNull(String name) { } public void mergeWithEmbeddedSubprocesses() { - for (Node node : Lists.newArrayList(nodes)) { + for (Node node : Lists.newArrayList(nodesList)) { if (node instanceof SubprocessNode) { SubprocessNode subprocessNode = (SubprocessNode) node; if (subprocessNode.isEmbedded()) { diff --git a/wfe-core/src/main/java/ru/runa/wfe/lang/SubprocessDefinition.java b/wfe-core/src/main/java/ru/runa/wfe/lang/SubprocessDefinition.java index 465112c6a1..f5007757b4 100644 --- a/wfe-core/src/main/java/ru/runa/wfe/lang/SubprocessDefinition.java +++ b/wfe-core/src/main/java/ru/runa/wfe/lang/SubprocessDefinition.java @@ -1,8 +1,8 @@ package ru.runa.wfe.lang; +import com.google.common.collect.Lists; import java.util.List; import java.util.Map; - import ru.runa.wfe.InternalApplicationException; import ru.runa.wfe.definition.FileDataProvider; import ru.runa.wfe.form.Interaction; @@ -10,8 +10,6 @@ import ru.runa.wfe.var.UserType; import ru.runa.wfe.var.VariableDefinition; -import com.google.common.collect.Lists; - public class SubprocessDefinition extends ProcessDefinition { private static final long serialVersionUID = 1L; private ProcessDefinition parentProcessDefinition; @@ -45,7 +43,7 @@ public void validate() { throw new InternalApplicationException("Start state in embedded subprocess should have 1 leaving transition"); } int endNodesCount = 0; - for (Node node : nodes) { + for (Node node : nodesList) { if (node instanceof EndNode) { throw new InternalApplicationException("In embedded subprocess it is not allowed end state"); } @@ -68,7 +66,7 @@ public EmbeddedSubprocessStartNode getStartStateNotNull() { public List getEndNodes() { List list = Lists.newArrayList(); - for (Node node : nodes) { + for (Node node : nodesList) { if (node instanceof EmbeddedSubprocessEndNode) { list.add((EmbeddedSubprocessEndNode) node); } diff --git a/wfe-core/src/main/resources/system.properties b/wfe-core/src/main/resources/system.properties index 6b3ddb89a6..e112e56b7c 100644 --- a/wfe-core/src/main/resources/system.properties +++ b/wfe-core/src/main/resources/system.properties @@ -78,3 +78,5 @@ javamelody.disabled = ${maven.profile.javamelody.disabled} javamelody.datasources = ${maven.profile.hibernate.datasource} statistic.report.enabled=false + +definition.compatibility.check.enabled = true diff --git a/wfe-web/src/main/java/ru/runa/common/web/ActionExceptionHelper.java b/wfe-web/src/main/java/ru/runa/common/web/ActionExceptionHelper.java index 56fd9ab37a..330883a7a7 100644 --- a/wfe-web/src/main/java/ru/runa/common/web/ActionExceptionHelper.java +++ b/wfe-web/src/main/java/ru/runa/common/web/ActionExceptionHelper.java @@ -17,18 +17,14 @@ */ package ru.runa.common.web; +import com.google.common.base.Throwables; import java.util.Locale; - import javax.security.auth.login.LoginException; import javax.servlet.jsp.PageContext; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; - -import com.google.common.base.Throwables; - import ru.runa.wf.web.VariablesFormatException; import ru.runa.wf.web.action.DataFileNotPresentException; import ru.runa.wfe.InternalApplicationException; @@ -39,6 +35,7 @@ import ru.runa.wfe.definition.DefinitionFileDoesNotExistException; import ru.runa.wfe.definition.DefinitionNameMismatchException; import ru.runa.wfe.definition.InvalidDefinitionException; +import ru.runa.wfe.definition.validation.ProcessDefinitionNotCompatibleException; import ru.runa.wfe.execution.ParentProcessExistsException; import ru.runa.wfe.execution.ProcessDoesNotExistException; import ru.runa.wfe.presentation.filter.FilterFormatException; @@ -120,6 +117,10 @@ private static ActionMessage getActionMessage(Throwable e, Locale locale) { DefinitionNameMismatchException exception = (DefinitionNameMismatchException) e; actionMessage = new ActionMessage(MessagesException.ERROR_DEFINITION_NAME_MISMATCH.getKey(), exception.getDeployedProcessDefinitionName(), exception.getGivenProcessDefinitionName()); + } else if (e instanceof ProcessDefinitionNotCompatibleException) { + ProcessDefinitionNotCompatibleException exception = (ProcessDefinitionNotCompatibleException) e; + actionMessage = new ActionMessage(MessagesException.ERROR_DEFINITION_NOT_COMPATIBLE.getKey() + "." + exception.getType(), + exception.getArgs()); } else if (e instanceof TaskDoesNotExistException) { actionMessage = new ActionMessage(MessagesException.ERROR_TASK_DOES_NOT_EXIST.getKey()); } else if (e instanceof SubstitutionDoesNotExistException) { diff --git a/wfe-web/src/main/java/ru/runa/common/web/MessagesException.java b/wfe-web/src/main/java/ru/runa/common/web/MessagesException.java index 2bfe81ad6c..4d0c517651 100644 --- a/wfe-web/src/main/java/ru/runa/common/web/MessagesException.java +++ b/wfe-web/src/main/java/ru/runa/common/web/MessagesException.java @@ -20,6 +20,7 @@ public final class MessagesException { public static final StrutsMessage ERROR_DEFINITION_ALREADY_EXISTS = new StrutsMessage("definition.already.exists.error"); public static final StrutsMessage ERROR_DEFINITION_DOES_NOT_EXIST = new StrutsMessage("definition.does.not.exist.error"); public static final StrutsMessage ERROR_DEFINITION_NAME_MISMATCH = new StrutsMessage("definition.name.mismatch.error"); + public static final StrutsMessage ERROR_DEFINITION_NOT_COMPATIBLE = new StrutsMessage("definition.not.compatible.error"); public static final StrutsMessage ERROR_PROCESS_DOES_NOT_EXIST = new StrutsMessage("process.does.not.exist.error"); public static final StrutsMessage ERROR_TASK_DOES_NOT_EXIST = new StrutsMessage("task.does.not.exist.error"); public static final StrutsMessage ERROR_TASK_FORM_NOT_DEFINED = new StrutsMessage("task.form.not.defined.error"); diff --git a/wfe-web/src/main/resources/settingsList.xml b/wfe-web/src/main/resources/settingsList.xml index 444e79d9c9..6fc7935b14 100644 --- a/wfe-web/src/main/resources/settingsList.xml +++ b/wfe-web/src/main/resources/settingsList.xml @@ -71,6 +71,10 @@ true false + + true + false + diff --git a/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties b/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties index f388675029..7f6d524eb3 100644 --- a/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties +++ b/wfe-web/src/main/webapp/WEB-INF/classes/struts.properties @@ -176,7 +176,9 @@ definition.file.does.not.exist.error = Process definition file "{0}" is missing definition.file.format.error = Process definition "{0}" can not be parsed due to {1} definition.file.not.found = File "{0}" not found in process definition "{1}" definition.name.mismatch.error = Process definition names: "{0}" and "{1}" mismatch -definition.variable.not.found = Variable "{0}" is defined in "{1}" but not defined in variables.xml +definition.not.compatible.error.node.existence = Process definition is not compatible: node {0} has been removed but used in active process {1} +definition.not.compatible.error.parallel.gateway.mistyped = Process definition is not compatible: parallel gateway {0} has different node type +definition.not.compatible.error.parallel.gateway.transitions = Process definition is not compatible: input transitions of parallel gateway {0} has been changed dynamic_group.name = Dynamic Group diff --git a/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties b/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties index 7a385f5a74..c9436f2e7d 100644 --- a/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties +++ b/wfe-web/src/main/webapp/WEB-INF/classes/struts_ru.properties @@ -172,6 +172,9 @@ definition.file.does.not.exist.error = \u041e\u043f\u0440\u0435\u0434\u0435\u043 definition.file.format.error = \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 "{0}" \u043d\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e: {1} definition.file.not.found = \u0424\u0430\u0439\u043b "{0}" \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 "{1}" definition.name.mismatch.error = \u0418\u043c\u0435\u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432: {0} \u0438 {1} \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 +definition.not.compatible.error.node.existence = \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e: \u0443\u0437\u0435\u043b {0} \u0443\u0434\u0430\u043b\u0435\u043d, \u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 {1} +definition.not.compatible.error.parallel.gateway.mistyped = \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e: \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0439 \u0448\u043b\u044e\u0437 {0} \u0441\u043c\u0435\u043d\u0438\u043b \u0442\u0438\u043f \u0443\u0437\u043b\u0430 +definition.not.compatible.error.parallel.gateway.transitions = \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e: \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u044b \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0448\u043b\u044e\u0437\u0430 {0} \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438\u0441\u044c dynamic_group.name = \u0412\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430