From ef0a9f70b225dee7b72fb45573f3d6c2c1f7489d Mon Sep 17 00:00:00 2001 From: ffalqui Date: Mon, 16 Feb 2026 18:25:56 +0100 Subject: [PATCH] Add contentworkflow plugin, fix redirect handling, and refactor system report - Add contentworkflow plugin module with Maven profile - Replace redirectAction result type with redirectActionXF to support correct redirect URLs behind reverse proxies - Refactor system report endpoint to dynamically check installation status of all registered CMS plugins using streams - Update README to document optional CMS plugins --- README.md | 4 +- .../com/agiletec/apsadmin/admin/lang/lang.xml | 2 +- .../admin/localestring/localeString.xml | 2 +- .../agiletec/apsadmin/category/category.xml | 4 +- .../com/agiletec/apsadmin/common/common.xml | 2 +- .../com/agiletec/apsadmin/portal/page.xml | 32 +- .../portal/specialwidget/specialWidget.xml | 2 +- .../agiletec/apsadmin/portal/widgetType.xml | 8 +- .../ServletActionRedirectResultXF.java | 182 ++++++ .../apsadmin/system/entity/entity.xml | 4 +- .../apsadmin/system/entity/type/entity.xml | 22 +- .../agiletec/apsadmin/user/group/group.xml | 4 +- .../com/agiletec/apsadmin/user/role/role.xml | 4 +- .../org/entando/entando/apsadmin/api/api.xml | 6 +- .../common/currentuser/currentUserProfile.xml | 4 +- .../apsadmin/filebrowser/filebrowser.xml | 8 +- .../portal/guifragment/guiFragment.xml | 12 +- .../apsadmin/portal/model/pageModel.xml | 2 +- .../entando/entando/apsadmin/user/user.xml | 10 +- .../entando/apsadmin/user/userprofile.xml | 8 +- admin-console/src/main/resources/struts.xml | 3 +- .../attribute/action/contentAttribute.xml | 12 +- .../jacms/apsadmin/content/content.xml | 20 +- .../apsadmin/content/model/contentModel.xml | 4 +- .../jacms/apsadmin/resource/resource.xml | 4 +- .../plugins/jacms/apsadmin/system/entity.xml | 8 +- .../apsadmin/jsp/common/template/subMenu.jsp | 5 +- .../apsadmin/global-messages_en.properties | 2 +- .../apsadmin/global-messages_it.properties | 2 +- contentworkflow-plugin/pom.xml | 186 ++++++ .../src/main/assembly/classes.xml | 19 + .../JpcontentworkflowSystemConstants.java | 42 ++ .../services/content/ContentSearcherDAO.java | 181 ++++++ .../content/ContentSearcherManager.java | 83 +++ .../services/content/IContentSearcherDAO.java | 42 ++ .../content/IContentSearcherManager.java | 44 ++ .../helper/ContentAuthorizationHelper.java | 105 ++++ .../notifier/IWorkflowNotifierDAO.java | 41 ++ .../notifier/IWorkflowNotifierManager.java | 38 ++ .../notifier/WorkflowNotifierDAO.java | 170 ++++++ .../notifier/WorkflowNotifierManager.java | 537 ++++++++++++++++++ .../model/ContentStatusChangedEventInfo.java | 88 +++ .../notifier/model/NotifierConfig.java | 129 +++++ .../notifier/parse/WorkflowNotifierDOM.java | 182 ++++++ .../notifier/scheduler/MailSenderTask.java | 52 ++ .../notifier/scheduler/Scheduler.java | 66 +++ .../services/notifier/scheduler/Task.java | 37 ++ .../services/workflow/ContentWorkflowDAO.java | 68 +++ .../workflow/ContentWorkflowManager.java | 241 ++++++++ .../workflow/IContentWorkflowDAO.java | 33 ++ .../workflow/IContentWorkflowManager.java | 88 +++ .../system/services/workflow/model/Step.java | 54 ++ .../services/workflow/model/Workflow.java | 74 +++ .../workflow/model/WorkflowSearchFilter.java | 52 ++ .../workflow/parse/ContentWorkflowDOM.java | 157 +++++ .../apsadmin/content/ContentAction.java | 239 ++++++++ .../apsadmin/content/ContentFinderAction.java | 221 +++++++ .../content/IntroNewContentActionAspect.java | 118 ++++ .../content/JpCwIntroNewContentAction.java | 96 ++++ .../apsadmin/content/content.xml | 163 ++++++ .../content/helper/ContentActionHelper.java | 228 ++++++++ .../helper/IContentWorkFlowActionHelper.java | 47 ++ .../apsadmin/content/package_en.properties | 47 ++ .../apsadmin/content/package_it.properties | 47 ++ .../apsadmin/global-messages_en.properties | 19 + .../apsadmin/global-messages_it.properties | 19 + ...orkflowNotifierConfigAction-validation.xml | 54 ++ .../WorkflowNotifierConfigAction.java | 163 ++++++ .../apsadmin/notifier/notifier.xml | 27 + .../apsadmin/notifier/package_en.properties | 37 ++ .../apsadmin/notifier/package_it.properties | 37 ++ .../apsadmin/tags/ContentStepTag.java | 92 +++ .../apsadmin/tags/ContentStepsTag.java | 79 +++ .../workflow/AbstractWorkflowAction.java | 70 +++ .../apsadmin/workflow/WorkflowListAction.java | 68 +++ .../apsadmin/workflow/WorkflowStepAction.java | 361 ++++++++++++ .../apsadmin/workflow/package_en.properties | 35 ++ .../apsadmin/workflow/package_it.properties | 35 ++ .../apsadmin/workflow/workflow.xml | 54 ++ .../jpcontentworkflow/aps/placeholder.txt | 0 .../plugins/jpcontentworkflow/component.xml | 25 + .../main/resources/entando-struts-plugin.xml | 13 + .../jpcontentworkflow/changeSetPort.xml | 12 + .../jpcontentworkflow/changeSetServ.xml | 12 + ..._jpcontentworkflow_dataPort_production.xml | 26 + ...000000_jpcontentworkflow_dataPort_test.xml | 26 + .../port/clob/production/config.xml | 1 + .../port/clob/production/notifier_config.xml | 23 + .../port/clob/test/config.xml | 6 + .../port/clob/test/notifier_config.xml | 14 + ...000000_jpcontentworkflow_dataServ_test.xml | 52 ++ ...415000000_jpcontentworkflow_schemaServ.xml | 34 ++ .../aps/managers/cmsManagersConfig.xml | 25 + .../managers/jpcontentworkflowManagers.xml | 38 ++ .../apsadmin/content/contentActionsConfig.xml | 45 ++ .../notifier/notifierActionsConfig.xml | 15 + .../workflow/workflowActionsConfig.xml | 31 + .../jpcontentworkflow-apsadmin-core.tld | 45 ++ .../apsadmin/jpcontentworkflow-tiles.xml | 33 ++ .../notifier_extraResources.jsp | 3 + .../apsadmin/jsp/common/template/subMenu.jsp | 11 + .../jsp/content/entryContent-actions-jack.jsp | 103 ++++ .../apsadmin/jsp/notifier/config.jsp | 233 ++++++++ .../jsp/notifier/configSavedConfirm.jsp | 35 ++ .../apsadmin/jsp/workflow/entrySteps.jsp | 230 ++++++++ .../apsadmin/jsp/workflow/workflowList.jsp | 109 ++++ .../config/conf/contextTestParams.properties | 46 ++ .../test/config/conf/systemParams.properties | 80 +++ .../src/test/config/entando_logo.jpg | 0 .../resources/cms/documents/text_resource.txt | 2 + .../services/content/TestContentManager.java | 87 +++ .../content/TestContentSearcherDAO.java | 86 +++ .../notifier/TestWorkflowNotifierDAO.java | 126 ++++ .../notifier/TestWorkflowNotifierManager.java | 198 +++++++ .../parse/TestWorkflowNotifierDOM.java | 110 ++++ .../workflow/TestContentWorkflowManager.java | 165 ++++++ .../apsadmin/content/TestContentAction.java | 195 +++++++ .../content/TestContentFinderAction.java | 142 +++++ .../content/TestIntroNewContentAction.java | 110 ++++ .../TestWorkflowNotifierConfigAction.java | 189 ++++++ .../workflow/TestWorkflowListAction.java | 119 ++++ .../workflow/TestWorkflowStepAction.java | 324 +++++++++++ .../util/WorkflowNotifierTestHelper.java | 126 ++++ .../util/WorkflowTestHelper.java | 117 ++++ .../resources/spring/propertyPlaceholder.xml | 10 + .../entando/entando/aps/util/UrlUtils.java | 67 ++- .../entando/web/system/SystemController.java | 15 +- .../jpmail/apsadmin/mail/mailConfig.xml | 4 +- pom.xml | 1 + .../plugins/jpseo/apsadmin/portal/page.xml | 2 +- .../plugins/jpsolr/apsadmin/config/solr.xml | 2 +- .../jpversioning/apsadmin/config/config.xml | 2 +- .../apsadmin/resource/resource.xml | 4 +- .../apsadmin/versioning/versioning.xml | 4 +- webapp/pom.xml | 34 ++ 135 files changed, 8996 insertions(+), 118 deletions(-) create mode 100644 admin-console/src/main/java/com/agiletec/apsadmin/system/dispatcher/ServletActionRedirectResultXF.java create mode 100644 contentworkflow-plugin/pom.xml create mode 100644 contentworkflow-plugin/src/main/assembly/classes.xml create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/JpcontentworkflowSystemConstants.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/ContentSearcherDAO.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/ContentSearcherManager.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/IContentSearcherDAO.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/IContentSearcherManager.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/helper/ContentAuthorizationHelper.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/IWorkflowNotifierDAO.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/IWorkflowNotifierManager.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/WorkflowNotifierDAO.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/WorkflowNotifierManager.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/model/ContentStatusChangedEventInfo.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/model/NotifierConfig.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/parse/WorkflowNotifierDOM.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/MailSenderTask.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/Scheduler.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/Task.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/ContentWorkflowDAO.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/ContentWorkflowManager.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/IContentWorkflowDAO.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/IContentWorkflowManager.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/Step.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/Workflow.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/WorkflowSearchFilter.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/parse/ContentWorkflowDOM.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/ContentAction.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/ContentFinderAction.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/IntroNewContentActionAspect.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/JpCwIntroNewContentAction.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/content.xml create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/helper/ContentActionHelper.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/helper/IContentWorkFlowActionHelper.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/package_en.properties create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/package_it.properties create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/global-messages_en.properties create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/global-messages_it.properties create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/WorkflowNotifierConfigAction-validation.xml create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/WorkflowNotifierConfigAction.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/notifier.xml create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/package_en.properties create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/package_it.properties create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/tags/ContentStepTag.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/tags/ContentStepsTag.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/AbstractWorkflowAction.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/WorkflowListAction.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/WorkflowStepAction.java create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/package_en.properties create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/package_it.properties create mode 100644 contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/workflow.xml create mode 100644 contentworkflow-plugin/src/main/resources/api/plugins/jpcontentworkflow/aps/placeholder.txt create mode 100644 contentworkflow-plugin/src/main/resources/component/plugins/jpcontentworkflow/component.xml create mode 100644 contentworkflow-plugin/src/main/resources/entando-struts-plugin.xml create mode 100644 contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/changeSetPort.xml create mode 100644 contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/changeSetServ.xml create mode 100644 contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/20240415000000_jpcontentworkflow_dataPort_production.xml create mode 100644 contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/20240415000000_jpcontentworkflow_dataPort_test.xml create mode 100644 contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/production/config.xml create mode 100644 contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/production/notifier_config.xml create mode 100644 contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/test/config.xml create mode 100644 contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/test/notifier_config.xml create mode 100644 contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/serv/20240415000000_jpcontentworkflow_dataServ_test.xml create mode 100644 contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/serv/20240415000000_jpcontentworkflow_schemaServ.xml create mode 100644 contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/aps/managers/cmsManagersConfig.xml create mode 100644 contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/aps/managers/jpcontentworkflowManagers.xml create mode 100644 contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/content/contentActionsConfig.xml create mode 100644 contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/notifier/notifierActionsConfig.xml create mode 100644 contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/workflow/workflowActionsConfig.xml create mode 100644 contentworkflow-plugin/src/main/tld/plugins/jpcontentworkflow/jpcontentworkflow-apsadmin-core.tld create mode 100644 contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jpcontentworkflow-tiles.xml create mode 100644 contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/common/template/extraresources/notifier_extraResources.jsp create mode 100644 contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/common/template/subMenu.jsp create mode 100644 contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/content/entryContent-actions-jack.jsp create mode 100644 contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/notifier/config.jsp create mode 100644 contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/notifier/configSavedConfirm.jsp create mode 100644 contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/workflow/entrySteps.jsp create mode 100644 contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/workflow/workflowList.jsp create mode 100644 contentworkflow-plugin/src/test/config/conf/contextTestParams.properties create mode 100644 contentworkflow-plugin/src/test/config/conf/systemParams.properties create mode 100644 contentworkflow-plugin/src/test/config/entando_logo.jpg create mode 100644 contentworkflow-plugin/src/test/config/resources/cms/documents/text_resource.txt create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/TestContentManager.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/TestContentSearcherDAO.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/TestWorkflowNotifierDAO.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/TestWorkflowNotifierManager.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/parse/TestWorkflowNotifierDOM.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/TestContentWorkflowManager.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestContentAction.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestContentFinderAction.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestIntroNewContentAction.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/TestWorkflowNotifierConfigAction.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/TestWorkflowListAction.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/TestWorkflowStepAction.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/util/WorkflowNotifierTestHelper.java create mode 100644 contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/util/WorkflowTestHelper.java create mode 100644 contentworkflow-plugin/src/test/resources/spring/propertyPlaceholder.xml diff --git a/README.md b/README.md index fc67935f80..61f64addf3 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ The application will be available at http://localhost:8080/entando-de-app/ More information are available on [webapp README](webapp/README.md). -## Content Scheduler Plugin +## Optional CMS Plugins -The Content Scheduler Plugin is disabled by default. It can be included in the webapp activating the `contentscheduler` Maven profile during the build. +The Content Scheduler Plugin and the Content Workflow Plugin are disabled by default. They can be included in the webapp activating the `contentscheduler` and/or `contentworkflow` Maven profiles during the build. ## Testing diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/admin/lang/lang.xml b/admin-console/src/main/java/com/agiletec/apsadmin/admin/lang/lang.xml index ccee565632..7112592dea 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/admin/lang/lang.xml +++ b/admin-console/src/main/java/com/agiletec/apsadmin/admin/lang/lang.xml @@ -17,7 +17,7 @@ list - list + list superuser diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/admin/localestring/localeString.xml b/admin-console/src/main/java/com/agiletec/apsadmin/admin/localestring/localeString.xml index 2289b39b1e..afa3e9351e 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/admin/localestring/localeString.xml +++ b/admin-console/src/main/java/com/agiletec/apsadmin/admin/localestring/localeString.xml @@ -34,7 +34,7 @@ admin.LocaleString.entry - list + list superuser diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/category/category.xml b/admin-console/src/main/java/com/agiletec/apsadmin/category/category.xml index 15828e04fe..2e769467c3 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/category/category.xml +++ b/admin-console/src/main/java/com/agiletec/apsadmin/category/category.xml @@ -59,7 +59,7 @@ admin.Category.entry - + viewTree ${categoryCode} @@ -94,7 +94,7 @@ - viewTree + viewTree viewTree manageCategories diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/common/common.xml b/admin-console/src/main/java/com/agiletec/apsadmin/common/common.xml index 7783d5a938..1c1bfeb49b 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/common/common.xml +++ b/admin-console/src/main/java/com/agiletec/apsadmin/common/common.xml @@ -26,7 +26,7 @@ /WEB-INF/apsadmin/jsp/common/login.jsp - main + main diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/portal/page.xml b/admin-console/src/main/java/com/agiletec/apsadmin/portal/page.xml index 8227368700..5c335e1916 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/portal/page.xml +++ b/admin-console/src/main/java/com/agiletec/apsadmin/portal/page.xml @@ -250,7 +250,7 @@ admin.Page.references - + viewTree ${selectedNode} @@ -262,7 +262,7 @@ admin.Page.entry - + viewTree ${pageCode} @@ -274,7 +274,7 @@ admin.Page.entry - + configure ${selectedNode} @@ -311,7 +311,7 @@ admin.Page.references viewTree - + viewTree ${pageCode} @@ -331,7 +331,7 @@ viewTree - + viewTree ${pageCode} @@ -342,7 +342,7 @@ - + configure ${selectedNode} @@ -364,7 +364,7 @@ admin.Page.viewTreeMenu - + configure ${pageCode} @@ -376,7 +376,7 @@ admin.Page.viewTreeMenu - + configure ${pageCode} @@ -391,7 +391,7 @@ - + configure ${selectedNode} @@ -403,7 +403,7 @@ admin.Page.viewTreeMenu - + /do/Page viewTree @@ -423,7 +423,7 @@ admin.Page.viewTreeMenu - + /do/Page viewTree @@ -456,7 +456,7 @@ - systemParams + systemParams superuser @@ -515,7 +515,7 @@ - viewTree + viewTree admin.Page.searchResult admin.Page.searchResult @@ -557,7 +557,7 @@ - + configure ${pageCode} @@ -568,7 +568,7 @@ - + configure ${selectedNode} @@ -578,7 +578,7 @@ - + configure ${selectedNode} diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/portal/specialwidget/specialWidget.xml b/admin-console/src/main/java/com/agiletec/apsadmin/portal/specialwidget/specialWidget.xml index ed49560245..e2cb398483 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/portal/specialwidget/specialWidget.xml +++ b/admin-console/src/main/java/com/agiletec/apsadmin/portal/specialwidget/specialWidget.xml @@ -12,7 +12,7 @@ /do/Page viewTree - + /do/Page configure ${pageCode} diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/portal/widgetType.xml b/admin-console/src/main/java/com/agiletec/apsadmin/portal/widgetType.xml index d533c41e7a..4e676172a3 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/portal/widgetType.xml +++ b/admin-console/src/main/java/com/agiletec/apsadmin/portal/widgetType.xml @@ -90,7 +90,7 @@ - + viewWidgetUtilizers ${showletTypeCode} @@ -131,12 +131,12 @@ admin.Portal.showletType.entry - + /do/Page configure ${pageCode} - viewWidgets + viewWidgets managePages @@ -150,7 +150,7 @@ - + viewWidgets diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/system/dispatcher/ServletActionRedirectResultXF.java b/admin-console/src/main/java/com/agiletec/apsadmin/system/dispatcher/ServletActionRedirectResultXF.java new file mode 100644 index 0000000000..73e31e7a8c --- /dev/null +++ b/admin-console/src/main/java/com/agiletec/apsadmin/system/dispatcher/ServletActionRedirectResultXF.java @@ -0,0 +1,182 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + */ +package com.agiletec.apsadmin.system.dispatcher; + +import org.apache.struts2.ActionInvocation; +import org.entando.entando.ent.util.EntLogging.EntLogFactory; +import org.entando.entando.ent.util.EntLogging.EntLogger; +import org.apache.struts2.util.reflection.ReflectionExceptionHandler; +import lombok.Setter; +import org.apache.struts2.ServletActionContext; +import org.apache.struts2.dispatcher.mapper.ActionMapper; +import org.apache.struts2.dispatcher.mapper.ActionMapping; +import org.apache.struts2.result.ServletRedirectResult; +import org.entando.entando.aps.util.UrlUtils; + +import jakarta.servlet.http.HttpServletRequest; +import java.util.Arrays; +import java.util.List; + +/** + * Redirect Action Result con ancora. + * Questo resultType รจ utilizzato per permettere il redirezionamento ad una url che invoca una specifica action + * (opzionalmente un namespace) con una specifica ancora. + *

+ * See examples below for an example of how request parameters could be passed in. + *

+ * + * + * This result type takes the following parameters: + *

+ * + * + *

    + * + *
  • actionName (default) - the name of the action that will be redirect to
  • + * + *
  • namespace - used to determine which namespace the action is in that we're redirecting to . If namespace is + * null, this defaults to the current namespace
  • + * + *
  • supressEmptyParameters - optional boolean (defaults to false) that can prevent parameters with no values + * from being included in the redirect URL.
  • + * + *
+ *

+ * + * + * Example: + * + *


+ * <package name="public" extends="struts-default">
+ *     <action name="login" class="...">
+ *         <!-- Redirect to another namespace -->
+ *         <result type="redirectActionWithAnchor">
+ *             <param name="actionName">dashboard</param>
+ *             <param name="namespace">/secure</param>
+ *             <param name="anchorDest">lang_it/param>
+ *         </result>
+ *     </action>
+ * </package>
+ *
+ * 
+ * @see ActionMapper + */ +public class ServletActionRedirectResultXF extends ServletRedirectResult implements ReflectionExceptionHandler { + + private static final long serialVersionUID = 5004297536492031384L; + + /** The default parameter */ + public static final String DEFAULT_PARAM = "actionName"; + + private static final EntLogger LOG = EntLogFactory.getSanitizedLogger(ServletActionRedirectResultXF.class); + + /** + * -- SETTER -- + * Sets the action name + * @param actionName The name + */ + @Setter + protected String actionName; + /** + * -- SETTER -- + * Sets the namespace + * @param namespace The namespace + */ + @Setter + protected String namespace; + /** + * -- SETTER -- + * Sets the method + * @param method The method + */ + @Setter + protected String method; + @Setter + private String anchorDest; + + public ServletActionRedirectResultXF() { + super(); + } + + public ServletActionRedirectResultXF(String actionName) { + this(null, actionName, null, null); + } + + public ServletActionRedirectResultXF(String actionName, String method) { + this(null, actionName, method, null); + } + + + public ServletActionRedirectResultXF(String namespace, String actionName, String method) { + this(namespace, actionName, method, null); + } + + public ServletActionRedirectResultXF(String namespace, String actionName, String method, String anchor) { + super(null, anchor); + this.namespace = namespace; + this.actionName = actionName; + this.method = method; + } + + @Override + public void execute(ActionInvocation invocation) throws Exception { + this.actionName = this.conditionalParse(this.actionName, invocation); + if (this.namespace == null) { + this.namespace = invocation.getProxy().getNamespace(); + } else { + this.namespace = this.conditionalParse(this.namespace, invocation); + } + if (this.method == null) { + this.method = ""; + } else { + this.method = this.conditionalParse(this.method, invocation); + } + + HttpServletRequest request = ServletActionContext.getRequest(); + + String frontendScheme = UrlUtils.determineFrontendUrlObject(request).toURI().getScheme(); + String frontendServerName = UrlUtils.determineFrontendUrlObject(request).getHost(); + int frontendPort = UrlUtils.determineFrontendUrlObject(request).getPort(); + + String sbLocation = frontendScheme + "://" + + frontendServerName + ((frontendPort != -1) ? ":" + frontendPort : "") + + request.getContextPath() + + this.actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null)); + + if (null != this.anchorDest) { + this.setAnchor(this.anchorDest); + } + +// System.out.println("\n" + +// "\n" + "|----------------------------------------------------------------------------------" + +// "\n" + "|- frontendScheme => " + frontendScheme + +// "\n" + "|- frontendServerName => " + frontendServerName + +// "\n" + "|- frontendPort => " + frontendPort + +// "\n" + "|- sbLocation => " + sbLocation + +// "\n" + "|----------------------------------------------------------------------------------" + +// "\n"); + + setLocation(sbLocation); + + super.execute(invocation); + } + + @Override + protected List getProhibitedResultParams() { + return Arrays.asList(DEFAULT_PARAM, + "namespace", "method", "encode", "parse", "location", + "prependServletContext", "supressEmptyParameters", "anchor", "anchorDest" + ); + } +} diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/system/entity/entity.xml b/admin-console/src/main/java/com/agiletec/apsadmin/system/entity/entity.xml index be40a34f63..2f7613061f 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/system/entity/entity.xml +++ b/admin-console/src/main/java/com/agiletec/apsadmin/system/entity/entity.xml @@ -17,7 +17,7 @@ admin.entityManagement.viewManagers - + viewManagers ${entityManagerName} @@ -32,7 +32,7 @@ - search + search superuser diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/system/entity/type/entity.xml b/admin-console/src/main/java/com/agiletec/apsadmin/system/entity/type/entity.xml index de502e8063..b3f6737a7b 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/system/entity/type/entity.xml +++ b/admin-console/src/main/java/com/agiletec/apsadmin/system/entity/type/entity.xml @@ -35,7 +35,7 @@ viewEntityTypes
- + /do${entityTypeManagementNamespacePrefix}/Entity viewEntityTypes ${entityManagerName} @@ -72,7 +72,7 @@ initViewEntityTypes admin.entityManagement.removeEntityTypeWithReferences - + initViewEntityTypes ${entityManagerName} @@ -107,7 +107,7 @@ admin.entityManagement.entryEntityType - + /do/Entity/Attribute addAttribute ${attributeTypeCode} @@ -118,7 +118,7 @@ admin.entityManagement.entryEntityType - + /do/Entity/Attribute editAttribute ${attributeName} @@ -149,7 +149,7 @@ admin.entityManagement.entryEntityType - + initViewEntityTypes ${entityManagerName} @@ -192,15 +192,15 @@ admin.entityManagement.entryEntityAttributeType - + /do/Entity/ListAttribute configureListElement - + /do/Entity/CompositeAttribute entryCompositeAttribute - + /do${entityTypeManagementNamespacePrefix}/Entity entryEntityType @@ -218,7 +218,7 @@ admin.entityManagement.textListElement.entryEntityAttributeType - + /do${entityTypeManagementNamespacePrefix}/Entity entryEntityType @@ -251,7 +251,7 @@ - + /do${entityTypeManagementNamespacePrefix}/Entity entryEntityType @@ -266,7 +266,7 @@ admin.entityManagement.compositeAttribute.entryAttributeElementType - entryCompositeAttribute + entryCompositeAttribute superuser diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/user/group/group.xml b/admin-console/src/main/java/com/agiletec/apsadmin/user/group/group.xml index f23734668e..e57c514d8e 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/user/group/group.xml +++ b/admin-console/src/main/java/com/agiletec/apsadmin/user/group/group.xml @@ -34,7 +34,7 @@ admin.Group.entry - list + list superuser @@ -48,7 +48,7 @@ admin.Group.references list - list + list superuser diff --git a/admin-console/src/main/java/com/agiletec/apsadmin/user/role/role.xml b/admin-console/src/main/java/com/agiletec/apsadmin/user/role/role.xml index 8cd092f7f3..b77872ef62 100644 --- a/admin-console/src/main/java/com/agiletec/apsadmin/user/role/role.xml +++ b/admin-console/src/main/java/com/agiletec/apsadmin/user/role/role.xml @@ -28,7 +28,7 @@ admin.Role.entry - list + list superuser @@ -46,7 +46,7 @@ - list + list admin.Role.references list superuser diff --git a/admin-console/src/main/java/org/entando/entando/apsadmin/api/api.xml b/admin-console/src/main/java/org/entando/entando/apsadmin/api/api.xml index 767e93cab8..b28796f060 100644 --- a/admin-console/src/main/java/org/entando/entando/apsadmin/api/api.xml +++ b/admin-console/src/main/java/org/entando/entando/apsadmin/api/api.xml @@ -110,7 +110,7 @@ admin.api.service.entry - list + list superuser @@ -159,7 +159,7 @@ admin.api.consumer.entry - list + list superuser @@ -171,7 +171,7 @@ list - list + list superuser diff --git a/admin-console/src/main/java/org/entando/entando/apsadmin/common/currentuser/currentUserProfile.xml b/admin-console/src/main/java/org/entando/entando/apsadmin/common/currentuser/currentUserProfile.xml index e0dac436d3..f8ebaa8300 100644 --- a/admin-console/src/main/java/org/entando/entando/apsadmin/common/currentuser/currentUserProfile.xml +++ b/admin-console/src/main/java/org/entando/entando/apsadmin/common/currentuser/currentUserProfile.xml @@ -46,14 +46,14 @@ - + entryProfile - + entryProfile diff --git a/admin-console/src/main/java/org/entando/entando/apsadmin/filebrowser/filebrowser.xml b/admin-console/src/main/java/org/entando/entando/apsadmin/filebrowser/filebrowser.xml index 63f60e2efe..96685a271d 100644 --- a/admin-console/src/main/java/org/entando/entando/apsadmin/filebrowser/filebrowser.xml +++ b/admin-console/src/main/java/org/entando/entando/apsadmin/filebrowser/filebrowser.xml @@ -50,7 +50,7 @@ admin.Filebrowser.newDir - + list ${currentPath} ${protectedFolder} @@ -63,7 +63,7 @@ admin.Filebrowser.entryFile - + list ${currentPath} ${protectedFolder} @@ -94,7 +94,7 @@ admin.Filebrowser.list - + list ${currentPath} ${protectedFolder} @@ -107,7 +107,7 @@ admin.Filebrowser.upload - + list ${currentPath} ${protectedFolder} diff --git a/admin-console/src/main/java/org/entando/entando/apsadmin/portal/guifragment/guiFragment.xml b/admin-console/src/main/java/org/entando/entando/apsadmin/portal/guifragment/guiFragment.xml index a39ceeb2f2..a9e6b7cfa3 100644 --- a/admin-console/src/main/java/org/entando/entando/apsadmin/portal/guifragment/guiFragment.xml +++ b/admin-console/src/main/java/org/entando/entando/apsadmin/portal/guifragment/guiFragment.xml @@ -27,27 +27,27 @@ admin.Portal.GuiFragment.entry - list + list superuser admin.Portal.GuiFragment.entry - list + list superuser admin.Portal.GuiFragment.trash admin.Portal.GuiFragment.references - list + list superuser - list + list admin.Portal.GuiFragment.references - list + list superuser @@ -64,7 +64,7 @@ - systemParams + systemParams superuser diff --git a/admin-console/src/main/java/org/entando/entando/apsadmin/portal/model/pageModel.xml b/admin-console/src/main/java/org/entando/entando/apsadmin/portal/model/pageModel.xml index 7e137ef09b..368fb08b7e 100644 --- a/admin-console/src/main/java/org/entando/entando/apsadmin/portal/model/pageModel.xml +++ b/admin-console/src/main/java/org/entando/entando/apsadmin/portal/model/pageModel.xml @@ -86,7 +86,7 @@ admin.PageModel.references list - list + list superuser diff --git a/admin-console/src/main/java/org/entando/entando/apsadmin/user/user.xml b/admin-console/src/main/java/org/entando/entando/apsadmin/user/user.xml index b3f2bace74..9c633d1a4a 100644 --- a/admin-console/src/main/java/org/entando/entando/apsadmin/user/user.xml +++ b/admin-console/src/main/java/org/entando/entando/apsadmin/user/user.xml @@ -47,18 +47,18 @@ admin.User.entry - list + list editUsers admin.User.entry - + /do/userprofile edit ${username} - list + list editUsers @@ -81,7 +81,7 @@ - systemParams + systemParams superuser @@ -118,7 +118,7 @@ - + /do/User list diff --git a/admin-console/src/main/java/org/entando/entando/apsadmin/user/userprofile.xml b/admin-console/src/main/java/org/entando/entando/apsadmin/user/userprofile.xml index fef95e5c5c..05a1fa24d4 100644 --- a/admin-console/src/main/java/org/entando/entando/apsadmin/user/userprofile.xml +++ b/admin-console/src/main/java/org/entando/entando/apsadmin/user/userprofile.xml @@ -39,7 +39,7 @@ - + /do/User list @@ -60,7 +60,7 @@ - + /do/User list @@ -92,7 +92,7 @@ - + entryProfile @@ -102,7 +102,7 @@ - + entryProfile diff --git a/admin-console/src/main/resources/struts.xml b/admin-console/src/main/resources/struts.xml index 85d2a2e895..b5c565050e 100644 --- a/admin-console/src/main/resources/struts.xml +++ b/admin-console/src/main/resources/struts.xml @@ -19,6 +19,7 @@ + @@ -79,7 +80,7 @@ /index.jsp admin.genericError admin.userNotAllowedMessage - + login /do diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/attribute/action/contentAttribute.xml b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/attribute/action/contentAttribute.xml index bf6e249c80..d5d04fd530 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/attribute/action/contentAttribute.xml +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/attribute/action/contentAttribute.xml @@ -138,15 +138,15 @@ - + configUrlLink ${contentOnSessionMarker} - + configPageLink ${contentOnSessionMarker} - + configContentLink ${contentOnSessionMarker} @@ -158,15 +158,15 @@ admin.jacms.content.chooseLinkType - + configUrlLink ${contentOnSessionMarker} - + configPageLink ${contentOnSessionMarker} - + configContentLink ${contentOnSessionMarker} diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/content.xml b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/content.xml index 15f832824d..c1d189188c 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/content.xml +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/content.xml @@ -187,7 +187,7 @@ admin.jacms.content.new - + entryContent ${contentOnSessionMarker} @@ -196,7 +196,7 @@ admin.jacms.content.new - + entryContent ${contentOnSessionMarker} @@ -219,7 +219,7 @@ - + entryContent ${categoryCode} ${contentOnSessionMarker} @@ -229,7 +229,7 @@ - + entryContent ${contentOnSessionMarker} @@ -250,7 +250,7 @@ admin.jacms.content.entry - results + results editContents @@ -262,7 +262,7 @@ admin.jacms.content.entry - results + results validateContents @@ -270,7 +270,7 @@ admin.jacms.content.entry admin.jacms.content.references - results + results validateContents @@ -278,7 +278,7 @@ - + chooseResource ${attributeName} ${elementIndex} @@ -286,7 +286,7 @@ ${listLangCode} ${contentOnSessionMarker} - + chooseLink ${attributeName} ${elementIndex} @@ -326,7 +326,7 @@ - + /do/jacms/Content/Resource findResource ${attributeName} diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/model/contentModel.xml b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/model/contentModel.xml index f982aca16c..460ebf9f73 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/model/contentModel.xml +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/content/model/contentModel.xml @@ -51,7 +51,7 @@ admin.jacms.contentModel.entry - list + list validateContents @@ -60,7 +60,7 @@ admin.jacms.contentModel.reference admin.jacms.contentModel.trash - list + list validateContents diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/resource/resource.xml b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/resource/resource.xml index 4a70f468f2..644d68bd38 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/resource/resource.xml +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/resource/resource.xml @@ -134,7 +134,7 @@ admin.jacms.resource.entry admin.jacms.resource.entry - + list ${resourceTypeCode} @@ -187,7 +187,7 @@ - + /do/jacms/Resource list ${resourceTypeCode} diff --git a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/system/entity.xml b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/system/entity.xml index a4a8d79bf2..14e35985d6 100644 --- a/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/system/entity.xml +++ b/cms-plugin/src/main/java/com/agiletec/plugins/jacms/apsadmin/system/entity.xml @@ -24,7 +24,7 @@ /do/jacms/Entity viewEntityTypes - + /do/jacms/Entity viewEntityTypes ${entityManagerName} @@ -61,7 +61,7 @@ admin.jacms.entityManagement.viewEntityType - + /do/Entity/Attribute addAttribute ${attributeTypeCode} @@ -71,7 +71,7 @@ admin.jacms.entityManagement.viewEntityType - + /do/Entity/Attribute editAttribute ${attributeName} @@ -97,7 +97,7 @@ admin.jacms.entityManagement.viewEntityType - + /do/Entity initViewEntityTypes ${entityManagerName} diff --git a/cms-plugin/src/main/webapp/WEB-INF/plugins/jacms/apsadmin/jsp/common/template/subMenu.jsp b/cms-plugin/src/main/webapp/WEB-INF/plugins/jacms/apsadmin/jsp/common/template/subMenu.jsp index 687cf8557b..70dc0f5616 100644 --- a/cms-plugin/src/main/webapp/WEB-INF/plugins/jacms/apsadmin/jsp/common/template/subMenu.jsp +++ b/cms-plugin/src/main/webapp/WEB-INF/plugins/jacms/apsadmin/jsp/common/template/subMenu.jsp @@ -51,13 +51,11 @@ - + - -
  • jacmsContentManager"> @@ -68,7 +66,6 @@
  • - diff --git a/contentscheduler-plugin/src/main/java/org/entando/entando/plugins/jpcontentscheduler/apsadmin/global-messages_en.properties b/contentscheduler-plugin/src/main/java/org/entando/entando/plugins/jpcontentscheduler/apsadmin/global-messages_en.properties index c4f7adc063..c95cc302bf 100644 --- a/contentscheduler-plugin/src/main/java/org/entando/entando/plugins/jpcontentscheduler/apsadmin/global-messages_en.properties +++ b/contentscheduler-plugin/src/main/java/org/entando/entando/plugins/jpcontentscheduler/apsadmin/global-messages_en.properties @@ -1,7 +1,7 @@ jpcontentscheduler.code=jpcontentscheduler jpcontentscheduler.name=Content Scheduler -jpcontentscheduler.title.management=Content Scheduler +jpcontentscheduler.title.management=Scheduler jpcontentscheduler.integrations=Integrations jpcontentscheduler.components=Components diff --git a/contentscheduler-plugin/src/main/java/org/entando/entando/plugins/jpcontentscheduler/apsadmin/global-messages_it.properties b/contentscheduler-plugin/src/main/java/org/entando/entando/plugins/jpcontentscheduler/apsadmin/global-messages_it.properties index f53f9dc28f..85d403dff0 100644 --- a/contentscheduler-plugin/src/main/java/org/entando/entando/plugins/jpcontentscheduler/apsadmin/global-messages_it.properties +++ b/contentscheduler-plugin/src/main/java/org/entando/entando/plugins/jpcontentscheduler/apsadmin/global-messages_it.properties @@ -1,7 +1,7 @@ jpcontentscheduler.code=jpcontentscheduler jpcontentscheduler.name=Content Scheduler -jpcontentscheduler.title.management=Content Scheduler Management +jpcontentscheduler.title.management=Scheduler jpcontentscheduler.integrations=Integrations jpcontentscheduler.components=Componenti diff --git a/contentworkflow-plugin/pom.xml b/contentworkflow-plugin/pom.xml new file mode 100644 index 0000000000..532e9dba9c --- /dev/null +++ b/contentworkflow-plugin/pom.xml @@ -0,0 +1,186 @@ + + + 4.0.0 + + org.entando + app-engine + 7.5.0-SNAPSHOT + + entando-plugin-jpcontentworkflow + org.entando.entando.plugins + jar + Entando Plugin: Content Workflow + Extends the basic CMS workflow and allowing customizable workflows for content categories + + + e.santoboni + Eugenio Santoboni + eugenio.santoboni@gmail.com + + + + + + src/main/resources + + src/main/resources/component + + + + src/main/resources + + **/*component.xml + + true + + + src/main/java + + **/*.properties + **/*.xml + **/*.xsd + **/*.txt + + + + src/test/java + + **/*.sql + **/*.json + + + + src/main/tld + META-INF + + **/*.tld + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + + + + org.entando.entando.plugins + entando-plugin-jacms + ${project.version} + + + org.entando.entando + entando-admin-console + ${project.version} + + + + org.entando.entando.plugins + entando-plugin-jpmail + ${project.version} + + + + jakarta.servlet + jakarta.servlet-api + + + jakarta.servlet.jsp + jakarta.servlet.jsp-api + + + + + + org.entando.entando + entando-engine + ${project.version} + test-jar + test + + + org.entando.entando + entando-admin-console + ${project.version} + test-jar + test + + + org.entando.entando.plugins + entando-plugin-jacms + ${project.version} + test-jar + test + + + org.junit.jupiter + junit-jupiter + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.mockito + mockito-junit-jupiter + test + + + org.springframework + spring-test + test + + + org.assertj + assertj-core + test + + + org.hamcrest + hamcrest-all + test + + + com.jayway.jsonpath + json-path-assert + test + + + org.apache.derby + derbyclient + test + + + org.apache.derby + derby + test + + + org.apache.derby + derbytools + + + org.testcontainers + junit-jupiter + test + + + org.mockito + mockito-inline + test + + + + + + diff --git a/contentworkflow-plugin/src/main/assembly/classes.xml b/contentworkflow-plugin/src/main/assembly/classes.xml new file mode 100644 index 0000000000..65bafd9a3e --- /dev/null +++ b/contentworkflow-plugin/src/main/assembly/classes.xml @@ -0,0 +1,19 @@ + + classes + + jar + + false + + + ${project.build.outputDirectory} + + **/* + + + + + diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/JpcontentworkflowSystemConstants.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/JpcontentworkflowSystemConstants.java new file mode 100644 index 0000000000..e2441419bd --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/JpcontentworkflowSystemConstants.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system; + +/** + * @author E.Santoboni + */ +public interface JpcontentworkflowSystemConstants { + + public static final String CONTENT_SEARCHER_MANAGER = "jpcontentworkflowContentSearcherManager"; + + public static final String CONTENT_WORKFLOW_MANAGER = "jpcontentworkflowWorkflowManager"; + + public static final String CONTENT_WORKFLOW_CONFIG_ITEM = "jpcontentworkflow_config"; + + public static final String WORKFLOW_NOTIFIER_CONFIG_ITEM = "jpcontentworkflow_notifierConfig"; + + /** + * Nome del servizio gestore delle notifiche di passaggio di stato dei contenuti. + */ + public static final String WORKFLOW_NOTIFIER_MANAGER = "jpcontentworkflowNotifierManager"; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/ContentSearcherDAO.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/ContentSearcherDAO.java new file mode 100644 index 0000000000..077e2f3bab --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/ContentSearcherDAO.java @@ -0,0 +1,181 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.content; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.agiletec.aps.system.common.entity.model.EntitySearchFilter; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.WorkflowSearchFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author E.Santoboni + */ +public class ContentSearcherDAO extends com.agiletec.plugins.jacms.aps.system.services.content.WorkContentSearcherDAO + implements IContentSearcherDAO { + + private static final Logger _logger = LoggerFactory.getLogger(ContentSearcherDAO.class); + + @Override + public int countContents(List workflowFilters, + String[] categories, boolean orClauseCategoryFilter, EntitySearchFilter[] filters, Collection userGroupCodes) { + Connection conn = null; + int count = 0; + PreparedStatement stat = null; + ResultSet result = null; + try { + conn = this.getConnection(); + stat = this.buildStatement(workflowFilters, filters, categories, + orClauseCategoryFilter, userGroupCodes, true, false, conn); + result = stat.executeQuery(); + if (result.next()) { + count = result.getInt(1); + } + } catch (Throwable t) { + _logger.error("Error while loading the count of IDs", t); + throw new RuntimeException("Error while loading the count of IDs", t); + } finally { + closeDaoResources(result, stat, conn); + } + return count; + } + + @Override + public List loadContentsId(List workflowFilters, + String[] categories, EntitySearchFilter[] filters, Collection userGroupCodes) { + return this.loadContentsId(workflowFilters, categories, false, filters, userGroupCodes); + } + + @Override + public List loadContentsId(List workflowFilters, + String[] categories, boolean orClauseCategoryFilter, EntitySearchFilter[] filters, Collection userGroupCodes) { + List contentsId = new ArrayList<>(); + if (workflowFilters.isEmpty() || userGroupCodes == null || userGroupCodes.isEmpty()) { + return contentsId; + } + Connection conn = null; + PreparedStatement stat = null; + ResultSet result = null; + try { + conn = this.getConnection(); + stat = this.buildStatement(workflowFilters, filters, categories, orClauseCategoryFilter, userGroupCodes, false, false, conn); + result = stat.executeQuery(); + while (result.next()) { + String id = result.getString(this.getMasterTableIdFieldName()); + if (!contentsId.contains(id)) { + contentsId.add(id); + } + } + } catch (Throwable t) { + _logger.error("Error loading content list", t); + throw new RuntimeException("Error loading content list", t); + } finally { + closeDaoResources(result, stat, conn); + } + return contentsId; + } + + private PreparedStatement buildStatement(List workflowFilters, + EntitySearchFilter[] filters, String[] categories, boolean orClauseCategoryFilter, Collection userGroupCodes, boolean isCount, boolean selectAll, Connection conn) { + Collection groupsForSelect = this.getGroupsForSelect(userGroupCodes); + String query = this.createQueryString(workflowFilters, filters, categories, orClauseCategoryFilter, groupsForSelect, isCount, selectAll); + PreparedStatement stat = null; + try { + stat = conn.prepareStatement(query); + int index = 0; + index = super.addAttributeFilterStatementBlock(filters, index, stat); + index = this.addMetadataFieldFilterStatementBlock(filters, index, stat); + if (groupsForSelect != null) { + index = this.addGroupStatementBlock(groupsForSelect, index, stat); + } + if (categories != null) { + for (int i=0; i workflowFilters, + EntitySearchFilter[] filters, String[] categories, boolean orClauseCategoryFilter, Collection groupsForSelect, boolean isCount, boolean selectAll) { + StringBuffer query = this.createBaseQueryBlock(filters, isCount, selectAll); + boolean hasAppendWhereClause = this.appendFullAttributeFilterQueryBlocks(filters, query, false); + hasAppendWhereClause = this.appendMetadataFieldFilterQueryBlocks(filters, query, hasAppendWhereClause); + if (groupsForSelect != null && !groupsForSelect.isEmpty()) { + hasAppendWhereClause = this.verifyWhereClauseAppend(query, hasAppendWhereClause); + this.addGroupsQueryBlock(query, groupsForSelect); + } + if (categories != null) { + hasAppendWhereClause = this.verifyWhereClauseAppend(query, hasAppendWhereClause); + for (int i=0; i0) { + query.append((orClauseCategoryFilter) ? " OR " :" AND "); + } + query.append(" contents.contentid IN (SELECT contentid FROM ") + .append(this.getContentRelationsTableName()).append(" WHERE ") + .append(this.getContentRelationsTableName()).append(".refcategory = ? ) "); + } + } + hasAppendWhereClause = this.verifyWhereClauseAppend(query, hasAppendWhereClause); + query.append(" ( "); + int i = 0; + for (WorkflowSearchFilter filter : workflowFilters) { + if (i++>0) query.append(" OR "); + query.append("( contents.contenttype = ? AND contents.status IN ( "); + int steps = filter.getAllowedSteps().size(); + if (steps-- > 0) { + query.append("? "); + } + while (steps-- > 0) { + query.append(", ?"); + } + query.append(" )) "); + } + query.append(") "); + if (!isCount) { + appendOrderQueryBlocks(filters, query, false); + this.appendLimitQueryBlock(filters, query); + } + return query.toString(); + } + +} diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/ContentSearcherManager.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/ContentSearcherManager.java new file mode 100644 index 0000000000..597bd28e74 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/ContentSearcherManager.java @@ -0,0 +1,83 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.content; + +import java.util.Collection; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.agiletec.aps.system.common.AbstractService; +import com.agiletec.aps.system.common.entity.model.EntitySearchFilter; +import com.agiletec.aps.system.common.model.dao.SearcherDaoPaginatedResult; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.WorkflowSearchFilter; + +/** + * @author E.Santoboni + */ +public class ContentSearcherManager extends AbstractService implements IContentSearcherManager { + + private static final Logger _logger = LoggerFactory.getLogger(ContentSearcherManager.class); + + private IContentSearcherDAO contentSearcherDAO; + + @Override + public void init() throws Exception { + _logger.debug("{} ready", this.getClass().getName()); + } + + @Override + @Deprecated + public List loadContentsId(List workflowFilters, String[] categories, + EntitySearchFilter[] filters, Collection userGroupCodes) throws ApsSystemException { + try { + return this.getContentSearcherDAO().loadContentsId(workflowFilters, categories, false, filters, userGroupCodes); + } catch (Throwable t) { + _logger.error("Error loading content identifiers filtered for workflow", t); + throw new ApsSystemException("Error loading content identifiers filtered for workflow", t); + } + } + + @Override + public SearcherDaoPaginatedResult getPaginatedWorkContentsId(List workflowFilters, String[] categories, boolean orClauseCategoryFilter, EntitySearchFilter[] filters, Collection userGroupCodes) throws ApsSystemException { + SearcherDaoPaginatedResult pagedResult = null; + try { + int count = this.getContentSearcherDAO().countContents(workflowFilters, categories, orClauseCategoryFilter, filters, userGroupCodes); + List contentsId = this.getContentSearcherDAO().loadContentsId(workflowFilters, categories, orClauseCategoryFilter, filters, userGroupCodes); + pagedResult = new SearcherDaoPaginatedResult<>(count, contentsId); + } catch (Throwable t) { + _logger.error("Error searching paginated contents id", t); + throw new ApsSystemException("Error searching paginated contents id", t); + } + return pagedResult; + } + + protected IContentSearcherDAO getContentSearcherDAO() { + return contentSearcherDAO; + } + public void setContentSearcherDAO(IContentSearcherDAO contentSearcherDAO) { + this.contentSearcherDAO = contentSearcherDAO; + } + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/IContentSearcherDAO.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/IContentSearcherDAO.java new file mode 100644 index 0000000000..672af9c1fe --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/IContentSearcherDAO.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.content; + +import java.util.Collection; +import java.util.List; + +import com.agiletec.aps.system.common.entity.model.EntitySearchFilter; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.WorkflowSearchFilter; + +/** + * @author E.Santoboni + */ +public interface IContentSearcherDAO { + + @Deprecated + public List loadContentsId(List workflowFilters, String[] categories, EntitySearchFilter[] filters, Collection userGroupCodes); + + public List loadContentsId(List workflowFilters, String[] categories, boolean orClauseCategoryFilter, EntitySearchFilter[] filters, Collection userGroupCodes); + + public int countContents(List workflowFilters, String[] categories, boolean orClauseCategoryFilter, EntitySearchFilter[] filters, Collection userGroupCodes); + +} diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/IContentSearcherManager.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/IContentSearcherManager.java new file mode 100644 index 0000000000..b20eff3da0 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/IContentSearcherManager.java @@ -0,0 +1,44 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.content; + +import java.util.Collection; +import java.util.List; + +import com.agiletec.aps.system.common.entity.model.EntitySearchFilter; +import com.agiletec.aps.system.common.model.dao.SearcherDaoPaginatedResult; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.WorkflowSearchFilter; + +/** + * @author E.Santoboni + */ +public interface IContentSearcherManager { + + @Deprecated + public List loadContentsId(List workflowFilters, String[] categories, + EntitySearchFilter[] filters, Collection userGroupCodes) throws ApsSystemException; + + public SearcherDaoPaginatedResult getPaginatedWorkContentsId(List workflowFilters, String[] categories, + boolean orClauseCategoryFilter, EntitySearchFilter[] filters, Collection userGroupCodes) throws ApsSystemException; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/helper/ContentAuthorizationHelper.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/helper/ContentAuthorizationHelper.java new file mode 100644 index 0000000000..68e53bada2 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/helper/ContentAuthorizationHelper.java @@ -0,0 +1,105 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.content.helper; + +import org.entando.entando.ent.exception.EntException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.aps.system.services.role.Permission; +import com.agiletec.aps.system.services.user.UserDetails; +import com.agiletec.plugins.jacms.aps.system.services.content.helper.PublicContentAuthorizationInfo; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.IContentWorkflowManager; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Step; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Workflow; +import org.apache.commons.lang3.StringUtils; + +/** + * Return informations of content authorization + * + * @author E.Santoboni + */ +public class ContentAuthorizationHelper extends com.agiletec.plugins.jacms.aps.system.services.content.helper.ContentAuthorizationHelper { + + private static final Logger _logger = LoggerFactory.getLogger(ContentAuthorizationHelper.class); + + @Override + public boolean isAuthToEdit(UserDetails user, Content content) throws EntException { + boolean isAllowed = false; + try { + boolean firstCheck = (null != content.getMainGroup()) ? super.isAuthToEdit(user, content) : true; + if (firstCheck) { + if (this.getAuthorizationManager().isAuthOnPermission(user, Permission.SUPERUSER)) { + return true; + } + String typeCode = content.getTypeCode(); + Workflow workflow = this.getContentWorkflowManager().getWorkflow(typeCode); + String requiredRole = workflow.getRole(); + if (!StringUtils.isEmpty(requiredRole) && !this.getAuthorizationManager().isAuthOnRole(user, requiredRole)) { + return false; + } + String status = content.getStatus(); + if (!Content.STATUS_NEW.equals(status) && !Content.STATUS_DRAFT.equals(status)) { + if (Content.STATUS_READY.equals(status) || Content.STATUS_PUBLIC.equals(status)) { + isAllowed = this.getAuthorizationManager().isAuthOnPermission(user, Permission.CONTENT_SUPERVISOR); + } else { + Step step = workflow.getStep(status); + if (step != null) { + isAllowed = this.getAuthorizationManager().isAuthOnRole(user, step.getRole()); + } + } + } else { + isAllowed = true; + } + } + } catch (Throwable t) { + _logger.error("Error verifing content authority by user {}", user, t); + throw new EntException("Error verifing content authority by user " + user, t); + } + return isAllowed; + } + + @Override + public boolean isAuthToEdit(UserDetails user, PublicContentAuthorizationInfo info) throws EntException { + Content content = this.getContentManager().loadContent(info.getContentId(), true); + return super.isAuthToEdit(user, content); + } + + @Override + public boolean isAuthToEdit(UserDetails user, String contentId, boolean publicVersion) throws EntException { + Content content = this.getContentManager().loadContent(contentId, publicVersion); + return super.isAuthToEdit(user, content); + } + + protected IContentWorkflowManager getContentWorkflowManager() { + return _contentWorkflowManager; + } + + public void setContentWorkflowManager(IContentWorkflowManager contentWorkflowManager) { + this._contentWorkflowManager = contentWorkflowManager; + } + + private IContentWorkflowManager _contentWorkflowManager; + +} diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/IWorkflowNotifierDAO.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/IWorkflowNotifierDAO.java new file mode 100644 index 0000000000..39a1fa25ac --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/IWorkflowNotifierDAO.java @@ -0,0 +1,41 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier; + +import java.util.List; +import java.util.Map; + +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.ContentStatusChangedEventInfo; + +/** + * @author E.Santoboni + */ +public interface IWorkflowNotifierDAO { + + public void saveContentEvent(ContentStatusChangedEventInfo contentEvent) throws ApsSystemException; + + public Map> getEventsToNotify() throws ApsSystemException; + + public void signNotifiedEvents(List notifiedEvents) throws ApsSystemException; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/IWorkflowNotifierManager.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/IWorkflowNotifierManager.java new file mode 100644 index 0000000000..2978caef34 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/IWorkflowNotifierManager.java @@ -0,0 +1,38 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier; + +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.NotifierConfig; + +/** + * @author E.Santoboni + */ +public interface IWorkflowNotifierManager { + + public NotifierConfig getNotifierConfig() throws ApsSystemException; + + public void saveNotifierConfig(NotifierConfig notifierConfig) throws ApsSystemException; + + public void sendMails() throws ApsSystemException; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/WorkflowNotifierDAO.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/WorkflowNotifierDAO.java new file mode 100644 index 0000000000..78c5d85440 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/WorkflowNotifierDAO.java @@ -0,0 +1,170 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.agiletec.aps.system.common.AbstractDAO; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.ContentStatusChangedEventInfo; + +/** + * @author E.Santoboni + */ +public class WorkflowNotifierDAO extends AbstractDAO implements IWorkflowNotifierDAO { + + private static final Logger _logger = LoggerFactory.getLogger(WorkflowNotifierDAO.class); + + private static final String SAVE_EVENT = + "INSERT INTO jpcontentworkflow_events " + + "(id, eventdate, contentid, contenttype, descr, maingroup, status, notified) " + + "VALUES ( ? , ? , ? , ? , ? , ? , ? , 0 ) "; + + private static final String LOAD_ALL_EVENTS_TO_BE_NOTIFIED = + "SELECT id, eventdate, contentid, contenttype, descr, maingroup, status " + + "FROM jpcontentworkflow_events WHERE notified = 0 ORDER BY contenttype, status "; + + private static final String UPDATE_EVENT = + "UPDATE jpcontentworkflow_events SET notified = 1 WHERE id = ? "; + + private static final String GET_LAST_ID = + "SELECT MAX(id) FROM jpcontentworkflow_events "; + + @Override + public void saveContentEvent(ContentStatusChangedEventInfo contentEvent) throws ApsSystemException { + Connection conn = null; + PreparedStatement stat = null; + try { + conn = this.getConnection(); + conn.setAutoCommit(false); + stat = conn.prepareStatement(SAVE_EVENT); + contentEvent.setId(this.newId(conn)); + stat.setInt(1, contentEvent.getId()); + stat.setTimestamp(2, new Timestamp(contentEvent.getDate().getTime())); + stat.setString(3, contentEvent.getContentId()); + stat.setString(4, contentEvent.getContentTypeCode()); + stat.setString(5, contentEvent.getContentDescr()); + stat.setString(6, contentEvent.getMainGroup()); + stat.setString(7, contentEvent.getStatus()); + stat.executeUpdate(); + conn.commit(); + } catch (Throwable t) { + this.executeRollback(conn); + _logger.error("Error saving content change event for content {}", contentEvent.getContentId(), t); + throw new RuntimeException("Error saving content change event", t); + } finally { + this.closeDaoResources(null, stat, conn); + } + } + + @Override + public Map> getEventsToNotify() throws ApsSystemException { + Map> eventsToNotify = new HashMap<>(); + Connection conn = null; + Statement stat = null; + ResultSet res = null; + try { + conn = this.getConnection(); + stat = conn.createStatement(); + res = stat.executeQuery(LOAD_ALL_EVENTS_TO_BE_NOTIFIED); + while (res.next()) { + ContentStatusChangedEventInfo event = new ContentStatusChangedEventInfo(); + event.setId(res.getInt(1)); + event.setDate(res.getTimestamp(2)); + event.setContentId(res.getString(3)); + String contentType = res.getString(4); + event.setContentTypeCode(contentType); + event.setContentDescr(res.getString(5)); + event.setMainGroup(res.getString(6)); + event.setStatus(res.getString(7)); + List contentTypeEvents = (List) eventsToNotify.get(contentType); + if (contentTypeEvents == null) { + contentTypeEvents = new ArrayList<>(); + eventsToNotify.put(contentType, contentTypeEvents); + } + contentTypeEvents.add(event); + } + } catch (Throwable t) { + _logger.error("Error loading contents to notify", t); + throw new RuntimeException("Error loading contents to notify", t); + } finally { + this.closeDaoResources(res, stat, conn); + } + return eventsToNotify; + } + + @Override + public void signNotifiedEvents(List notifiedEvents) throws ApsSystemException { + Connection conn = null; + PreparedStatement stat = null; + try { + conn = this.getConnection(); + conn.setAutoCommit(false); + stat = conn.prepareStatement(UPDATE_EVENT); + for (ContentStatusChangedEventInfo event : notifiedEvents) { + stat.setInt(1, event.getId()); + stat.addBatch(); + stat.clearParameters(); + } + stat.executeBatch(); + conn.commit(); + } catch (Throwable t) { + this.executeRollback(conn); + _logger.error("Error in update events", t); + throw new RuntimeException("Error in update events", t); + } finally { + this.closeDaoResources(null, stat, conn); + } + } + + private int newId(Connection conn) throws ApsSystemException { + int id = 0; + Statement stat = null; + ResultSet res = null; + try { + stat = conn.createStatement(); + res = stat.executeQuery(GET_LAST_ID); + if (res.next()) { + id = res.getInt(1); + } + id = id + 1; // N.B.: funziona anche per il primo record + } catch (Throwable t) { + _logger.error("Error loading last id", t); + throw new RuntimeException("Error loading last id", t); + } finally { + this.closeDaoResources(res, stat); + } + return id; + } + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/WorkflowNotifierManager.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/WorkflowNotifierManager.java new file mode 100644 index 0000000000..bb6e30234c --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/WorkflowNotifierManager.java @@ -0,0 +1,537 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier; + +import com.agiletec.aps.system.SystemConstants; +import com.agiletec.aps.system.common.AbstractService; +import com.agiletec.aps.system.common.entity.model.attribute.ITextAttribute; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.aps.system.services.authorization.Authorization; +import com.agiletec.aps.system.services.authorization.IApsAuthority; +import com.agiletec.aps.system.services.authorization.IAuthorizationManager; +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.aps.system.services.role.IRoleManager; +import com.agiletec.aps.system.services.role.Permission; +import com.agiletec.aps.system.services.role.Role; +import com.agiletec.aps.system.services.user.IAuthenticationProviderManager; +import com.agiletec.aps.system.services.user.IUserManager; +import com.agiletec.aps.util.DateConverter; +import com.agiletec.plugins.jacms.aps.system.services.content.IContentManager; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.ContentStatusChangedEventInfo; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.NotifierConfig; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.parse.WorkflowNotifierDOM; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.scheduler.MailSenderTask; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.scheduler.Scheduler; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.scheduler.Task; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.IContentWorkflowManager; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Step; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Workflow; +import com.agiletec.plugins.jpmail.aps.services.mail.IMailManager; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.apache.commons.lang3.StringUtils; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.entando.entando.aps.system.services.userprofile.IUserProfileManager; +import org.entando.entando.aps.system.services.userprofile.model.IUserProfile; +import org.entando.entando.ent.exception.EntException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Aspect +public class WorkflowNotifierManager extends AbstractService implements IWorkflowNotifierManager { + + private static final Logger _logger = LoggerFactory.getLogger(WorkflowNotifierManager.class); + + @Override + public void init() throws Exception { + this.loadConfigs(); + this.openScheduler(); + _logger.debug("{}: ready", this.getClass().getName()); + } + + @Override + public void release() { + this.closeScheduler(); + } + + @Override + public void destroy() { + this.release(); + super.destroy(); + } + + protected void loadConfigs() throws ApsSystemException { + try { + ConfigInterface configManager = this.getConfigManager(); + String xml = configManager.getConfigItem(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM); + if (xml == null) { + throw new ApsSystemException("Configuration item not present: " + JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM); + } + WorkflowNotifierDOM configDOM = new WorkflowNotifierDOM(); + this.setNotifierConfig(configDOM.extractConfig(xml)); + } catch (Throwable t) { + _logger.error("Error loading configs", t); + throw new ApsSystemException("Error loading configs", t); + } + } + + @Around("execution(* com.agiletec.plugins.jacms.aps.system.services.content.IContentManager.saveContent(..)) && args(content,..)") + public void listenContentSaving(ProceedingJoinPoint pjp, Object content) { + try { + boolean notify = true; + Content currentContent = (Content) content; + String contentId = currentContent.getId(); + if (null != contentId) { + Content previousContent = this.getContentManager().loadContent(contentId, false); + if (previousContent.getStatus().equals(currentContent.getStatus())) { + notify = false; + } + } + pjp.proceed(); + if (notify) { + this.saveContentStatusChanged(currentContent); + } + } catch (Throwable t) { + _logger.error("Error notifying content status change", t); + } + } + + @Override + public NotifierConfig getNotifierConfig() { + return _notifierConfig.clone(); + } + + protected NotifierConfig getWorkflowNotifierConfig() { + return _notifierConfig; + } + + protected void setNotifierConfig(NotifierConfig notifierConfig) { + this._notifierConfig = notifierConfig; + } + + @Override + public void saveNotifierConfig(NotifierConfig notifierConfig) throws ApsSystemException { + try { + WorkflowNotifierDOM configDOM = new WorkflowNotifierDOM(); + String xml = configDOM.createConfigXml(notifierConfig); + this.getConfigManager().updateConfigItem(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM, xml); + this.setNotifierConfig(notifierConfig); + this.closeScheduler(); + this.openScheduler(); + } catch (Throwable t) { + _logger.error("Error saving configs", t); + throw new ApsSystemException("Error saving configs", t); + } + } + + protected void saveContentStatusChanged(Content content) { + if (this.getWorkflowNotifierConfig().isActive()) { + try { + ContentStatusChangedEventInfo statusChangedInfo = new ContentStatusChangedEventInfo(); + statusChangedInfo.setContentId(content.getId()); + statusChangedInfo.setContentTypeCode(content.getTypeCode()); + statusChangedInfo.setContentDescr(content.getDescr()); + statusChangedInfo.setMainGroup(content.getMainGroup()); + statusChangedInfo.setDate(new Date()); + statusChangedInfo.setStatus(content.getStatus()); + this.getNotifierDAO().saveContentEvent(statusChangedInfo); + } catch (Throwable t) { + _logger.error("Error saving content status changed event for content {}", content.getId(), t); + } + } + } + + protected void openScheduler() { + this.closeScheduler(); + NotifierConfig notifierConfig = this.getWorkflowNotifierConfig(); + if (notifierConfig.isActive()) { + long milliSecondsDelay = notifierConfig.getHoursDelay() * 3600000l; // x minuti secondi millisecondi + Date startTime = notifierConfig.getStartScheduler(); + startTime = this.calculateStartTime(startTime, milliSecondsDelay); + Task task = new MailSenderTask(this); + this._mailSenderScheduler = new Scheduler(task, startTime, milliSecondsDelay); + } + } + + private Date calculateStartTime(Date startTime, long delay) { + Date current = new Date(); + long waitTime = current.getTime() - startTime.getTime(); + if (waitTime > 0) { + startTime = new Date((current.getTime() + delay) - (waitTime % delay)); + } + return startTime; + } + + protected void closeScheduler() { + if (this._mailSenderScheduler != null) { + this._mailSenderScheduler.cancel(); + } + this._mailSenderScheduler = null; + } + + @Override + public void sendMails() throws ApsSystemException { + try { + Map> statusChangedInfos = this.getNotifierDAO().getEventsToNotify(); + _logger.trace("Found {} events to notify", statusChangedInfos.size()); + if (statusChangedInfos.size() > 0) { + Map> contentsForUsers = this.prepareContentsForUsers(statusChangedInfos); + Iterator iter = contentsForUsers.keySet().iterator(); + while (iter.hasNext()) { + String username = iter.next(); + List contentInfos = contentsForUsers.get(username); + this.sendMail(username, contentInfos); + } + List notifiedContents = new ArrayList(); + for (List contentsForType : statusChangedInfos.values()) { + notifiedContents.addAll(contentsForType); + } + _logger.trace("Notified {} events", notifiedContents.size()); + this.getNotifierDAO().signNotifiedEvents(notifiedContents); + } + } catch (Throwable t) { + _logger.error("error sending emails ", t); + throw new ApsSystemException("error sending emails", t); + } + } + + protected void sendMail(String username, List contentInfos) { + try { + NotifierConfig notifierConfig = this.getWorkflowNotifierConfig(); + String mailAddress = this.getMailAddress(username); + if (null == mailAddress) { + return; + } + String[] mailAddresses = {mailAddress}; + Map params = this.prepareParams(username); + String subject = this.replaceParams(notifierConfig.getSubject(), params); + String text = this.prepareMailText(params, contentInfos); + String senderCode = notifierConfig.getSenderCode(); + String contentType = (notifierConfig.isHtml()) ? IMailManager.CONTENTTYPE_TEXT_HTML : IMailManager.CONTENTTYPE_TEXT_PLAIN; + this.getMailManager().sendMail(text, subject, mailAddresses, null, null, senderCode, contentType); + } catch (Throwable t) { + _logger.error("Error sending mail to user {}", username, t); + } + } + + protected String getMailAddress(String username) throws Throwable { + String email = null; + IUserProfileManager profileManager = (IUserProfileManager) super.getBeanFactory().getBean(SystemConstants.USER_PROFILE_MANAGER); + IUserProfile profile = profileManager.getProfile(username); + if (null != profile) { + ITextAttribute mailAttribute = (ITextAttribute) profile.getAttributeByRole(SystemConstants.USER_PROFILE_ATTRIBUTE_ROLE_MAIL); + if (null != mailAttribute && mailAttribute.getText().trim().length() > 0) { + email = mailAttribute.getText(); + } + } + return email; + } + + protected Map prepareParams(String username) { + Map params = new HashMap(); + params.put("user", username); + return params; + } + + protected void addContentParams(Map params, ContentStatusChangedEventInfo contentInfo) { + params.put("type", contentInfo.getContentTypeCode()); + params.put("contentId", contentInfo.getContentId()); + params.put("descr", contentInfo.getContentDescr()); + params.put("group", contentInfo.getMainGroup()); + params.put("status", contentInfo.getStatus()); + params.put("data", DateConverter.getFormattedDate(contentInfo.getDate(), "dd MMMM yyyy")); + } + + protected String prepareMailText(Map params, List contentInfos) { + NotifierConfig notifierConfig = this.getWorkflowNotifierConfig(); + String header = this.replaceParams(notifierConfig.getHeader(), params); + String footer = this.replaceParams(notifierConfig.getFooter(), params); + String body = notifierConfig.getTemplate(); + StringBuilder text = new StringBuilder(header); + for (ContentStatusChangedEventInfo contentInfo : contentInfos) { + this.addContentParams(params, contentInfo); + text.append(this.replaceParams(body, params)); + } + text.append(footer); + return text.toString(); + } + + protected String replaceParams(String defaultText, Map params) { + String body = defaultText; + Iterator> it = params.entrySet().iterator(); + while (it.hasNext()) { + Entry pairs = it.next(); + String field = "\\{" + pairs.getKey() + "\\}"; + body = body.replaceAll(field, pairs.getValue()); + } + return body; + } + + protected Map> prepareContentsForUsers( + Map> statusChangedInfos) throws EntException{ + Map> contentsForUsers = new HashMap>(); + List editors = new ArrayList(); + List supervisors = new ArrayList(); + this.findContentOperators(editors, supervisors); + if (null != statusChangedInfos) { + Iterator iter = statusChangedInfos.keySet().iterator(); + while (iter.hasNext()) { + String typeCode = iter.next(); + List infosForContentType = statusChangedInfos.get(typeCode); + this.prepareUsersForContentType(contentsForUsers, typeCode, infosForContentType, editors, supervisors); + } + } + return contentsForUsers; + } + + protected void findContentOperators(List editors, List supervisors) throws EntException { + List rolesWithSupervisor = this.getRoleManager().getRolesWithPermission(Permission.CONTENT_SUPERVISOR); + List roleNamesWithSupervisor = this.getRolesNames(rolesWithSupervisor); + List rolesWithEditors = this.getRoleManager().getRolesWithPermission(Permission.CONTENT_EDITOR); + List roleNamesWithEditor = this.getRolesNames(rolesWithEditors); + IUserProfileManager profileManager = (IUserProfileManager) super.getBeanFactory().getBean(SystemConstants.USER_PROFILE_MANAGER); + List usernames = profileManager.searchId(null); + for (int i = 0; i < usernames.size(); i++) { + String extractedUsername = usernames.get(i); + List authorizations = this.getAuthorizationManager().getUserAuthorizations(extractedUsername); + if (null == authorizations) { + continue; + } + for (int j = 0; j < authorizations.size(); j++) { + Authorization authorization = authorizations.get(j); + Role role = (null != authorization) ? authorization.getRole() : null; + String roleName = (null != role) ? role.getName() : null; + if (null == roleName) { + continue; + } + if (roleNamesWithSupervisor.contains(roleName)) { + supervisors.add(extractedUsername); + } + if (roleNamesWithEditor.contains(roleName)) { + editors.add(extractedUsername); + } + } + } + } + + private List getRolesNames(List roles) { + List names = new ArrayList(); + if (null == roles) { + return names; + } + for (int i = 0; i < roles.size(); i++) { + IApsAuthority role = roles.get(i); + if (null == role) { + continue; + } + names.add(role.getAuthority()); + } + return names; + } + + protected void prepareUsersForContentType(Map> contentsForUsers, + String typeCode, List infosForContentType, List editors, List supervisors) throws EntException { + Workflow workflow = this.getWorkflowManager().getWorkflow(typeCode); + String contentTypeRole = workflow.getRole(); + if (contentTypeRole == null || contentTypeRole.length() == 0) { + editors = this.filterUsersForRole(contentTypeRole, editors); + supervisors = this.filterUsersForRole(contentTypeRole, supervisors); + } + List usersForStep = null; + String previousStepRole = null; + for (ContentStatusChangedEventInfo contentInfo : infosForContentType) { + String currentStatus = contentInfo.getStatus(); + Step step = workflow.getStep(currentStatus); + String currentStepRole = (step != null && !StringUtils.isEmpty(step.getRole())) ? step.getRole() : null; + boolean needsSupervisor = Content.STATUS_READY.equals(currentStatus); + if (previousStepRole == null || !previousStepRole.equals(currentStepRole)) { + previousStepRole = currentStepRole; + if (needsSupervisor) { + usersForStep = supervisors; + } else { + usersForStep = this.filterUsersForRole(currentStepRole, editors); + } + } + String mainGroup = contentInfo.getMainGroup(); + List allowedUsers = this.filterUsersForGroup(mainGroup, usersForStep); + this.addContentForUsers(contentInfo, allowedUsers, contentsForUsers); + } + } + + protected List filterUsersForRole(String roleName, List users) throws EntException { + List usersForContentType = null; + try { + if (users.isEmpty() || roleName == null || roleName.length() == 0) { + usersForContentType = users; + } else { + usersForContentType = new ArrayList(); + List usersWithAuth = this.getAuthorizationManager().getUsersByRole(roleName, false); + for (int i = 0; i < users.size(); i++) { + String username = users.get(i); + if (null == username || null == usersWithAuth) { + continue; + } + if (usersWithAuth.contains(username)) { + usersForContentType.add(username); + } + } + } + } catch (Throwable t) { + _logger.error("error extracting users by role {}", roleName, t); + throw new EntException("error extracting users by role", t); + } + return usersForContentType; + } + + protected List filterUsersForGroup(String groupName, List usernames) throws EntException { + List usersForContentType = null; + if (usernames.isEmpty() || groupName == null || groupName.length() == 0) { + usersForContentType = usernames; + } else { + usersForContentType = new ArrayList(); + List usersWithAuth = this.getAuthorizationManager().getUsersByGroup(groupName, false); + for (int i = 0; i < usernames.size(); i++) { + String username = usernames.get(i); + if (null == username || null == usersWithAuth) { + continue; + } + if (usersWithAuth.contains(username)) { + usersForContentType.add(username); + } + } + } + return usersForContentType; + } + + protected void addContentForUsers(ContentStatusChangedEventInfo contentInfo, List allowedUsers, + Map> contentsForUsers) { + if (null == contentsForUsers || null == allowedUsers) { + return; + } + for (int i = 0; i < allowedUsers.size(); i++) { + String username = allowedUsers.get(i); + List infos = contentsForUsers.get(username); + if (infos == null) { + infos = new ArrayList(); + contentsForUsers.put(username, infos); + } + infos.add(contentInfo); + } + } + + protected ConfigInterface getConfigManager() { + return _configManager; + } + + public void setConfigManager(ConfigInterface configManager) { + this._configManager = configManager; + } + + protected IUserManager getUserManager() { + return _userManager; + } + + public void setUserManager(IUserManager userManager) { + this._userManager = userManager; + } + + protected IAuthenticationProviderManager getAuthProvider() { + return _authProvider; + } + + public void setAuthProvider(IAuthenticationProviderManager authProvider) { + this._authProvider = authProvider; + } + + protected IAuthorizationManager getAuthorizationManager() { + return _authorizationManager; + } + + public void setAuthorizationManager(IAuthorizationManager authorizationManager) { + this._authorizationManager = authorizationManager; + } + + protected IRoleManager getRoleManager() { + return _roleManager; + } + + public void setRoleManager(IRoleManager roleManager) { + this._roleManager = roleManager; + } + + protected IContentWorkflowManager getWorkflowManager() { + return _workflowManager; + } + + public void setWorkflowManager(IContentWorkflowManager workflowManager) { + this._workflowManager = workflowManager; + } + + protected IMailManager getMailManager() { + return _mailManager; + } + + public void setMailManager(IMailManager mailManager) { + this._mailManager = mailManager; + } + + protected IContentManager getContentManager() { + return _contentManager; + } + + public void setContentManager(IContentManager contentManager) { + this._contentManager = contentManager; + } + + protected IWorkflowNotifierDAO getNotifierDAO() { + return _notifierDAO; + } + + public void setNotifierDAO(IWorkflowNotifierDAO notifierDAO) { + this._notifierDAO = notifierDAO; + } + + private NotifierConfig _notifierConfig; + protected Scheduler _mailSenderScheduler; + + private ConfigInterface _configManager; + private IUserManager _userManager; + private IAuthenticationProviderManager _authProvider; + private IAuthorizationManager _authorizationManager; + private IRoleManager _roleManager; + private IContentWorkflowManager _workflowManager; + private IMailManager _mailManager; + private IContentManager _contentManager; + private IWorkflowNotifierDAO _notifierDAO; + +} diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/model/ContentStatusChangedEventInfo.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/model/ContentStatusChangedEventInfo.java new file mode 100644 index 0000000000..dd00f99c66 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/model/ContentStatusChangedEventInfo.java @@ -0,0 +1,88 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model; + +import java.util.Date; + +/** + * @author E.Santoboni + */ +public class ContentStatusChangedEventInfo { + + public int getId() { + return _id; + } + public void setId(int id) { + this._id = id; + } + + public String getContentId() { + return _contentId; + } + public void setContentId(String contentId) { + this._contentId = contentId; + } + + public String getContentTypeCode() { + return _contentTypeCode; + } + public void setContentTypeCode(String contentTypeCode) { + this._contentTypeCode = contentTypeCode; + } + + public String getContentDescr() { + return _contentDescr; + } + public void setContentDescr(String contentDescr) { + this._contentDescr = contentDescr; + } + + public Date getDate() { + return _date; + } + public void setDate(Date date) { + this._date = date; + } + + public String getMainGroup() { + return _mainGroup; + } + public void setMainGroup(String mainGroup) { + this._mainGroup = mainGroup; + } + + public String getStatus() { + return _status; + } + public void setStatus(String status) { + this._status = status; + } + + private int _id; + private String _contentId; + private String _contentTypeCode; + private String _contentDescr; + private Date _date; + private String _mainGroup; + private String _status; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/model/NotifierConfig.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/model/NotifierConfig.java new file mode 100644 index 0000000000..3b3d71c75c --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/model/NotifierConfig.java @@ -0,0 +1,129 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model; + +import java.util.Date; + +/** + * @author E.Santoboni + */ +public class NotifierConfig implements Cloneable { + + @Override + public NotifierConfig clone() { + NotifierConfig config = new NotifierConfig(); + config.setActive(this.isActive()); + config.setStartScheduler(this.getStartScheduler()); + config.setHoursDelay(this.getHoursDelay()); + config.setSenderCode(this.getSenderCode()); + //config.setMailAttrName(this.getMailAttrName()); + config.setHtml(this.isHtml()); + config.setSubject(this.getSubject()); + config.setHeader(this.getHeader()); + config.setTemplate(this.getTemplate()); + config.setFooter(this.getFooter()); + return config; + } + + public boolean isActive() { + return _active; + } + public void setActive(boolean active) { + this._active = active; + } + + public int getHoursDelay() { + return _hoursDelay; + } + public void setHoursDelay(int hoursDelay) { + this._hoursDelay = hoursDelay; + } + + public Date getStartScheduler() { + return _startScheduler; + } + public void setStartScheduler(Date startScheduler) { + this._startScheduler = startScheduler; + } + + public String getSenderCode() { + return _senderCode; + } + public void setSenderCode(String senderCode) { + this._senderCode = senderCode; + } + /* + public String getMailAttrName() { + return _mailAttrName; + } + public void setMailAttrName(String mailAttrName) { + this._mailAttrName = mailAttrName; + } + */ + public boolean isHtml() { + return _html; + } + public void setHtml(boolean html) { + this._html = html; + } + + public String getSubject() { + return _subject; + } + public void setSubject(String subject) { + this._subject = subject; + } + + public String getHeader() { + return _header; + } + public void setHeader(String header) { + this._header = header; + } + + public String getTemplate() { + return _template; + } + public void setTemplate(String template) { + this._template = template; + } + + public String getFooter() { + return _footer; + } + public void setFooter(String footer) { + this._footer = footer; + } + + private boolean _active = false; + private Date _startScheduler = new Date(); + private int _hoursDelay; + + private String _senderCode; + //private String _mailAttrName; + private boolean _html; + private String _subject = ""; + private String _header = ""; + private String _template = ""; + private String _footer = ""; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/parse/WorkflowNotifierDOM.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/parse/WorkflowNotifierDOM.java new file mode 100644 index 0000000000..20f25010ce --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/parse/WorkflowNotifierDOM.java @@ -0,0 +1,182 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.parse; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.aps.util.DateConverter; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.NotifierConfig; +import java.io.StringReader; +import java.util.Date; +import org.jdom2.CDATA; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.input.SAXBuilder; +import org.jdom2.output.XMLOutputter; + +/** + * @author E.Mezzano + */ +public class WorkflowNotifierDOM { + + public NotifierConfig extractConfig(String xml) throws ApsSystemException { + NotifierConfig notifierConfig = new NotifierConfig(); + Element root = this.getRootElement(xml); + Element schedulerElement = root.getChild(SCHEDULER_CHILD); + this.extractSchedulerConfig(notifierConfig, schedulerElement); + Element mailElement = root.getChild(MAIL_CHILD); + this.extractMailConfig(notifierConfig, mailElement); + return notifierConfig; + } + + public String createConfigXml(NotifierConfig notifierConfig) throws ApsSystemException { + Element root = new Element(ROOT); + Element schedulerElement = this.prepareSchedulerElement(notifierConfig); + root.addContent(schedulerElement); + Element mailElement = this.prepareMailElement(notifierConfig); + root.addContent(mailElement); + + XMLOutputter out = new XMLOutputter(); + String xml = out.outputString(new Document(root)); + return xml; + } + + protected void extractSchedulerConfig(NotifierConfig notifierConfig, Element schedulerElement) { + Element activeElem = schedulerElement.getChild(SCHEDULER_ACTIVE_CHILD); + if (activeElem != null) { + notifierConfig.setActive("true".equalsIgnoreCase(activeElem.getAttributeValue(SCHEDULER_VALUE_ATTR))); + } + Element delayElem = schedulerElement.getChild(SCHEDULER_DELAY_CHILD); + int hoursDelay = 1; + if (delayElem != null) { + hoursDelay = Integer.parseInt(delayElem.getAttributeValue(SCHEDULER_VALUE_ATTR)); + } + notifierConfig.setHoursDelay(hoursDelay); + Element startElem = schedulerElement.getChild(SCHEDULER_START_CHILD); + if (startElem != null) { + String value = startElem.getAttributeValue(SCHEDULER_VALUE_ATTR); + Date extractedStart = DateConverter.parseDate(value, DATE_SCHEDULER_CONFIG_PATTERN); + notifierConfig.setStartScheduler(extractedStart); + } + } + + protected void extractMailConfig(NotifierConfig notifierConfig, Element mailElement) { + notifierConfig.setSenderCode(mailElement.getAttributeValue(MAIL_SENDERCODE_ATTR)); + //notifierConfig.setMailAttrName(mailElement.getAttributeValue(MAIL_MAILATTRNAME_ATTR)); + String html = mailElement.getAttributeValue(MAIL_HTML_ATTR); + notifierConfig.setHtml(html!=null && "true".equalsIgnoreCase(html)); + notifierConfig.setSubject(mailElement.getChild(MAIL_SUBJECT_CHILD).getText()); + notifierConfig.setHeader(mailElement.getChild(MAIL_HEADER_CHILD).getText()); + notifierConfig.setTemplate(mailElement.getChild(MAIL_TEMPLATE_CHILD).getText()); + notifierConfig.setFooter(mailElement.getChild(MAIL_FOOTER_CHILD).getText()); + } + + protected Element prepareSchedulerElement(NotifierConfig notifierConfig) { + Element schedulerElement = new Element(SCHEDULER_CHILD); + + Element activeElement = new Element(SCHEDULER_ACTIVE_CHILD); + activeElement.setAttribute(SCHEDULER_VALUE_ATTR, String.valueOf(notifierConfig.isActive())); + schedulerElement.addContent(activeElement); + + Element delayElement = new Element(SCHEDULER_DELAY_CHILD); + delayElement.setAttribute(SCHEDULER_VALUE_ATTR, String.valueOf(notifierConfig.getHoursDelay())); + schedulerElement.addContent(delayElement); + + Element startElement = new Element(SCHEDULER_START_CHILD); + startElement.setAttribute(SCHEDULER_VALUE_ATTR, DateConverter.getFormattedDate( + notifierConfig.getStartScheduler(), DATE_SCHEDULER_CONFIG_PATTERN)); + schedulerElement.addContent(startElement); + + return schedulerElement; + } + + protected Element prepareMailElement(NotifierConfig notifierConfig) { + Element mailElement = new Element(MAIL_CHILD); + mailElement.setAttribute(MAIL_SENDERCODE_ATTR, notifierConfig.getSenderCode()); + //mailElement.setAttribute(MAIL_MAILATTRNAME_ATTR, notifierConfig.getMailAttrName()); + mailElement.setAttribute(MAIL_HTML_ATTR, String.valueOf(notifierConfig.isHtml())); + + Element subjectElement = new Element(MAIL_SUBJECT_CHILD); + subjectElement.addContent(new CDATA(notifierConfig.getSubject())); + mailElement.addContent(subjectElement); + + Element headerElement = new Element(MAIL_HEADER_CHILD); + headerElement.addContent(new CDATA(notifierConfig.getHeader())); + mailElement.addContent(headerElement); + + Element templateElement = new Element(MAIL_TEMPLATE_CHILD); + templateElement.addContent(new CDATA(notifierConfig.getTemplate())); + mailElement.addContent(templateElement); + + Element footerElement = new Element(MAIL_FOOTER_CHILD); + footerElement.addContent(new CDATA(notifierConfig.getFooter())); + mailElement.addContent(footerElement); + + return mailElement; + } + + protected Element getRootElement(String xmlText) throws ApsSystemException { + SAXBuilder builder = new SAXBuilder(); + builder.setValidation(false); + StringReader reader = new StringReader(xmlText); + Element root = null; + try { + Document doc = builder.build(reader); + root = doc.getRootElement(); + } catch (Throwable t) { + ApsSystemUtils.getLogger().error("Errore nel parsing: " + t.getMessage()); + throw new ApsSystemException("Errore nel parsing della configurazione Dimensioni di resize", t); + } + return root; + } + + protected Document decodeDOM(String xmlText) throws ApsSystemException { + SAXBuilder builder = new SAXBuilder(); + builder.setValidation(false); + StringReader reader = new StringReader(xmlText); + try { + return builder.build(reader); + } catch (Throwable t) { + throw new ApsSystemException("Errore nel parsing dell'xml", t); + } + } + + private static final String ROOT = "notifierConfig"; + + private static final String SCHEDULER_CHILD = "scheduler"; + private static final String SCHEDULER_ACTIVE_CHILD = "active"; + private static final String SCHEDULER_DELAY_CHILD = "delay"; + private static final String SCHEDULER_START_CHILD = "start"; + private static final String SCHEDULER_VALUE_ATTR = "value"; + + private static final String MAIL_CHILD = "mail"; + private static final String MAIL_SENDERCODE_ATTR = "senderCode"; + //private static final String MAIL_MAILATTRNAME_ATTR = "mailAttributeName"; + private static final String MAIL_HTML_ATTR = "html"; + private static final String MAIL_SUBJECT_CHILD = "subject"; + private static final String MAIL_HEADER_CHILD = "header"; + private static final String MAIL_TEMPLATE_CHILD = "template"; + private static final String MAIL_FOOTER_CHILD = "footer"; + + private final String DATE_SCHEDULER_CONFIG_PATTERN = "dd/MM/yyyy HH:mm"; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/MailSenderTask.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/MailSenderTask.java new file mode 100644 index 0000000000..c80efcdcff --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/MailSenderTask.java @@ -0,0 +1,52 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.scheduler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.IWorkflowNotifierManager; + +/** + * @author E.Santoboni + */ +public class MailSenderTask extends Task { + + private static final Logger _logger = LoggerFactory.getLogger(MailSenderTask.class); + + public MailSenderTask(IWorkflowNotifierManager notifierManager) { + this._notifierManager = notifierManager; + } + + @Override + public void execute() { + try { + this._notifierManager.sendMails(); + } catch (ApsSystemException e) { + _logger.error("error in execute", e); + } + } + + private IWorkflowNotifierManager _notifierManager; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/Scheduler.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/Scheduler.java new file mode 100644 index 0000000000..f03285ef6c --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/Scheduler.java @@ -0,0 +1,66 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.scheduler; + +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; +import java.util.logging.Level; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.util.DateConverter; + +/** + * Classe Scheduler + * @author M.Casari - E.Santoboni + */ +public class Scheduler extends TimerTask { + + /** + * Costruttore dello scheduler + * @param task Task da eseguire. + * @param start Data di partenza dello scheduler + * @param delay Intervallo di schedulazione in millisecondi + */ + public Scheduler(Task task, Date start, long delay) { + this._timer = new Timer(); + this._task = task; + this._timer.schedule(this, start, delay); + ApsSystemUtils.getLogger().trace("jpcontentworkflow: Scheduler - StartTime: " + DateConverter.getFormattedDate(start, "dd/MM/yyyy HH:mm:ss") + " - Delay: " + delay); + } + + @Override + public boolean cancel() { + this._task = null; + this._timer.cancel(); + this._timer.purge(); + return super.cancel(); + } + + @Override + public void run() { + if (null != _task) _task.execute(); + } + + private Task _task; + private Timer _timer; +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/Task.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/Task.java new file mode 100644 index 0000000000..9fe2b343e2 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/scheduler/Task.java @@ -0,0 +1,37 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.scheduler; + +/** + * Classe astratta base per l'implementazione del task + * da associare allo scheduler. + * @author M.Casari + */ +public abstract class Task { + + public Task() {} + + public Task(Object taskInput){} + + public abstract void execute(); + +} diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/ContentWorkflowDAO.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/ContentWorkflowDAO.java new file mode 100644 index 0000000000..ee20b672f2 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/ContentWorkflowDAO.java @@ -0,0 +1,68 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.agiletec.aps.system.common.AbstractDAO; + +/** + * @author E.Santoboni + */ +public class ContentWorkflowDAO extends AbstractDAO implements IContentWorkflowDAO { + + private static final Logger _logger = LoggerFactory.getLogger(ContentWorkflowDAO.class); + + @Override + public List searchUsedSteps(String typeCode) { + List steps = new ArrayList(); + Connection conn = null; + PreparedStatement stat = null; + ResultSet res = null; + try { + conn = this.getConnection(); + stat = conn.prepareStatement(SEARCH_STEPS); + stat.setString(1, typeCode); + res = stat.executeQuery(); + while (res.next()) { + steps.add(res.getString(1)); + } + } catch (Throwable t) { + _logger.error("Error searching steps for type {}", typeCode, t); + throw new RuntimeException("Error searching steps by type ", t); + } finally { + closeDaoResources(res, stat, conn); + } + return steps; + } + + private final String SEARCH_STEPS = + "SELECT status FROM contents WHERE contenttype = ? GROUP BY status "; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/ContentWorkflowManager.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/ContentWorkflowManager.java new file mode 100644 index 0000000000..e383db6c25 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/ContentWorkflowManager.java @@ -0,0 +1,241 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.system.common.AbstractService; +import com.agiletec.aps.system.common.entity.model.SmallEntityType; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.aps.system.services.authorization.IAuthorizationManager; +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.aps.system.services.role.Permission; +import com.agiletec.aps.system.services.user.UserDetails; +import com.agiletec.plugins.jacms.aps.system.services.content.IContentManager; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jacms.aps.system.services.content.model.SmallContentType; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Step; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Workflow; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.WorkflowSearchFilter; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.parse.ContentWorkflowDOM; + +/** + * @author E.Santoboni + */ +public class ContentWorkflowManager extends AbstractService implements IContentWorkflowManager { + + private static final Logger _logger = LoggerFactory.getLogger(ContentWorkflowManager.class); + + @Override + public void init() throws Exception { + this.loadConfig(); + ApsSystemUtils.getLogger().debug(this.getName() + ": initialized"); + } + + protected void loadConfig() { + try { + ConfigInterface configManager = this.getConfigManager(); + String xml = configManager.getConfigItem(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_CONFIG_ITEM); + if (xml == null) { + throw new ApsSystemException("Configuration item not present: " + JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_CONFIG_ITEM); + } + ContentWorkflowDOM configDOM = new ContentWorkflowDOM(); + this.setWorkflowConfig(configDOM.extractConfig(xml)); + } catch (Exception e) { + _logger.error("error loading configs", e); + } + } + + @Override + public String getRole(String typeCode) { + Workflow workflow = this.getWorkflow(typeCode); + return workflow.getRole(); + } + + @Override + public void updateRole(String typeCode, String role) throws ApsSystemException { + Workflow workflow = this.getWorkflow(typeCode); + workflow.setRole(role); + this.updateWorkflow(workflow); + } + + @Override + public List getSteps(String typeCode) { + Workflow workflow = this.getWorkflow(typeCode); + return workflow.getSteps(); + } + + @Override + public void updateSteps(String typeCode, List steps) throws ApsSystemException { + Workflow workflow = this.getWorkflow(typeCode); + workflow.setSteps(steps); + this.updateWorkflow(workflow); + } + + @Override + public Workflow getWorkflow(String typeCode) { + Workflow workflow = this.getWorkflowConfig().get(typeCode); + if (workflow == null) { + workflow = new Workflow(); + workflow.setTypeCode(typeCode); + } + return workflow; + } + + protected void updateWorkflow(Workflow workflow) throws ApsSystemException { + Map config = this.getWorkflowConfig(); + config.put(workflow.getTypeCode(), workflow); + try { + String xml = new ContentWorkflowDOM().createConfigXml(config); + this.getConfigManager().updateConfigItem(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_CONFIG_ITEM, xml); + this.setWorkflowConfig(config); + } catch (Exception e) { + this.loadConfig(); + _logger.error("Error updating workflow for content {}", workflow.getTypeCode(), e); + throw new ApsSystemException("Error updating workflow for content " + workflow.getTypeCode(), e); + } + } + + @Override + public List searchUsedSteps(String typeCode) { + return this.getWorkflowDAO().searchUsedSteps(typeCode); + } + + @Override + public List getWorkflowSearchFilters(UserDetails user) throws ApsSystemException { + List filters = new ArrayList(); + try { + List contentTypes = this.getManagingContentTypes(user); + boolean isSupervisor = this.getAuthorizationManager().isAuthOnPermission(user, Permission.CONTENT_SUPERVISOR); + for (int i = 0; i < contentTypes.size(); i++) { + SmallEntityType type = contentTypes.get(i); + Workflow workflow = this.getWorkflow(type.getCode()); + WorkflowSearchFilter filter = new WorkflowSearchFilter(); + filter.setTypeCode(type.getCode()); + List allowedSteps = this.getAllowedStatus(user, isSupervisor, workflow); + filter.setAllowedSteps(allowedSteps); + filters.add(filter); + } + } catch (Throwable t) { + _logger.error("Error extracting workflow search filters by user {}", user, t); + throw new ApsSystemException("Error extracting workflow search filters by user " + user, t); + } + return filters; + } + + protected List getAllowedStatus(UserDetails user, boolean isSupervisor, Workflow workflow) { + List allowedSteps = new ArrayList(); + allowedSteps.add(Content.STATUS_NEW); + allowedSteps.add(Content.STATUS_DRAFT); + Iterator stepsIter = workflow.getSteps().iterator(); + while (stepsIter.hasNext()) { + Step step = stepsIter.next(); + String stepRole = step.getRole(); + if (null == stepRole || stepRole.trim().length() == 0 + || this.getAuthorizationManager().isAuthOnRole(user, step.getRole())) { + allowedSteps.add(step.getCode()); + } + } + if (isSupervisor) { + allowedSteps.add(Content.STATUS_READY); + allowedSteps.add(Content.STATUS_PUBLIC); + } + return allowedSteps; + } + + @Override + public List getManagingContentTypes(UserDetails user) throws ApsSystemException { + List types = new ArrayList(); + try { + List contentTypes = this.getContentManager().getSmallEntityTypes(); + for (int i = 0; i < contentTypes.size(); i++) { + SmallEntityType contentType = contentTypes.get(i); + Workflow workflow = this.getWorkflow(contentType.getCode()); + if (null != workflow && null != workflow.getRole()) { + String roleName = workflow.getRole(); + if (null == roleName || roleName.trim().length() == 0 + || this.getAuthorizationManager().isAuthOnRole(user, roleName)) { + types.add(contentType); + } + } else { + types.add(contentType); + } + } + } catch (Throwable t) { + _logger.error("Error extracting types by user {}", user, t); + throw new ApsSystemException("Error extracting types by user " + user, t); + } + return types; + } + + protected Map getWorkflowConfig() { + return _workflowConfig; + } + protected void setWorkflowConfig(Map workflowConfig) { + this._workflowConfig = workflowConfig; + } + + protected IContentWorkflowDAO getWorkflowDAO() { + return _workflowDAO; + } + public void setWorkflowDAO(IContentWorkflowDAO workflowDAO) { + this._workflowDAO = workflowDAO; + } + + protected ConfigInterface getConfigManager() { + return _configManager; + } + public void setConfigManager(ConfigInterface configManager) { + this._configManager = configManager; + } + + protected IContentManager getContentManager() { + return _contentManager; + } + public void setContentManager(IContentManager contentManager) { + this._contentManager = contentManager; + } + + protected IAuthorizationManager getAuthorizationManager() { + return _authorizationManager; + } + public void setAuthorizationManager(IAuthorizationManager authorizationManager) { + this._authorizationManager = authorizationManager; + } + + private Map _workflowConfig; + + private IContentWorkflowDAO _workflowDAO; + private ConfigInterface _configManager; + + private IContentManager _contentManager; + private IAuthorizationManager _authorizationManager; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/IContentWorkflowDAO.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/IContentWorkflowDAO.java new file mode 100644 index 0000000000..55867d3eec --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/IContentWorkflowDAO.java @@ -0,0 +1,33 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow; + +import java.util.List; + +/** + * @author E.Santoboni + */ +public interface IContentWorkflowDAO { + + public List searchUsedSteps(String typeCode); + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/IContentWorkflowManager.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/IContentWorkflowManager.java new file mode 100644 index 0000000000..038bc7db6b --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/IContentWorkflowManager.java @@ -0,0 +1,88 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow; + +import com.agiletec.aps.system.common.entity.model.SmallEntityType; +import java.util.ArrayList; +import java.util.List; + +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.aps.system.services.role.Permission; +import com.agiletec.aps.system.services.user.UserDetails; +import com.agiletec.plugins.jacms.aps.system.services.content.model.SmallContentType; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Step; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Workflow; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.WorkflowSearchFilter; + +/** + * @author E.Santoboni + */ +public interface IContentWorkflowManager { + + /** + * Restituisce il nome del ruolo per un dato tipo di contenuto. + * @param typeCode Il codice del tipo di contenuto. + * @return Il nome del ruolo per il tipo di contenuto richiesto. + */ + public String getRole(String typeCode); + + /** + * Aggiorna il ruolo per un dato tipo di contenuto. + * @param typeCode Il codice del tipo di contenuto. + * @param role Il nome del ruolo asociato al tipo di contenuto. + * @throws ApsSystemException In caso di errori in fase di aggiornamento. + */ + public void updateRole(String typeCode, String role) throws ApsSystemException; + + /** + * Restituisce la lista degli step per un dato tipo di contenuto. + * @param typeCode Il codice del tipo di contenuto. + * @return La lista degli step per il tipo di contenuto richiesto. + */ + public List getSteps(String typeCode); + + /** + * Aggiorna la lista degli step di un dato tipo di contenuto. + * @param workflow Il workflow aggiornato. + * @throws ApsSystemException In caso di errori in fase di aggiornamento. + */ + public void updateSteps(String typeCode, List steps) throws ApsSystemException; + + /** + * Restituisce il workflow per un dato tipo di contenuto. + * @param typeCode Il codice del tipo di contenuto. + * @return Il workflow per il tipo di contenuto richiesto. + */ + public Workflow getWorkflow(String typeCode); + + /** + * Restituisce gli step utilizzati per i contenuti del tipo dato. + * @param typeCode Il codice del tipo di contenuto. + * @return La lista degli step per cui sono presenti contenuti del tipo dato. + */ + public List searchUsedSteps(String typeCode); + + public List getWorkflowSearchFilters(UserDetails currentUser) throws ApsSystemException; + + public List getManagingContentTypes(UserDetails currentUser) throws ApsSystemException; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/Step.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/Step.java new file mode 100644 index 0000000000..94fc52e1b8 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/Step.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model; + +/** + * @author E.Santoboni + */ +public class Step { + + public String getCode() { + return _code; + } + public void setCode(String code) { + this._code = code; + } + + public String getDescr() { + return _descr; + } + public void setDescr(String descr) { + this._descr = descr; + } + + public String getRole() { + return _role; + } + public void setRole(String role) { + this._role = role; + } + + private String _code; + private String _descr; + private String _role; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/Workflow.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/Workflow.java new file mode 100644 index 0000000000..7f5a1905fe --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/Workflow.java @@ -0,0 +1,74 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * @author E.Santoboni + */ +public class Workflow { + + public String getTypeCode() { + return _typeCode; + } + public void setTypeCode(String typeCode) { + this._typeCode = typeCode; + } + + public String getRole() { + return _role; + } + public void setRole(String role) { + this._role = role; + } + + public Step getStep(String stepCode) { + return this._stepsMap.get(stepCode); + } + public void addStep(Step step) { + this._steps.add(step); + this._stepsMap.put(step.getCode(), step); + } + public List getSteps() { + return _steps; + } + public void setSteps(List steps) { + this._steps = steps; + this._stepsMap = new HashMap(); + Iterator stepsIter = steps.iterator(); + while (stepsIter.hasNext()) { + Step step = stepsIter.next(); + this._stepsMap.put(step.getCode(), step); + } + } + + private String _typeCode; + private String _role; + private List _steps = new ArrayList(); + private Map _stepsMap = new HashMap(); + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/WorkflowSearchFilter.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/WorkflowSearchFilter.java new file mode 100644 index 0000000000..1b40321668 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/model/WorkflowSearchFilter.java @@ -0,0 +1,52 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author E.Santoboni + */ +public class WorkflowSearchFilter { + + public String getTypeCode() { + return _typeCode; + } + public void setTypeCode(String typeCode) { + this._typeCode = typeCode; + } + + public List getAllowedSteps() { + return _allowedSteps; + } + public void setAllowedSteps(List allowedSteps) { + this._allowedSteps = allowedSteps; + } + public void addAllowedStep(String allowedStep) { + this._allowedSteps.add(allowedStep); + } + + private String _typeCode; + private List _allowedSteps = new ArrayList(); + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/parse/ContentWorkflowDOM.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/parse/ContentWorkflowDOM.java new file mode 100644 index 0000000000..48aa4952e4 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/parse/ContentWorkflowDOM.java @@ -0,0 +1,157 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.parse; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Step; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Workflow; +import java.io.StringReader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.input.SAXBuilder; +import org.jdom2.output.Format; +import org.jdom2.output.XMLOutputter; + +/** + * @author E.Santoboni + */ +public class ContentWorkflowDOM { + + public Map extractConfig(String xml) throws ApsSystemException { + Map config = new HashMap(); + Element root = this.getRootElement(xml); + Iterator contentTypesIter = root.getChildren(CONTENT_CHILD).iterator(); + while (contentTypesIter.hasNext()) { + Element contentTypeElem = contentTypesIter.next(); + Workflow workflow = this.extractContentWorkflow(contentTypeElem); + config.put(workflow.getTypeCode(), workflow); + } + return config; + } + + public String createConfigXml(Map config) throws ApsSystemException { + Element root = this.createConfigElement(config); + Document doc = new Document(root); + XMLOutputter out = new XMLOutputter(); + Format format = Format.getPrettyFormat(); + format.setIndent("\t"); + out.setFormat(format); + return out.outputString(doc); + } + + protected Workflow extractContentWorkflow(Element contentTypeElem) { + Workflow workflow = new Workflow(); + String typeCode = contentTypeElem.getAttributeValue(CONTENT_TYPECODE_ATTR); + workflow.setTypeCode(typeCode); + String role = contentTypeElem.getAttributeValue(CONTENT_ROLE_ATTR); + if (null != role && role.trim().length()>0) { + workflow.setRole(role.trim()); + } + Iterator stepIter = contentTypeElem.getChildren(STEP_CHILD).iterator(); + while (stepIter.hasNext()) { + Element stepElem = stepIter.next(); + Step step = this.extractStep(stepElem); + workflow.addStep(step); + } + return workflow; + } + + protected Step extractStep(Element stepElem) { + Step step = new Step(); + String code = stepElem.getAttributeValue(STEP_CODE_ATTR); + step.setCode(code); + String descr = stepElem.getAttributeValue(STEP_DESCR_ATTR); + step.setDescr(descr); + String role = stepElem.getAttributeValue(STEP_ROLE_ATTR); + step.setRole(role); + return step; + } + + protected Element createConfigElement(Map config) { + Element configElem = new Element(ROOT); + Iterator workflowIter = config.values().iterator(); + while (workflowIter.hasNext()) { + Workflow workflow = workflowIter.next(); + Element workflowElem = this.createWorkflowElement(workflow); + configElem.addContent(workflowElem); + } + return configElem; + } + + protected Element createWorkflowElement(Workflow workflow) { + Element workflowElem = new Element(CONTENT_CHILD); + workflowElem.setAttribute(CONTENT_TYPECODE_ATTR, workflow.getTypeCode()); + String role = workflow.getRole(); + if (role != null && role.trim().length() > 0) { + workflowElem.setAttribute(CONTENT_ROLE_ATTR, role.trim()); + } + Iterator stepsIter = workflow.getSteps().iterator(); + while (stepsIter.hasNext()) { + Step step = stepsIter.next(); + Element stepElem = this.createStepElement(step); + workflowElem.addContent(stepElem); + } + return workflowElem; + } + + protected Element createStepElement(Step step) { + Element stepElem = new Element(STEP_CHILD); + stepElem.setAttribute(STEP_CODE_ATTR, step.getCode()); + stepElem.setAttribute(STEP_DESCR_ATTR, step.getDescr()); + String role = step.getRole(); + if (role!=null) { + stepElem.setAttribute(STEP_ROLE_ATTR, step.getRole()); + } + return stepElem; + } + + protected Element getRootElement(String xmlText) throws ApsSystemException { + SAXBuilder builder = new SAXBuilder(); + builder.setValidation(false); + StringReader reader = new StringReader(xmlText); + Element root = null; + try { + Document doc = builder.build(reader); + root = doc.getRootElement(); + } catch (Throwable t) { + ApsSystemUtils.getLogger().error("Errore nel parsing: " + t.getMessage()); + throw new ApsSystemException("Errore nel parsing della configurazione Dimensioni di resize", t); + } + return root; + } + + private static final String ROOT = "contenttypes"; + + private static final String CONTENT_CHILD = "contenttype"; + private static final String CONTENT_TYPECODE_ATTR = "typecode"; + private static final String CONTENT_ROLE_ATTR = "role"; + + private static final String STEP_CHILD = "step"; + private static final String STEP_CODE_ATTR = "code"; + private static final String STEP_DESCR_ATTR = "descr"; + private static final String STEP_ROLE_ATTR = "role"; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/ContentAction.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/ContentAction.java new file mode 100644 index 0000000000..afee340563 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/ContentAction.java @@ -0,0 +1,239 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.content; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.system.common.entity.model.attribute.TextAttribute; +import com.agiletec.aps.system.services.user.UserDetails; +import com.agiletec.aps.util.SelectItem; +import com.agiletec.apsadmin.system.ApsAdminSystemConstants; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jacms.apsadmin.content.ContentActionConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.IContentWorkflowManager; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Workflow; +import com.agiletec.plugins.jpcontentworkflow.apsadmin.content.helper.IContentWorkFlowActionHelper; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.apache.commons.text.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author E.Santoboni + */ +public class ContentAction extends com.agiletec.plugins.jacms.apsadmin.content.ContentAction { + + private static final Logger _logger = LoggerFactory.getLogger(ContentAction.class); + + @Override + protected String saveContent(boolean approve) { + try { + Content currentContent = this.getContent(); + dumpTextAttributes(currentContent); + if (null != currentContent) { + int strutsAction = (null == currentContent.getId()) ? ApsAdminSystemConstants.ADD : ApsAdminSystemConstants.EDIT; + if (approve) { + strutsAction += 10; + } + if (!this.getContentActionHelper().isUserAllowed(currentContent, this.getCurrentUser())) { + _logger.info("User not allowed to save content {}", currentContent.getId()); + return USER_NOT_ALLOWED; + } + currentContent.setLastEditor(this.getCurrentUser().getUsername()); + if (approve) { + if (!Content.STATUS_READY.equals(currentContent.getStatus()) && !Content.STATUS_PUBLIC.equals(currentContent.getStatus())) { + String[] args = { currentContent.getId() , currentContent.getDescription()}; + this.addFieldError("status", this.getText("error.content.publish.notReadyStatus", args)); + return INPUT; + } + this.getContentManager().insertOnLineContent(currentContent); + } else { + this.getContentManager().saveContent(currentContent); + } + this.addActivityStreamInfo(currentContent, strutsAction, true); + this.getRequest().getSession().removeAttribute(ContentActionConstants.SESSION_PARAM_NAME_CURRENT_CONTENT_PREXIX + + this.getContentOnSessionMarker()); + this.getRequest().getSession().removeAttribute(ContentActionConstants.SESSION_PARAM_NAME_CURRENT_CONTENT_GROUP); + _logger.info("Saving content {} - Description: '{}' - User: {}", currentContent.getId(), currentContent.getDescription(), + this.getCurrentUser().getUsername()); + } else { + _logger.error("Save/approve NULL content - User: {}", this.getCurrentUser().getUsername()); + } + } catch (Throwable t) { + _logger.error("error in saveContent", t); + return FAILURE; + } + return SUCCESS; + } + + private void dumpTextAttributes(Content content) { + if (content != null) { + content.getAttributeList() + .forEach(a -> { + if (a instanceof TextAttribute) { + _logger.error("\t*** {}", a.getName()); + Map values = ((TextAttribute) a).getTextMap(); + if (values != null &&!values.isEmpty()) { + values.forEach((k,v) -> _logger.error("\t\t{}:{} [{}]", k, v, + StringEscapeUtils.unescapeHtml4(v))); + } + } + }); + } + } + + + /** + * Esegue l'azione di salvataggio contenuto con passaggio allo step precedente. + * @return Il codice del risultato dell'azione. + */ + public String previousStep() { + try { + Content currentContent = this.updateContentOnSession(); + dumpTextAttributes(currentContent); + if (null != currentContent) { + currentContent.setLastEditor(this.getCurrentUser().getUsername()); + String previousStep = this.getPreviousStep(); + if (previousStep != null) { + currentContent.setStatus(previousStep); + this.getContentManager().saveContent(currentContent); + String sessionParamName = ContentActionConstants.SESSION_PARAM_NAME_CURRENT_CONTENT_PREXIX + this.getContentOnSessionMarker(); + this.getRequest().getSession().removeAttribute(sessionParamName); + } else { + this.addActionError(this.getText("error.content.save.statusNotAllowed")); + return INPUT; + } + } else { + _logger.error("Tentativo Salvataggio/approvazione contenuto NULLO - Utente: " + this.getCurrentUser().getUsername()); + } + } catch (Exception e) { + _logger.error("Error extracting prev step", e); + return FAILURE; + } + return SUCCESS; + } + + /** + * Esegue l'azione di salvataggio contenuto con passaggio allo step successivo. + * @return Il codice del risultato dell'azione. + */ + public String nextStep() { + try { + Content currentContent = this.updateContentOnSession(); + dumpTextAttributes(currentContent); + if (null != currentContent) { + currentContent.setLastEditor(this.getCurrentUser().getUsername()); + String nextStep = this.getNextStep(); + if (nextStep != null) { + currentContent.setStatus(nextStep); + this.getContentManager().saveContent(currentContent); + String sessionParamName = ContentActionConstants.SESSION_PARAM_NAME_CURRENT_CONTENT_PREXIX + this.getContentOnSessionMarker(); + this.getRequest().getSession().removeAttribute(sessionParamName); + } else { + this.addActionError(this.getText("error.content.save.statusNotAllowed")); + return INPUT; + } + } else { + _logger.error("Tentativo Salvataggio/approvazione contenuto NULLO - Utente: " + this.getCurrentUser().getUsername()); + } + } catch (Exception e) { + _logger.error("Error extracting next step", e); + return FAILURE; + } + return SUCCESS; + } + + /** + * Verifica se l'utente corrente รจ abilitato all'accesso + * del contenuto specificato. + * @param content Il contenuto su cui verificare il permesso di accesso. + * @return True se l'utente corrente รจ abilitato all'eccesso al contenuto, + * false in caso contrario. + */ + @Override + protected boolean isUserAllowed(Content content) { + UserDetails currentUser = this.getCurrentUser(); + boolean isAllowed = this.getContentActionHelper().isUserAllowed(content, currentUser); + return isAllowed; + } + + public String getPreviousStep() { + if (this._previousStep == null) { + Content content = this.getContent(); + this._previousStep = ((IContentWorkFlowActionHelper) this.getContentActionHelper()).getPreviousStep(content.getStatus(), content.getTypeCode()); + } + return this._previousStep; + } + + public String getNextStep() { + if (this._nextStep == null) { + Content content = this.getContent(); + this._nextStep = ((IContentWorkFlowActionHelper) this.getContentActionHelper()).getNextStep(content.getStatus(), content.getTypeCode()); + } + return this._nextStep; + } + + @Override + public List getAvalaibleStatus() { + ApsSystemUtils.ApsDeepDebug.print("CONTENT", String.format("%s - getAvalaibleStatus", this.getClass().getName())); + List items = new ArrayList<>(); + try { + Content content = this.getContent(); + if (null == content) { + _logger.warn("Null content on session"); + return items; + } + String statusDescrKey = "name.contentStatus." +content.getStatus(); + SelectItem item = null; + if (statusDescrKey.equals(this.getText(statusDescrKey))) { + String contentType = content.getTypeCode(); + Workflow workflow = this.getWorkflowManager().getWorkflow(contentType); + if (null != workflow && null != workflow.getStep(content.getStatus())) { + item = new SelectItem(content.getStatus(), workflow.getStep(content.getStatus()).getDescr()); + } else { + item = new SelectItem(content.getStatus(), content.getStatus()); + } + } else { + item = new SelectItem(content.getStatus(), statusDescrKey); + } + items.add(item); + } catch (Exception e) { + _logger.error("Error extracting status", e); + throw new RuntimeException("Error in getAvalaibleStatus", e); + } + return items; + } + + protected IContentWorkflowManager getWorkflowManager() { + return _workflowManager; + } + public void setWorkflowManager(IContentWorkflowManager workflowManager) { + this._workflowManager = workflowManager; + } + + private String _previousStep; + private String _nextStep; + + private IContentWorkflowManager _workflowManager; + +} diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/ContentFinderAction.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/ContentFinderAction.java new file mode 100644 index 0000000000..a3e884646c --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/ContentFinderAction.java @@ -0,0 +1,221 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.content; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.system.common.entity.model.EntitySearchFilter; +import com.agiletec.aps.system.common.entity.model.SmallEntityType; +import com.agiletec.aps.system.common.model.dao.SearcherDaoPaginatedResult; +import com.agiletec.aps.system.services.category.Category; +import com.agiletec.aps.system.services.role.Permission; +import com.agiletec.aps.system.services.user.UserDetails; +import com.agiletec.aps.util.SelectItem; +import com.agiletec.plugins.jacms.aps.system.services.content.IContentManager; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jacms.apsadmin.content.ContentFinderSearchInfo; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.content.IContentSearcherManager; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.WorkflowSearchFilter; +import com.agiletec.plugins.jpcontentworkflow.apsadmin.content.helper.IContentWorkFlowActionHelper; +import org.apache.commons.lang3.ArrayUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author E.Santoboni + */ +public class ContentFinderAction extends com.agiletec.plugins.jacms.apsadmin.content.ContentFinderAction { + + private static final Logger logger = LoggerFactory.getLogger(ContentFinderAction.class); + + @Override + public SearcherDaoPaginatedResult getPaginatedContentsId(Integer limit) { + SearcherDaoPaginatedResult result = null; + try { + if (this.hasCurrentUserPermission(Permission.SUPERUSER)) { + return super.getPaginatedContentsId(limit); + } + ContentFinderSearchInfo searchInfo = this.getContentSearchInfo(); + UserDetails user = this.getCurrentUser(); + List workflowFilters = ((IContentWorkFlowActionHelper) this.getContentActionHelper()).getWorkflowSearchFilters(user); + if (workflowFilters.size() > 0) { + List allowedGroups = this.getContentGroupCodes(); + EntitySearchFilter[] filters = this.createFilters(); + if (null != limit) { + filters = ArrayUtils.add(filters, this.getPagerFilter(limit)); + } + String[] categories = null; + Category category = this.getCategoryManager().getCategory(this.getCategoryCode()); + if (null != category && !category.isRoot()) { + categories = new String[]{this.getCategoryCode().trim()}; + searchInfo.setCategoryCode(this.getCategoryCode().trim()); + } else { + searchInfo.setCategoryCode(null); + } + result = this.getContentSearcherManager().getPaginatedWorkContentsId(workflowFilters, categories, false, filters, allowedGroups); + } else { + result = new SearcherDaoPaginatedResult(); + result.setCount(0); + result.setList(new ArrayList<>()); + } + } catch (Throwable t) { + logger.error("error in getPaginatedWorkContentsId", t); + throw new RuntimeException("error in getPaginatedWorkContentsId", t); + } + return result; + } + + private ContentFinderSearchInfo getContentSearchInfo() { + ContentFinderSearchInfo searchInfo = (ContentFinderSearchInfo) this.getRequest().getSession() + .getAttribute(ContentFinderSearchInfo.SESSION_NAME); + return searchInfo; + } + + @Override + @Deprecated + public List getContents() { + List result = null; + try { + if (this.hasCurrentUserPermission(Permission.SUPERUSER)) { + return super.getContents(); + } + UserDetails user = this.getCurrentUser(); + List workflowFilters = ((IContentWorkFlowActionHelper) this.getContentActionHelper()).getWorkflowSearchFilters(user); + if (workflowFilters.size() > 0) { + List allowedGroups = this.getContentGroupCodes(); + EntitySearchFilter[] filters = this.createFilters(); + String[] categories = null; + Category category = this.getCategoryManager().getCategory(this.getCategoryCode()); + if (null != category && !category.isRoot()) { + categories = new String[]{this.getCategoryCode().trim()}; + } + result = this.getContentSearcherManager().loadContentsId(workflowFilters, categories, filters, allowedGroups); + } else { + result = new ArrayList<>(); + } + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "getContents"); + throw new RuntimeException("Error searching contents", t); + } + return result; + } + + @Override + public String insertOnLine() { + try { + if (null == this.getContentIds()) { + return SUCCESS; + } + Iterator iter = this.getContentIds().iterator(); + List publishedContents = new ArrayList<>(); + IContentManager contentManager = (IContentManager) this.getContentManager(); + while (iter.hasNext()) { + String contentId = (String) iter.next(); + Content contentToPublish = contentManager.loadContent(contentId, false); + String[] msgArg = new String[1]; + if (null == contentToPublish) { + msgArg[0] = contentId; + this.addActionError(this.getText("error.content.contentToPublishNull", msgArg)); + continue; + } + msgArg[0] = contentToPublish.getDescription(); + if (!Content.STATUS_READY.equals(contentToPublish.getStatus())) { + String nextStep = this.getNextStep(contentToPublish); + if (null != nextStep && !Content.STATUS_READY.equals(nextStep)) { + String[] args = {contentToPublish.getId(), contentToPublish.getDescription(), contentToPublish.getStatus()}; + this.addActionError(this.getText("error.content.publish.statusNotAllowed", args)); + continue; + } + } + if (!this.isUserAllowed(contentToPublish)) { + this.addActionError(this.getText("error.content.userNotAllowedToPublishContent", msgArg)); + continue; + } + this.getContentActionHelper().scanEntity(contentToPublish, this); + if (!this.getFieldErrors().isEmpty()) { + this.addActionError(this.getText("error.content.publishingContentWithErrors", msgArg)); + continue; + } + contentManager.insertOnLineContent(contentToPublish); + ApsSystemUtils.getLogger().info("Content '" + contentToPublish.getId() + + "' published by user '" + this.getCurrentUser().getUsername() + "'"); + publishedContents.add(contentToPublish); + } + //RIVISITARE LOGICA DI COSTRUZIONE LABEL + this.addConfirmMessage("message.content.publishedContents", publishedContents); + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "insertOnLine"); + throw new RuntimeException("Error inserting online content", t); + } + return SUCCESS; + } + + protected String getNextStep(Content content) { + return ((IContentWorkFlowActionHelper) this.getContentActionHelper()).getNextStep(content.getStatus(), content.getTypeCode()); + } + + // Portare a protected in Action padre di jacms + protected void addConfirmMessage(String key, List deletedContents) { + if (deletedContents.size() > 0) { + String confirm = this.getText(key); + for (int i=0; i0) { + confirm += " - "; + } + confirm += " '" + content.getDescription()+ "'"; + } + this.addActionMessage(confirm); + } + } + + @Override + public List getContentTypes() { + return ((IContentWorkFlowActionHelper) this.getContentActionHelper()).getAllowedContentTypes(this.getCurrentUser()); + } + + @Override + public List getAvalaibleStatus() { + if (null != this.getContentType() && this.getContentType().trim().length() > 0) { + return ((IContentWorkFlowActionHelper) this.getContentActionHelper()).getAvalaibleStatus(this.getCurrentUser(), this.getContentType()); + } + List items = new ArrayList<>(); + items.add(new SelectItem(Content.STATUS_DRAFT, "name.contentStatus." + Content.STATUS_DRAFT)); + if (super.hasCurrentUserPermission(Permission.SUPERVISOR)) { + items.add(new SelectItem(Content.STATUS_READY, "name.contentStatus." + Content.STATUS_READY)); + } + return items; + } + + protected IContentSearcherManager getContentSearcherManager() { + return _contentSearcherManager; + } + public void setContentSearcherManager(IContentSearcherManager contentSearcherManager) { + this._contentSearcherManager = contentSearcherManager; + } + + private IContentSearcherManager _contentSearcherManager; + +} diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/IntroNewContentActionAspect.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/IntroNewContentActionAspect.java new file mode 100644 index 0000000000..4a2ac5b2ac --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/IntroNewContentActionAspect.java @@ -0,0 +1,118 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.content; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.system.SystemConstants; +import com.agiletec.aps.system.common.entity.model.SmallEntityType; +import com.agiletec.aps.system.services.user.UserDetails; +import com.agiletec.aps.util.SelectItem; +import com.agiletec.plugins.jacms.aps.system.services.content.IContentManager; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jacms.aps.system.services.content.model.SmallContentType; +import com.agiletec.plugins.jacms.apsadmin.content.IntroNewContentAction; +import com.agiletec.plugins.jpcontentworkflow.apsadmin.content.helper.IContentWorkFlowActionHelper; +import jakarta.servlet.http.HttpServletRequest; +import java.util.List; +import org.apache.struts2.ServletActionContext; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; + +/** + * @author E.Santoboni + */ +@Aspect +public class IntroNewContentActionAspect { + + @After("execution(* com.agiletec.plugins.jacms.apsadmin.content.IntroNewContentAction.createNewVoid())") + public void checkCreateNewContent(JoinPoint joinPoint) { + try { + IntroNewContentAction action = (IntroNewContentAction) joinPoint.getTarget(); + List allowedContentTypes = this.getAllowedContentTypes(); + boolean check = false; + for (int i = 0; i < allowedContentTypes.size(); i++) { + SmallEntityType contentType = allowedContentTypes.get(i); + if (contentType.getCode().equals(action.getContentTypeCode())) { + check = true; + break; + } + } + if (!check) { + SmallContentType contentType = (SmallContentType) this.getContentManager().getSmallContentTypesMap().get(action.getContentTypeCode()); + String typeDescr = contentType != null ? contentType.getCode() : action.getContentTypeCode(); + action.addFieldError("contentTypeCode", action.getText("error.content.contentType.userNotAllowed", typeDescr)); + } + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "getAllowedContentTypes", "Error checking content type authorization"); + throw new RuntimeException("Error extracting allowed content types", t); + } + } + /* + //@Override + public String getContentStatus() { + return Content.STATUS_DRAFT; + } + */ + @AfterReturning(pointcut = "execution(* com.agiletec.plugins.jacms.apsadmin.content.IntroNewContentAction.getContentTypes())", returning = "contentTypes") + public void getAllowedContentTypes(Object contentTypes) { + List allowed = this.getAllowedContentTypes(); + System.out.println("getAllowedContentTypes " + this); + ((List)contentTypes).clear(); + ((List)contentTypes).addAll(allowed); + } + + protected List getAllowedContentTypes() { + HttpServletRequest request = ServletActionContext.getRequest(); + UserDetails currentUser = (UserDetails) request.getSession().getAttribute(SystemConstants.SESSIONPARAM_CURRENT_USER); + return this.getContentActionHelper().getAllowedContentTypes(currentUser); + } + + //@Override + @AfterReturning(pointcut = "execution(* com.agiletec.plugins.jacms.apsadmin.content.IntroNewContentAction.getAvalaibleStatus())", returning = "items") + public void getAvalaibleStatus(Object items) { + System.out.println("getAvalaibleStatus " + this); + //List items = new ArrayList(1); + SelectItem item = new SelectItem(Content.STATUS_DRAFT, "name.contentStatus." + Content.STATUS_DRAFT); + ((List)items).clear(); + ((List)items).add(item); + } + + protected IContentManager getContentManager() { + return _contentManager; + } + public void setContentManager(IContentManager contentManager) { + this._contentManager = contentManager; + } + + protected IContentWorkFlowActionHelper getContentActionHelper() { + return _contentActionHelper; + } + public void setContentActionHelper(IContentWorkFlowActionHelper contentActionHelper) { + this._contentActionHelper = contentActionHelper; + } + + private IContentManager _contentManager; + private IContentWorkFlowActionHelper _contentActionHelper; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/JpCwIntroNewContentAction.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/JpCwIntroNewContentAction.java new file mode 100644 index 0000000000..182307cc35 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/JpCwIntroNewContentAction.java @@ -0,0 +1,96 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.content; + +import java.util.ArrayList; +import java.util.List; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.system.common.entity.model.SmallEntityType; +import com.agiletec.aps.util.SelectItem; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jacms.aps.system.services.content.model.SmallContentType; +import com.agiletec.plugins.jpcontentworkflow.apsadmin.content.helper.IContentWorkFlowActionHelper; + +/** + * @author E.Santoboni + */ +public class JpCwIntroNewContentAction extends com.agiletec.plugins.jacms.apsadmin.content.IntroNewContentAction { + + @Override + public void validate() { + super.validate(); + this.checkContentType(); + } + + protected void checkContentType() { + try { + List allowedContentTypes = this.getContentTypes(); + boolean check = false; + for (int i = 0; i < allowedContentTypes.size(); i++) { + SmallContentType contentType = allowedContentTypes.get(i); + if (contentType.getCode().equals(this.getContentTypeCode())) { + check = true; + break; + } + } + if (!check) { + SmallContentType contentType = (SmallContentType) this.getContentManager().getSmallContentTypesMap().get(this.getContentTypeCode()); + String typeDescr = contentType != null ? contentType.getCode() : this.getContentTypeCode(); + this.addFieldError("contentTypeCode", this.getText("error.content.contentType.userNotAllowed", typeDescr)); + } + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "getAllowedContentTypes", "Error checking content type authorization"); + throw new RuntimeException("Error extracting allowed content types", t); + } + + } + + @Override + public String getContentStatus() { + return Content.STATUS_DRAFT; + } + + @Override + @Deprecated + public List getContentTypes() { + List cts = new ArrayList(); + List types = ((IContentWorkFlowActionHelper) this.getContentActionHelper()).getAllowedContentTypes(this.getCurrentUser()); + for (int i = 0; i < types.size(); i++) { + SmallEntityType set = types.get(i); + SmallContentType ct = new SmallContentType(); + ct.setCode(set.getCode()); + ct.setDescr(set.getDescription()); + cts.add(ct); + } + return cts; + } + + @Override + public List getAvalaibleStatus() { + List items = new ArrayList(1); + SelectItem item = new SelectItem(Content.STATUS_DRAFT, "name.contentStatus." + Content.STATUS_DRAFT); + items.add(item); + return items; + } + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/content.xml b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/content.xml new file mode 100644 index 0000000000..797929cb39 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/content.xml @@ -0,0 +1,163 @@ + + + + + + + + + admin.jacms.content.list + + editContents + fieldErrors,actionErrors,actionMessages + + + + + admin.jacms.content.list + editContents + + + + admin.jacms.content.list + editContents + + + + admin.jacms.content.list + editContents + + + + admin.jacms.content.list + editContents + + + + list + list + + validateContents + + + + list + list + + validateContents + + + + list + list + admin.jacms.content.trash + editContents + + + + list + list + + editContents + + + + + + admin.jacms.content.entry + editContents + + + + admin.jacms.content.entry + editContents + + + + newJpCw + editContents + + + admin.jacms.content.new + editContents + + + + admin.jacms.content.new + createNewVoidJpCw + editContents + + + + admin.jacms.content.new + + entryContent + ${contentOnSessionMarker} + + + editContents + contentOnSessionMarker + + + + + admin.jacms.content.entry + editContents + + + + admin.jacms.content.entry + editContents + + + + admin.jacms.content.entry + editContents + + + + admin.jacms.content.entry + editContents + + + + admin.jacms.content.entry + list + + editContents + + + + admin.jacms.content.entry + list + + editContents + + + + admin.jacms.content.entry + results + + editContents + + + + admin.jacms.content.entry + results + + validateContents + + + + admin.jacms.content.entry + admin.jacms.content.references + results + + validateContents + + + + + diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/helper/ContentActionHelper.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/helper/ContentActionHelper.java new file mode 100644 index 0000000000..4e1ad4b1b0 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/helper/ContentActionHelper.java @@ -0,0 +1,228 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.content.helper; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.system.common.entity.model.IApsEntity; +import com.agiletec.aps.system.common.entity.model.SmallEntityType; +import com.agiletec.aps.system.services.role.Permission; +import com.agiletec.aps.system.services.user.UserDetails; +import com.agiletec.aps.util.SelectItem; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.IContentWorkflowManager; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Step; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Workflow; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.WorkflowSearchFilter; +import jakarta.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * @author E.Santoboni + */ +public class ContentActionHelper extends com.agiletec.plugins.jacms.apsadmin.content.helper.ContentActionHelper + implements IContentWorkFlowActionHelper { + + @Override + public void updateEntity(IApsEntity entity, HttpServletRequest request) { + Content content = (Content) entity; + try { + if (null != content) { + String descr = request.getParameter("descr"); + if (descr != null) content.setDescription(descr.trim()); + // Non consente di modificare lo stato del contenuto + String status = content.getStatus(); + if (status==null || status.equals(Content.STATUS_NEW)) { + content.setStatus(Content.STATUS_DRAFT); + } + if (null == content.getId()) { + String mainGroup = request.getParameter("mainGroup"); + if (mainGroup != null) content.setMainGroup(mainGroup); + } + super.updateEntity(content, request); + } + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "updateContent"); + throw new RuntimeException("Errore in updateContent", t); + } + } + + @Override + public List getWorkflowSearchFilters(UserDetails currentUser) { + try { + return this.getWorkflowManager().getWorkflowSearchFilters(currentUser); + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "getWorkflowSearchFilters", "Error extracting filters"); + throw new RuntimeException("Error extracting filters", t); + } + } + + @Override + public String getPreviousStep(String currentStep, String typeCode) { + String previousStep = null; + if (!currentStep.equals(Content.STATUS_NEW) && !currentStep.equals(Content.STATUS_DRAFT)) { + List steps = this.getWorkflowManager().getSteps(typeCode); + previousStep = Content.STATUS_DRAFT; + if (Content.STATUS_READY.equals(currentStep)) { + if (steps.size() > 0) { + previousStep = steps.get(steps.size()-1).getCode(); + } + } else { + for (int i = 0; i < steps.size(); i++) { + Step step = steps.get(i); + if (step.getCode().equals(currentStep)) { + break; + } + previousStep = step.getCode(); + } + } + } + return previousStep; + } + + @Override + public String getNextStep(String currentStep, String typeCode) { + String nextStep = null; + if (!currentStep.equals(Content.STATUS_READY) && !currentStep.equals(Content.STATUS_PUBLIC)) { + List steps = this.getWorkflowManager().getSteps(typeCode); + Iterator stepsIter = steps.iterator(); + if (!currentStep.equals(Content.STATUS_NEW) && !currentStep.equals(Content.STATUS_DRAFT)) { + while (stepsIter.hasNext()) { + if (currentStep.equals(stepsIter.next().getCode())) { + break; + } + } + } + if (stepsIter.hasNext()) { + nextStep = stepsIter.next().getCode(); + } else { + nextStep = Content.STATUS_READY; + } + } + return nextStep; + } + + @Override + public boolean isUserAllowed(Content content, UserDetails currentUser) { + try { + if (!super.isUserAllowed(content, currentUser)) { + return false; + } + boolean allowedType = false; + List allowedContentTypes = this.getAllowedContentTypes(currentUser); + for (int i = 0; i < allowedContentTypes.size(); i++) { + SmallEntityType smallContentType = allowedContentTypes.get(i); + if (smallContentType.getCode().equals(content.getTypeCode())) { + allowedType = true; + break; + } + } + if (!allowedType) { + return false; + } + String status = content.getStatus(); + if (status != null && !status.equals(Content.STATUS_NEW) && !status.equals(Content.STATUS_DRAFT)) { + if (status.equals(Content.STATUS_READY) || status.equals(Content.STATUS_PUBLIC)) { + boolean isSupervisor = this.getAuthorizationManager().isAuthOnPermission(currentUser, Permission.SUPERVISOR); + if (!isSupervisor) { + return false; + } + } else { + List steps = this.getWorkflowManager().getSteps(content.getTypeCode()); + boolean auth = false; + for (int i = 0; i < steps.size(); i++) { + Step step = steps.get(i); + if (step.getCode().equals(status)) { + if (step.getRole() != null || this.checkRole(step.getRole(), currentUser)) { + auth = true; + break; + } + } + } + if (!auth) { + return false; + } + } + } + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "isUserAllowed"); + throw new RuntimeException("Error checking user authority", t); + } + return true; + } + + @Override + public List getAllowedContentTypes(UserDetails currentUser) { + try { + return this.getWorkflowManager().getManagingContentTypes(currentUser); + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "getAllowedContentTypes", "Error extracting allowed content types"); + throw new RuntimeException("Error extracting allowed content types", t); + } + } + + @Override + public List getAvalaibleStatus(UserDetails user, String contentTypeCode) { + List items = new ArrayList(); + String roleName = this.getWorkflowManager().getRole(contentTypeCode); + if (!this.checkRole(roleName, user)) { + return items; + } + Workflow workflow = this.getWorkflowManager().getWorkflow(contentTypeCode); + items.add(new SelectItem(Content.STATUS_DRAFT, "name.contentStatus." + Content.STATUS_DRAFT)); + if (null != workflow) { + Iterator stepsIter = workflow.getSteps().iterator(); + while (stepsIter.hasNext()) { + Step step = stepsIter.next(); + if (this.checkRole(step.getRole(), user)) { + items.add(new SelectItem(step.getCode(), step.getDescr())); + } + } + } + if (this.getAuthorizationManager().isAuthOnPermission(user, Permission.SUPERVISOR)) { + items.add(new SelectItem(Content.STATUS_READY, "name.contentStatus." + Content.STATUS_READY)); + } + return items; + } + + protected boolean checkRole(String roleName, UserDetails user) { + boolean isAllowed = true; + if (roleName != null && roleName.length() > 0) { + boolean isSuperuser = this.getAuthorizationManager().isAuthOnPermission(user, Permission.SUPERUSER); + if (!isSuperuser) { + isAllowed = this.getAuthorizationManager().isAuthOnRole(user, roleName); + } + } + return isAllowed; + } + + protected IContentWorkflowManager getWorkflowManager() { + return _workflowManager; + } + public void setWorkflowManager(IContentWorkflowManager workflowManager) { + this._workflowManager = workflowManager; + } + + private IContentWorkflowManager _workflowManager; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/helper/IContentWorkFlowActionHelper.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/helper/IContentWorkFlowActionHelper.java new file mode 100644 index 0000000000..00457e3862 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/helper/IContentWorkFlowActionHelper.java @@ -0,0 +1,47 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.content.helper; + +import com.agiletec.aps.system.common.entity.model.SmallEntityType; +import java.util.List; + +import com.agiletec.aps.system.services.user.UserDetails; +import com.agiletec.aps.util.SelectItem; +import com.agiletec.plugins.jacms.aps.system.services.content.model.SmallContentType; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.WorkflowSearchFilter; + +/** + * @author E.Santoboni + */ +public interface IContentWorkFlowActionHelper { + + public List getWorkflowSearchFilters(UserDetails user); + + public List getAllowedContentTypes(UserDetails currentUser); + + public List getAvalaibleStatus(UserDetails user, String contentTypeCode); + + public String getPreviousStep(String currentStep, String typeCode); + + public String getNextStep(String currentStep, String typeCode); + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/package_en.properties b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/package_en.properties new file mode 100644 index 0000000000..ccdeccd287 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/package_en.properties @@ -0,0 +1,47 @@ +title.contentManagement=Content Management + +#WORKFLOW CONTENUTI +label.nextStep=Next Step +label.previousStep=Previous Step +label.inventoryId=Inventory Id +label.contentId=Content Id + +note.button.nextStep=Pass to the next step +note.button.previousStep=Pass to the previous step + +#WORKFLOW VALIDATION LABELS +error.content.contentType.userNotAllowed=User not allowed to edit contents of type {0}. +error.content.save.statusNotAllowed=Content editing ''{0}''-''{1}'' not allowed. +error.content.publish.notReadyStatus=Content ''{0}''-''{1}'' not 'Ready'. +error.content.publish.statusNotAllowed=Content publishing ''{0}''-''{1}'' not allowed - status ''{2}''. + +title.categoryTree=Category tree +title.advancedContentFinding=Advanced content search +advancedContentSearch=Advanced search +error.nullContentVersion=There is any version + +#ADVANCED SEARCH +label.contentTypeFilter=Refine seaech for contentType +requiredContentType=Content Type is required +label.filterFrom=from +label.filterTo=to +label.filterValue=which contains +label.filterValue.exact=which must be +invalidNumber=the field {0} must be numeric +invalidDate=the field {0} must be a date + +Page.extraGroupRefContent=Contenuto Publicato nella pagina ''{0}'' e deve essere visibile ai gruppi {1} + +note.button.changeOwnerGroup=Cambia gruppo proprieterio +label.pagerItems=Elementi per pagina +label.selectAll=Seleziona tutti +label.selectNone=Deseleziona tutti +name.isUnsyncContent=Approvato e Modificato + +label.OPERATOR_AND=tutte le parole +label.OPERATOR_OR=almeno una parola +label.OPERATOR_EXACT=frase esatta + +content.sipervisor.readOnly=Attenzione: contenuto in sola visualizzazione. Le modifiche non verranno salvate +note.button.approve=Approve the content +label.approve=Approve the content diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/package_it.properties b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/package_it.properties new file mode 100644 index 0000000000..d4b6318a24 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/package_it.properties @@ -0,0 +1,47 @@ +title.contentManagement=Gestione Contenuti + +#WORKFLOW CONTENUTI +label.nextStep=Prossimo Step +label.previousStep=Step Precedente +label.inventoryId=Inventory Id +label.contentId=Id Contenuto + +note.button.nextStep=Passa allo step successivo +note.button.previousStep=Passa allo step precedente + +#WORKFLOW VALIDATION LABELS +error.content.contentType.userNotAllowed=Utente non autorizzato ad editare contenuti del tipo {0}. +error.content.save.statusNotAllowed=Modifica stato contenuto ''{0}''-''{1}'' non consentita. +error.content.publish.notReadyStatus=Non è possibile pubblicare il contenuto ''{0}''-''{1}''. Non è in stato 'Pronto'. +error.content.publish.statusNotAllowed=Pubblicazione contenuto ''{0}''-''{1}'' non consentita - stato ''{2}''. + +title.categoryTree=Albero delle categorie +title.advancedContentFinding=Ricerca avanzata contenuti +advancedContentSearch=Ricerca avanzata +error.nullContentVersion=Nessuna versione disponibile + +#ADVANCED SEARCH +label.contentTypeFilter=Affina la ricerca per tipo di contenuto +requiredContentType=È necessario specificare un campo per il tipo di contenuto +label.filterFrom=da +label.filterTo=fino a +label.filterValue.exact=che sia +label.filterValue=che contenga +invalidNumber=il campo {0} deve essere di tipo numerico +invalidNumber=il campo {0} deve essere una data del tipo dd/MM/yyyy + +Page.extraGroupRefContent=Contenuto Publicato nella pagina ''{0}'' e deve essere visibile ai gruppi {1} + +note.button.changeOwnerGroup=Cambia gruppo proprieterio +label.pagerItems=Elementi per pagina +label.selectAll=Seleziona tutti +label.selectNone=Deseleziona tutti +name.isUnsyncContent=Approvato e Modificato + +label.OPERATOR_AND=tutte le parole +label.OPERATOR_OR=almeno una parola +label.OPERATOR_EXACT=frase esatta + +content.sipervisor.readOnly=Attenzione: contenuto in sola visualizzazione. Le modifiche non verranno salvate +note.button.approve=Approva il contenuto +label.approve=Approva il contenuto diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/global-messages_en.properties b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/global-messages_en.properties new file mode 100644 index 0000000000..196ada4533 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/global-messages_en.properties @@ -0,0 +1,19 @@ +jpcontentworkflow.code=jpcontentworkflow +jpcontentworkflow.name=Content Workflow + +jpcontentworkflow.menu.workflowAdmin=Workflow +jpcontentworkflow.menu.workflow=Workflow Configuration +jpcontentworkflow.menu.notifier=Notifier Configuration + +jpcontentworkflow.workflow.config.shortDesc=Workflow Config +jpcontentworkflow.workflow.config.longDesc=Workflow Configuration: configure steps and privileges. +jpcontentworkflow.workflow.notifier.config.shortDesc=Workflow Notifier +jpcontentworkflow.workflow.notifier.config.longDesc=Configure the notifier for the workflow process. + +name.contentStatus.DRAFT=Draft (default step) +name.contentStatus.READY=Ready (default step) +name.contentStatus.PUBLIC=Public (default step) + +jpcontentworkflow.title.general.help=The CONTENT WORKFLOW plugin lets you extend the basic content workflow and create and manage enhanced workflows. + +title.workflowManagement=Workflow \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/global-messages_it.properties b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/global-messages_it.properties new file mode 100644 index 0000000000..f9953d2dfc --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/global-messages_it.properties @@ -0,0 +1,19 @@ +jpcontentworkflow.code=jpcontentworkflow +jpcontentworkflow.name=Workflow Contenuti + +jpcontentworkflow.menu.workflowAdmin=Workflow +jpcontentworkflow.menu.workflow=Workflow Configuration +jpcontentworkflow.menu.notifier=Configurazione Notificatore + +jpcontentworkflow.workflow.config.shortDesc=Workflow Config. +jpcontentworkflow.workflow.config.longDesc=Configurazione Workflow: configura i privilegi e il flusso. +jpcontentworkflow.workflow.notifier.config.shortDesc=Workflow Notificatore +jpcontentworkflow.workflow.notifier.config.longDesc=Configura le notifiche associate agli stati del Workflow. + +name.contentStatus.DRAFT=Bozza (default step) +name.contentStatus.READY=Pronto (default step) +name.contentStatus.PUBLIC=Pubblico (default step) + +jpcontentworkflow.title.general.help=Il plugin WORKFLOW DEI CONTENUTI consente di estendere il workflow base dei contenuti e gestire workflow avanzati. + +title.workflowManagement=Workflow \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/WorkflowNotifierConfigAction-validation.xml b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/WorkflowNotifierConfigAction-validation.xml new file mode 100644 index 0000000000..b9d1256d7e --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/WorkflowNotifierConfigAction-validation.xml @@ -0,0 +1,54 @@ + + + + + + + 1 + + + + + + + true + + + + + + + + + + + 0 + 23 + + + + + + + 0 + 59 + + + + + + + true + + + + + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/WorkflowNotifierConfigAction.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/WorkflowNotifierConfigAction.java new file mode 100644 index 0000000000..1c9db28126 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/WorkflowNotifierConfigAction.java @@ -0,0 +1,163 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.notifier; + +import java.text.ParseException; +import java.util.Calendar; +import java.util.Date; +import java.util.Map; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.aps.util.DateConverter; +import com.agiletec.apsadmin.system.BaseAction; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.IWorkflowNotifierManager; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.NotifierConfig; +import com.agiletec.plugins.jpmail.aps.services.mail.IMailManager; + +/** + * @author E.Santoboni + */ +public class WorkflowNotifierConfigAction extends BaseAction { + + public String config() { + try { + NotifierConfig notifierConfig = this.getNotifierManager().getNotifierConfig(); + this.valueFormForEdit(notifierConfig); + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "config"); + return FAILURE; + } + return SUCCESS; + } + + public String save() { + try { + NotifierConfig notifierConfig = this.getUpdatedConfig(); + this.getNotifierManager().saveNotifierConfig(notifierConfig); + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "save"); + return FAILURE; + } + return SUCCESS; + } + + protected NotifierConfig getUpdatedConfig() throws ApsSystemException, ParseException { + NotifierConfig notifierConfig = this.getConfig(); + + Date startDate = DateConverter.parseDate(this.getStartDate(), DATE_FORMAT); + long time = startDate.getTime() + this.getHour() * 3600000l + this.getMinute() * 60000l; + startDate.setTime(time); + notifierConfig.setStartScheduler(startDate); + + return notifierConfig; + } + + protected void valueFormForEdit(NotifierConfig notifierConfig) { + this.setConfig(notifierConfig); + + Calendar start = Calendar.getInstance(); + start.setTime(notifierConfig.getStartScheduler()); + this.setStartDate(DateConverter.getFormattedDate(notifierConfig.getStartScheduler(), DATE_FORMAT)); + this.setHour(start.get(Calendar.HOUR_OF_DAY)); + this.setMinute(start.get(Calendar.MINUTE)); + } + + public int[] getCounterArray(int startValue, int length) { + int[] counter = {}; + if (length > 0) { + counter = new int[length]; + for (int i = 0; i < length; i++) { + counter[i] = startValue++; + } + } + return counter; + } + + public Map getSenderCodes() { + try { + return this.getMailManager().getMailConfig().getSenders(); + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "getSenderCodes"); + throw new RuntimeException("Error loading mail sender codes", t); + } + } + + public NotifierConfig getConfig() { + return _config; + } + + public void setConfig(NotifierConfig config) { + this._config = config; + } + + public String getStartDate() { + return _startDate; + } + + public void setStartDate(String startDate) { + this._startDate = startDate; + } + + public int getHour() { + return _hour; + } + + public void setHour(int hour) { + this._hour = hour; + } + + public int getMinute() { + return _minute; + } + + public void setMinute(int minute) { + this._minute = minute; + } + + protected IWorkflowNotifierManager getNotifierManager() { + return _notifierManager; + } + + public void setNotifierManager(IWorkflowNotifierManager notifierManager) { + this._notifierManager = notifierManager; + } + + protected IMailManager getMailManager() { + return _mailManager; + } + + public void setMailManager(IMailManager mailManager) { + this._mailManager = mailManager; + } + + private NotifierConfig _config = new NotifierConfig(); + + private String _startDate; + private int _hour; + private int _minute; + + private IWorkflowNotifierManager _notifierManager; + private IMailManager _mailManager; + private static final String DATE_FORMAT = "dd/MM/yyyy"; + +} diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/notifier.xml b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/notifier.xml new file mode 100644 index 0000000000..56826a89a6 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/notifier.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + admin.jpcontentworkflow.notifier.config + superuser + + + + admin.jpcontentworkflow.notifier.config + admin.jpcontentworkflow.notifier.savedConfirm + superuser + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/package_en.properties b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/package_en.properties new file mode 100644 index 0000000000..71bf51c97f --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/package_en.properties @@ -0,0 +1,37 @@ +label.active=Active Service +label.senderCode=E-mail Sender +label.mailAttrName=E-mail field of User Profile +label.hoursDelay=Delay (hours) +label.startDate=Start date +label.startDatePattern=dd/mm/yyyy +label.hour=Hour +label.minute=Minute +label.html=Send in HTML format +label.subject=Subject +label.header=Header +label.template=Single Content Template +label.footer=Footer + +label.schedulerSettings=Scheduler Settings +label.mailSettings=Mail Settings +notifier.generalSettings=General Settings + +title.workflowNotifierManagement=Workflow - Content Status Change Notifier +title.workflowNotifierManagement.config=Notifier Configuration + +note.workflowNotifierManagement.savedConfirm=Notifier Configuration Successfully Saved + +#LABELS IN USO AL VALIDATORE +requiredstring=${getText(fieldName)} is required. +wrongDate=${getText(fieldName)} doesn't match [dd/mm/yyyy] sintax. +wrongMinValue=${getText(fieldName)} must be at least ${getText(min)}. +wrongIntRange=${getText(fieldName)} must be between ${getText(min)} and ${getText(max)}. + +config.hoursDelay=Delay +startDate=Start Date +hour=Hour +minute=Minute +config.subject=Subject +config.template=Template + +notifier.time=Time \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/package_it.properties b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/package_it.properties new file mode 100644 index 0000000000..61c34a0292 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/package_it.properties @@ -0,0 +1,37 @@ +label.active=Servizio Attivo +label.senderCode=Mittente +label.mailAttrName=Nome Campo e-mail del Profilo Utente +label.hoursDelay=Delay (ore) +label.startDate=Data Partenza +label.startDatePattern=gg/mm/aaaa +label.hour=Ora +label.minute=Minuto +label.html=Invia in formato Html +label.subject=Oggetto +label.header=Header +label.template=Template Singolo Contenuto +label.footer=Footer + +label.schedulerSettings=Impostazioni Scheduler +label.mailSettings=Impostazioni Mail +notifier.generalSettings=Impostazioni Generali + +title.workflowNotifierManagement=Workflow - Notificatore Passaggio Stato Contenuti +title.workflowNotifierManagement.config=Configurazione Notificatore + +note.workflowNotifierManagement.savedConfirm=Salvataggio Configurazione Notificatore eseguito + +#LABELS IN USO AL VALIDATORE +requiredstring=${getText(fieldName)} è richiesto. +wrongDate=${getText(fieldName)} non rispetta il formato [gg/mm/aaaa]. +wrongMinValue=${getText(fieldName)} deve essere almeno ${getText(min)}. +wrongIntRange=${getText(fieldName)} deve essere compreso tra ${getText(min)} e ${getText(max)}. + +config.hoursDelay=Delay +startDate=Data Partenza +hour=Ora +minute=Minuto +config.subject=Oggetto +config.template=Template +notifier.time=Ora + diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/tags/ContentStepTag.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/tags/ContentStepTag.java new file mode 100644 index 0000000000..4d6d2de848 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/tags/ContentStepTag.java @@ -0,0 +1,92 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.tags; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.util.ApsWebApplicationUtils; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jacms.apsadmin.content.ContentActionConstants; +import com.agiletec.plugins.jpcontentworkflow.apsadmin.content.helper.IContentWorkFlowActionHelper; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.jsp.JspException; +import org.apache.struts2.util.ValueStack; +import org.apache.struts2.views.jsp.StrutsBodyTagSupport; + +/** + * @author E.Santoboni + */ +public class ContentStepTag extends StrutsBodyTagSupport { + + @Override + public int doStartTag() throws JspException { + IContentWorkFlowActionHelper helper = (IContentWorkFlowActionHelper) ApsWebApplicationUtils.getBean("jpcontentworkflowContentActionHelper", pageContext); + try { + Content content = this.getContent(); + String stepCode = null; + if (this.isNextStep()) { + stepCode = helper.getNextStep(content.getStatus(), content.getTypeCode()); + } else { + stepCode = helper.getPreviousStep(content.getStatus(), content.getTypeCode()); + } + if (null != this.getVar()) { + ValueStack stack = this.getStack(); + stack.getContext().put(this.getVar(), stepCode); + stack.setValue("#attr['" + this.getVar() + "']", stepCode, false); + } else { + this.pageContext.getOut().print(stepCode); + } + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "doStartTag"); + throw new JspException("Error on doStartTag", t); + } + return super.doStartTag(); + } + + private Content getContent() { + ServletRequest request = this.pageContext.getRequest(); + String contentOnSessionMarker = (String) request.getAttribute("contentOnSessionMarker"); + if (null == contentOnSessionMarker || contentOnSessionMarker.trim().length() == 0) { + contentOnSessionMarker = request.getParameter("contentOnSessionMarker"); + } + String sessionParamName = ContentActionConstants.SESSION_PARAM_NAME_CURRENT_CONTENT_PREXIX + contentOnSessionMarker; + return (Content) this.pageContext.getSession().getAttribute(sessionParamName); + } + + public boolean isNextStep() { + return _nextStep; + } + public void setNextStep(boolean nextStep) { + this._nextStep = nextStep; + } + + protected String getVar() { + return _var; + } + public void setVar(String var) { + this._var = var; + } + + private boolean _nextStep; + + private String _var; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/tags/ContentStepsTag.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/tags/ContentStepsTag.java new file mode 100644 index 0000000000..d5ecbeb021 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/tags/ContentStepsTag.java @@ -0,0 +1,79 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.tags; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.util.ApsWebApplicationUtils; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jacms.apsadmin.content.ContentActionConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.IContentWorkflowManager; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Step; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.jsp.JspException; +import java.util.List; +import org.apache.struts2.views.jsp.StrutsBodyTagSupport; + +public class ContentStepsTag extends StrutsBodyTagSupport { + + @Override + public int doStartTag() throws JspException { + IContentWorkflowManager manager = (IContentWorkflowManager) ApsWebApplicationUtils.getBean(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_MANAGER, pageContext); + try { + Content content = this.getContent(); + + List steps = manager.getSteps(content.getTypeCode()); + + ValueStack stack = this.getStack(); + stack.getContext().put(this.getVar(), steps); + stack.setValue("#attr['" + this.getVar() + "']", steps, false); + + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "doStartTag"); + throw new JspException("Error on doStartTag", t); + } + return super.doStartTag(); + } + + private Content getContent() { + ServletRequest request = this.pageContext.getRequest(); + String contentOnSessionMarker = (String) request.getAttribute("contentOnSessionMarker"); + if (null == contentOnSessionMarker || contentOnSessionMarker.trim().length() == 0) { + contentOnSessionMarker = request.getParameter("contentOnSessionMarker"); + } + String sessionParamName = ContentActionConstants.SESSION_PARAM_NAME_CURRENT_CONTENT_PREXIX + contentOnSessionMarker; + return (Content) this.pageContext.getSession().getAttribute(sessionParamName); + } + + + protected String getVar() { + return _var; + } + public void setVar(String var) { + this._var = var; + } + + + private String _var; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/AbstractWorkflowAction.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/AbstractWorkflowAction.java new file mode 100644 index 0000000000..fbcc94d66c --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/AbstractWorkflowAction.java @@ -0,0 +1,70 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.workflow; + +import com.agiletec.aps.system.services.role.IRoleManager; +import com.agiletec.aps.system.services.role.Role; +import com.agiletec.apsadmin.system.BaseAction; +import com.agiletec.plugins.jacms.aps.system.services.content.IContentManager; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.IContentWorkflowManager; +import java.util.Collections; +import java.util.List; +import org.apache.commons.beanutils.BeanComparator; + +/** + * @author E.Santoboni + */ +public abstract class AbstractWorkflowAction extends BaseAction { + + public List getRoles() { + List roles = this.getRoleManager().getRoles(); + BeanComparator c = new BeanComparator("description"); + Collections.sort(roles, c); + return roles; + } + + protected IContentManager getContentManager() { + return _contentManager; + } + public void setContentManager(IContentManager contentManager) { + this._contentManager = contentManager; + } + + protected IContentWorkflowManager getWorkflowManager() { + return _workflowManager; + } + public void setWorkflowManager(IContentWorkflowManager workflowManager) { + this._workflowManager = workflowManager; + } + + protected IRoleManager getRoleManager() { + return _roleManager; + } + public void setRoleManager(IRoleManager roleManager) { + this._roleManager = roleManager; + } + + private IContentManager _contentManager; + private IContentWorkflowManager _workflowManager; + private IRoleManager _roleManager; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/WorkflowListAction.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/WorkflowListAction.java new file mode 100644 index 0000000000..722031f0f3 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/WorkflowListAction.java @@ -0,0 +1,68 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.workflow; + +import java.util.List; + +import com.agiletec.aps.system.services.role.Role; +import com.agiletec.plugins.jacms.aps.system.services.content.model.SmallContentType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author E.Santoboni + */ +public class WorkflowListAction extends AbstractWorkflowAction { + + private static final Logger _logger = LoggerFactory.getLogger(WorkflowListAction.class); + + public String saveRoles() { + try { + List types = this.getContentTypes(); + for (int i = 0; i < types.size(); i++) { + SmallContentType smallContentType = types.get(i); + String roleNameParam = this.getRequest().getParameter(smallContentType.getCode() + "_authority"); + String roleName = (null != this.getRoleManager().getRole(roleNameParam)) ? roleNameParam : null; + this.getWorkflowManager().updateRole(smallContentType.getCode(), roleName); + } + this.addActionMessage(this.getText("jpcontentworkflow.config.updated")); + } catch (Throwable t) { + _logger.error("error in saveRoles", t); + return FAILURE; + } + return SUCCESS; + } + + public List getContentTypes() { + return this.getContentManager().getSmallContentTypes(); + } + + public Role getRole(String typeCode) { + Role role = null; + String roleName = this.getWorkflowManager().getRole(typeCode); + if (roleName != null) { + role = this.getRoleManager().getRole(roleName); + } + return role; + } + +} diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/WorkflowStepAction.java b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/WorkflowStepAction.java new file mode 100644 index 0000000000..aafe462476 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/WorkflowStepAction.java @@ -0,0 +1,361 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.workflow; + +import com.agiletec.aps.system.ApsSystemUtils; +import com.agiletec.aps.system.services.role.Role; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jacms.aps.system.services.content.model.SmallContentType; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Step; +import jakarta.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.apache.commons.lang3.StringUtils; + +/** + * @author E.Santoboni + */ +public class WorkflowStepAction extends AbstractWorkflowAction { + + public static final String MOVEMENT_UP_CODE = "UP"; + public static final String MOVEMENT_DOWN_CODE = "DOWN"; + + @Override + public void validate() { + super.validate(); + this.updateSteps(); + this.checkSteps(); + } + + protected void checkSteps() { + List usedSteps = this.getWorkflowManager().searchUsedSteps(this.getTypeCode()); + usedSteps.remove(Content.STATUS_NEW); + usedSteps.remove(Content.STATUS_DRAFT); + usedSteps.remove(Content.STATUS_READY); + usedSteps.remove(Content.STATUS_PUBLIC); + List steps = this.getSteps(); + for (Step step : steps) { + usedSteps.remove(step.getCode()); + String descr = step.getDescr(); + if (descr == null || descr.trim().length() == 0) { + String[] args = {step.getCode()}; + this.addFieldError("descr", this.getText("error.saveSteps.requiredDescr", args)); + } + String roleName = step.getRole(); + if (roleName != null && roleName.length() > 0) { + if (this.getRoleManager().getRole(roleName) == null) { + String[] args = {roleName}; + this.addFieldError("descr", this.getText("error.save.unknowRole", args)); + } + } + } + for (String stepCode : usedSteps) { + String[] args = {stepCode}; + this.addActionError(this.getText("error.saveSteps.removeUsedStep", args)); + } + } + + public String edit() { + try { + String typeCode = this.getTypeCode(); + List steps = this.getWorkflowManager().getSteps(typeCode); + this.setSteps(steps); + this.updateStepCodes(); + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "edit"); + return FAILURE; + } + return SUCCESS; + } + + public String addStep() { + try { + this.updateSteps(); + Step step = this.createNewStep(); + if (this.validateNewStep(step)) { + this.getSteps().add(step); + String stepCodes = this.getStepCodes() + "," + step.getCode(); + this.setStepCodes(stepCodes); + } + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "addStep"); + return FAILURE; + } + return SUCCESS; + } + + public String moveStep() { + try { + this.updateSteps(); + this.moveStepElement(); + this.updateStepCodes(); + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "moveStep"); + return FAILURE; + } + return SUCCESS; + } + + public String removeStep() { + try { + this.updateSteps(); + String code = this.getStepCode(); + if (code != null && code.length() > 0) { + List usedSteps = this.getWorkflowManager().searchUsedSteps(this.getTypeCode()); + if (usedSteps.contains(code)) { + String[] args = {code}; + this.addActionError(this.getText("error.saveSteps.removeUsedStep", args)); + return INPUT; + } + Iterator stepsIter = this.getSteps().iterator(); + for (int i = 0; stepsIter.hasNext(); i++) { + Step step = stepsIter.next(); + if (code.equals(step.getCode())) { + this.getSteps().remove(i); + this.updateStepCodes(); + break; + } + } + } + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "removeStep"); + return FAILURE; + } + return SUCCESS; + } + + public String save() { + try { + this.updateSteps(); + String typeCode = this.getTypeCode(); + List steps = this.getSteps(); + this.getWorkflowManager().updateSteps(typeCode, steps); + } catch (Throwable t) { + ApsSystemUtils.logThrowable(t, this, "save"); + return FAILURE; + } + return SUCCESS; + } + + protected boolean validateNewStep(Step step) { + boolean validated = true; + String code = step.getCode(); + String descr = step.getDescr(); + if (code == null || (code = code.trim()).length() == 0) { + this.addFieldError("code", this.getText("error.newStep.requiredCode")); + validated = false; + } else if (code.trim().length() > 12) { + this.addFieldError("code", this.getText("error.newStep.wrongMaxLength")); + validated = false; + } else if (this.getExtractedStepCodes().contains(code)) { + this.addFieldError("code", this.getText("error.newStep.duplicatedCode")); + validated = false; + } + if (StringUtils.isEmpty(descr)) { + this.addFieldError("descr", this.getText("error.newStep.requiredDescr")); + validated = false; + } + return validated; + } + + protected Step createNewStep() { + Step step = new Step(); + if (null != this.getStepCode()) { + step.setCode(this.getStepCode().trim()); + } + if (null != this.getStepDescr()) { + step.setDescr(this.getStepDescr().trim()); + } + if (null != this.getStepRole()) { + step.setRole(this.getStepRole().trim()); + } + return step; + } + + protected void updateSteps() { + List steps = new ArrayList(); + List codes = this.extractStepCodes(); + HttpServletRequest request = this.getRequest(); + Iterator codesIter = codes.iterator(); + while (codesIter.hasNext()) { + Step step = new Step(); + String code = codesIter.next(); + step.setCode(code); + String descr = request.getParameter(code + "_SEP_descr"); + step.setDescr(descr); + String role = request.getParameter(code + "_SEP_role"); + step.setRole(role); + steps.add(step); + } + this.setSteps(steps); + this.updateStepCodes(); + } + + protected List extractStepCodes() { + List extractedCodes = new ArrayList(); + String stepCodes = this.getStepCodes(); + if (stepCodes != null) { + String[] array = stepCodes.trim().split(","); + for (int i = 0; i < array.length; i++) { + String code = array[i].trim(); + if (code.length() > 0) { + if (!extractedCodes.contains(code)) { + extractedCodes.add(code); + } + } + } + } + this.setExtractedStepCodes(extractedCodes); + return extractedCodes; + } + + protected void updateStepCodes() { + StringBuilder stepCodes = new StringBuilder(); + Iterator stepsIter = this.getSteps().iterator(); + while (stepsIter.hasNext()) { + Step step = stepsIter.next(); + stepCodes.append(step.getCode()); + if (stepsIter.hasNext()) { + stepCodes.append(","); + } + } + this.setStepCodes(stepCodes.toString()); + } + + protected void moveStepElement() { + List steps = this.getSteps(); + int elements = steps.size(); + int elementIndex = this.getElementIndex(); + String movement = this.getMovement(); + boolean isUp = MOVEMENT_UP_CODE.equals(movement); + boolean isDown = MOVEMENT_DOWN_CODE.equals(movement); + if ((isUp || isDown) && elementIndex >= 0 && elementIndex < elements) { + if (isUp && elementIndex > 0) { + Step step = steps.remove(elementIndex); + steps.add(elementIndex - 1, step); + } + if (isDown && elementIndex < elements - 1) { + Step step = steps.remove(elementIndex); + steps.add(elementIndex + 1, step); + } + } + } + + public SmallContentType getContentType() { + if (this._contentType == null) { + String typeCode = this.getTypeCode(); + this._contentType = (SmallContentType) this.getContentManager().getSmallContentTypesMap().get(typeCode); + } + return this._contentType; + } + + public String getTypeCode() { + return _typeCode; + } + + public void setTypeCode(String typeCode) { + this._typeCode = typeCode; + } + + public String getStepCodes() { + return _stepCodes; + } + + public void setStepCodes(String stepCodes) { + this._stepCodes = stepCodes; + } + + protected List getExtractedStepCodes() { + return _extractedStepCodes; + } + + protected void setExtractedStepCodes(List extractedStepCodes) { + this._extractedStepCodes = extractedStepCodes; + } + + public List getSteps() { + return _steps; + } + + protected void setSteps(List steps) { + this._steps = steps; + } + + public String getStepCode() { + return _stepCode; + } + + public void setStepCode(String stepCode) { + this._stepCode = stepCode; + } + + public String getStepDescr() { + return _stepDescr; + } + + public void setStepDescr(String stepDescr) { + this._stepDescr = stepDescr; + } + + public String getStepRole() { + return _stepRole; + } + + public void setStepRole(String stepRole) { + this._stepRole = stepRole; + } + + public int getElementIndex() { + return _elementIndex; + } + + public void setElementIndex(int elementIndex) { + this._elementIndex = elementIndex; + } + + public String getMovement() { + return _movement; + } + + public void setMovement(String movement) { + this._movement = movement; + } + + private String _typeCode; + private String _stepCodes; + private List _extractedStepCodes; + private List _steps; + private List _roles; + + /* Parametri Nuovo Step*/ + private String _stepCode; + private String _stepDescr; + private String _stepRole; + + /* Parametri Nuovo Step*/ + private int _elementIndex; + private String _movement; + + private SmallContentType _contentType; + +} diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/package_en.properties b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/package_en.properties new file mode 100644 index 0000000000..a2dc461a7d --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/package_en.properties @@ -0,0 +1,35 @@ +label.contentType=Content Type +label.code=Code +label.descr=Description +label.role=Role + +label.editMainRole=Edit Main Role +label.editRole=Edit Role +label.editSteps=Edit Workflow +label.addStep=Add Step +label.mainRole=Main Role +label.updateMainRoles=Update Main Roles + +title.workflowManagement.editRole=Edit Role +title.workflowManagement.editSteps=Manage Steps + +title.newStep=New Step +note.stepList.empty=There aren''t defined itermediate steps between statues. +note.stepList.caption=Intermediate steps between Draft,Ready and Approved statues. + +jpcontentworkflow.config.updated=Role configuration updated + +#VALIDATION LABELS +error.newStep.requiredCode=Code is required. +error.newStep.duplicatedCode=Code is duplicated. +error.newStep.requiredDescr=Description is required. +error.saveSteps.requiredDescr=Description for step {0} is required. +error.save.unknowRole=Not existant role {0}. +error.saveSteps.removeUsedStep=Step {0} is used and can''t be removed. +error.newStep.wrongMaxLength=The step code exceed the length of 12 characters. + +note.workingOn=You are working on +content.types.list=Content Types + +name.contentStatus.DRAFT=Draft +name.contentStatus.READY=Ready diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/package_it.properties b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/package_it.properties new file mode 100644 index 0000000000..4d0b8065ec --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/package_it.properties @@ -0,0 +1,35 @@ +label.contentType=Tipo di Contenuto +label.code=Codice +label.descr=Descrizione +label.role=Ruolo + +label.editMainRole=Modifica Ruolo Principale +label.editRole=Modifica Ruolo +label.editSteps=Modifica Workflow +label.addStep=Aggiungi Step +label.mainRole=Ruolo Principale +label.updateMainRoles=Aggiorna Ruoli + +title.workflowManagement.editRole=Modifica Ruolo +title.workflowManagement.editSteps=Gestione Step + +title.newStep=Nuovo Step +note.stepList.empty=Nessuno Step intermedio definito tra lo stato Bozza e quelli Pronto e Approvato +note.stepList.caption=Step intermedi tra lo stato Bozza e quelli Pronto e Approvato + +jpcontentworkflow.config.updated=Configurazione ruoli aggiornata + +#VALIDATION LABELS +error.newStep.requiredCode=Codice è richiesto. +error.newStep.duplicatedCode=Codice è duplicato. +error.newStep.requiredDescr=Descrizione è richiesta. +error.saveSteps.requiredDescr=Descrizione per lo step {0} è richiesta. +error.save.unknowRole=Ruolo {0} inesistente. +error.saveSteps.removeUsedStep=Lo step {0} è utilizzato e non può essere rimosso. +error.newStep.wrongMaxLength=Il codice dello step eccede la lunghezza massima di 12 caratteri. + +note.workingOn=Stai lavorando su +content.types.list=Tipi di Contenuto + +name.contentStatus.DRAFT=Bozza +name.contentStatus.READY=Pronto diff --git a/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/workflow.xml b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/workflow.xml new file mode 100644 index 0000000000..c13426afd5 --- /dev/null +++ b/contentworkflow-plugin/src/main/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/workflow.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + admin.jpcontentworkflow.workflow.list + superuser + + + + admin.jpcontentworkflow.workflow.list + admin.jpcontentworkflow.workflow.list + superuser + + + + admin.jpcontentworkflow.workflow.entrySteps + superuser + + + + admin.jpcontentworkflow.workflow.entrySteps + superuser + + + + admin.jpcontentworkflow.workflow.entrySteps + admin.jpcontentworkflow.workflow.entrySteps + superuser + + + + admin.jpcontentworkflow.workflow.entrySteps + superuser + + + + admin.jpcontentworkflow.workflow.entrySteps + list + superuser + + + + + + + diff --git a/contentworkflow-plugin/src/main/resources/api/plugins/jpcontentworkflow/aps/placeholder.txt b/contentworkflow-plugin/src/main/resources/api/plugins/jpcontentworkflow/aps/placeholder.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/contentworkflow-plugin/src/main/resources/component/plugins/jpcontentworkflow/component.xml b/contentworkflow-plugin/src/main/resources/component/plugins/jpcontentworkflow/component.xml new file mode 100644 index 0000000000..a45f53527a --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/component/plugins/jpcontentworkflow/component.xml @@ -0,0 +1,25 @@ + + + jpcontentworkflow + Content Workflow + + ${project.artifactId} + ${project.groupId} + ${project.version} + + + jacms + jpmail + + + + + jpcontentworkflow_events
    +
    +
    + + + + +
    +
    diff --git a/contentworkflow-plugin/src/main/resources/entando-struts-plugin.xml b/contentworkflow-plugin/src/main/resources/entando-struts-plugin.xml new file mode 100644 index 0000000000..39dbf8d01b --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/entando-struts-plugin.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/changeSetPort.xml b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/changeSetPort.xml new file mode 100644 index 0000000000..eec19d4cc3 --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/changeSetPort.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/changeSetServ.xml b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/changeSetServ.xml new file mode 100644 index 0000000000..ee560bd700 --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/changeSetServ.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/20240415000000_jpcontentworkflow_dataPort_production.xml b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/20240415000000_jpcontentworkflow_dataPort_production.xml new file mode 100644 index 0000000000..181a344c3f --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/20240415000000_jpcontentworkflow_dataPort_production.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/20240415000000_jpcontentworkflow_dataPort_test.xml b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/20240415000000_jpcontentworkflow_dataPort_test.xml new file mode 100644 index 0000000000..86813524bc --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/20240415000000_jpcontentworkflow_dataPort_test.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/production/config.xml b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/production/config.xml new file mode 100644 index 0000000000..6a5dca43a2 --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/production/config.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/production/notifier_config.xml b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/production/notifier_config.xml new file mode 100644 index 0000000000..acdbd1a0db --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/production/notifier_config.xml @@ -0,0 +1,23 @@ + + + + + + + + + +
    + + + + +

    Your Company

    subject

    +
    +

    Ciao ${user}, di seguito l''elenco dei contenuti per cui รจ richiesto il tuo intervento +

      ]]>
    + +
    ]]>
    +
    +
    \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/test/config.xml b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/test/config.xml new file mode 100644 index 0000000000..bae30bb117 --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/test/config.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/test/notifier_config.xml b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/test/notifier_config.xml new file mode 100644 index 0000000000..6b70c0db71 --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/port/clob/test/notifier_config.xml @@ -0,0 +1,14 @@ + + + + + + + + + +
    these contents require your attention

    ]]>
    + +
    End (footer)]]>
    +
    +
    \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/serv/20240415000000_jpcontentworkflow_dataServ_test.xml b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/serv/20240415000000_jpcontentworkflow_dataServ_test.xml new file mode 100644 index 0000000000..523076f2ac --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/serv/20240415000000_jpcontentworkflow_dataServ_test.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/serv/20240415000000_jpcontentworkflow_schemaServ.xml b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/serv/20240415000000_jpcontentworkflow_schemaServ.xml new file mode 100644 index 0000000000..f8d07e9777 --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/liquibase/jpcontentworkflow/serv/20240415000000_jpcontentworkflow_schemaServ.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/aps/managers/cmsManagersConfig.xml b/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/aps/managers/cmsManagersConfig.xml new file mode 100644 index 0000000000..1a025f2f07 --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/aps/managers/cmsManagersConfig.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/aps/managers/jpcontentworkflowManagers.xml b/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/aps/managers/jpcontentworkflowManagers.xml new file mode 100644 index 0000000000..f9ddb928ee --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/aps/managers/jpcontentworkflowManagers.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/content/contentActionsConfig.xml b/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/content/contentActionsConfig.xml new file mode 100644 index 0000000000..19eff5837a --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/content/contentActionsConfig.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/content/entryContent-actions-jack.jsp + jacms.entryContent.actions + 5 + + + diff --git a/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/notifier/notifierActionsConfig.xml b/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/notifier/notifierActionsConfig.xml new file mode 100644 index 0000000000..6992139e42 --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/notifier/notifierActionsConfig.xml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/workflow/workflowActionsConfig.xml b/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/workflow/workflowActionsConfig.xml new file mode 100644 index 0000000000..d08d524acf --- /dev/null +++ b/contentworkflow-plugin/src/main/resources/spring/plugins/jpcontentworkflow/apsadmin/workflow/workflowActionsConfig.xml @@ -0,0 +1,31 @@ + + + + + + /WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/common/template/subMenu.jsp + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/tld/plugins/jpcontentworkflow/jpcontentworkflow-apsadmin-core.tld b/contentworkflow-plugin/src/main/tld/plugins/jpcontentworkflow/jpcontentworkflow-apsadmin-core.tld new file mode 100644 index 0000000000..57c271a1d7 --- /dev/null +++ b/contentworkflow-plugin/src/main/tld/plugins/jpcontentworkflow/jpcontentworkflow-apsadmin-core.tld @@ -0,0 +1,45 @@ + + + + "jpcontentworkflow-apsadmin-core tag library" + 2.2 + wpcw + /jpcontentworkflow-apsadmin-core + + + + + + contentStep + com.agiletec.plugins.jpcontentworkflow.apsadmin.tags.ContentStepTag + empty + + + nextStep + true + true + + + + var + false + true + + + + + + + + contentSteps + com.agiletec.plugins.jpcontentworkflow.apsadmin.tags.ContentStepsTag + empty + + + var + true + true + + + + diff --git a/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jpcontentworkflow-tiles.xml b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jpcontentworkflow-tiles.xml new file mode 100644 index 0000000000..cff5c9a3fb --- /dev/null +++ b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jpcontentworkflow-tiles.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/common/template/extraresources/notifier_extraResources.jsp b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/common/template/extraresources/notifier_extraResources.jsp new file mode 100644 index 0000000000..df2ff08f50 --- /dev/null +++ b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/common/template/extraresources/notifier_extraResources.jsp @@ -0,0 +1,3 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + diff --git a/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/common/template/subMenu.jsp b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/common/template/subMenu.jsp new file mode 100644 index 0000000000..dd16738eb1 --- /dev/null +++ b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/common/template/subMenu.jsp @@ -0,0 +1,11 @@ +<%@ taglib prefix="s" uri="/struts-tags"%> +<%@ taglib prefix="wpsa" uri="/apsadmin-core"%> +<%@ taglib prefix="wp" uri="/aps-core"%> + +
  • + "> + + + +
  • +
    diff --git a/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/content/entryContent-actions-jack.jsp b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/content/entryContent-actions-jack.jsp new file mode 100644 index 0000000000..409c70a2fd --- /dev/null +++ b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/content/entryContent-actions-jack.jsp @@ -0,0 +1,103 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> +<%@ taglib prefix="wp" uri="/aps-core" %> +<%@ taglib prefix="wpcw" uri="/jpcontentworkflow-apsadmin-core" %> +<%@ taglib prefix="wpsa" uri="/apsadmin-core" %> +<%@ taglib prefix="wpsf" uri="/apsadmin-form" %> + +
    +
    + + : + +
    +
    + + +
    + +
    +
    + + +
    +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    diff --git a/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/notifier/config.jsp b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/notifier/config.jsp new file mode 100644 index 0000000000..ec9bfa2442 --- /dev/null +++ b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/notifier/config.jsp @@ -0,0 +1,233 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> +<%@ taglib uri="/apsadmin-core" prefix="wpsa" %> +<%@ taglib uri="/apsadmin-form" prefix="wpsf" %> +<%@ taglib uri="/aps-core" prefix="wp" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + +
    +
    + + +
    + + + +
      + + +
    • +
      +
      +
    +
    +
    + +
    + + + +
      + +
    • +
      +
    +
    +
    + +
    + + + +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + + + +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + + + + + +  :  + + + + + +
    +
    +
    +
    +
    + +
    + + + +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    +
    diff --git a/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/notifier/configSavedConfirm.jsp b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/notifier/configSavedConfirm.jsp new file mode 100644 index 0000000000..564fffa82d --- /dev/null +++ b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/notifier/configSavedConfirm.jsp @@ -0,0 +1,35 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="s" uri="/struts-tags"%> +<%@ taglib prefix="wp" uri="/aps-core"%> +<%@ taglib prefix="wpsa" uri="/apsadmin-core"%> +<%@ taglib prefix="wpsf" uri="/apsadmin-form"%> + +

    + +

    +
    +
    +
    +
    +
    + + +
    diff --git a/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/workflow/entrySteps.jsp b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/workflow/entrySteps.jsp new file mode 100644 index 0000000000..791e198ad1 --- /dev/null +++ b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/workflow/entrySteps.jsp @@ -0,0 +1,230 @@ +<%@ taglib prefix="s" uri="/struts-tags"%> +<%@ taglib uri="/aps-core" prefix="wp"%> +<%@ taglib uri="/apsadmin-core" prefix="wpsa"%> +<%@ taglib uri="/apsadmin-form" prefix="wpsf"%> + +

    + +

    +
    +
    +
    +
    +
    + + +
    + + + +
      + + +
    • + +
    • +
      +
      +
    +
    +
    + +
    + + + +
      + +
    • +
      +
    +
    +
    +

    + + : + + +

    +

    + + +

    + +

    + +

    +
    + <%-- --%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    DRAFTnonenone
    + + + + + + + +
    READYnonenone
    +
    + + + +
    + + +
    + +
    + +
    +
    + + +
    + +
    + +
    +
    + +
    +
    + + + + + + + +
    +
    + +
    +
    +
    +
    + + + +
    +
    +
    +
    diff --git a/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/workflow/workflowList.jsp b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/workflow/workflowList.jsp new file mode 100644 index 0000000000..87801a3b0f --- /dev/null +++ b/contentworkflow-plugin/src/main/webapp/WEB-INF/plugins/jpcontentworkflow/apsadmin/jsp/workflow/workflowList.jsp @@ -0,0 +1,109 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> +<%@ taglib prefix="wp" uri="/aps-core" %> +<%@ taglib prefix="wpsf" uri="/apsadmin-form" %> + + +
    +
    + + + +
    + +
      + +
    • +
      +
    +
    +
    + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    +
    +
    +
    + + + +
    +
    +
    +
    diff --git a/contentworkflow-plugin/src/test/config/conf/contextTestParams.properties b/contentworkflow-plugin/src/test/config/conf/contextTestParams.properties new file mode 100644 index 0000000000..3b786d9cff --- /dev/null +++ b/contentworkflow-plugin/src/test/config/conf/contextTestParams.properties @@ -0,0 +1,46 @@ +######## Datasources -- start + +# IMPORTANT # +# any other datasource has to have parameters likes the follows: +# jdbc..beanName +# jdbc..driverClassName +# jdbc..url +# jdbc..username +# jdbc..password +# DS_TEST_CODE is the unique code of the datasource + +jdbc.portDb.beanName=portDataSource +jdbc.portDb.driverClassName=${test.database.driver} +jdbc.portDb.url=${test.database.port.url} +jdbc.portDb.username=${test.database.username} +jdbc.portDb.password=${test.database.password} + +jdbc.servDb.beanName=servDataSource +jdbc.servDb.driverClassName=${test.database.driver} +jdbc.servDb.url=${test.database.serv.url} +jdbc.servDb.username=${test.database.username} +jdbc.servDb.password=${test.database.password} + +######## Datasources -- end + +logActiveFileOutput=false +logName=${project.build.directory}/test/${project.artifactId} +logFileRotatePattern=${project.build.directory}/test/${project.artifactId}_logs/${project.artifactId}-%i.log.gz +logLevel=ERROR +# Maximum allowed file size for single log file in Bytes (10485760 = 10 Mb) +logFileSize=1048576 +logFilesCount=10 + +configVersion=test + +applicationBaseURL=/Entando/ +resourceRootURL=/Entando/resources/ +protectedResourceRootURL=/Entando/protected/ + +resourceDiskRootFolder=target/test/resources/ +protectedResourceDiskRootFolder=target/test/protected/ + +indexDiskRootFolder=target/test/indexdir + +portDataSourceClassName=${test.database.driver} +servDataSourceClassName=${test.database.driver} diff --git a/contentworkflow-plugin/src/test/config/conf/systemParams.properties b/contentworkflow-plugin/src/test/config/conf/systemParams.properties new file mode 100644 index 0000000000..09e56b5616 --- /dev/null +++ b/contentworkflow-plugin/src/test/config/conf/systemParams.properties @@ -0,0 +1,80 @@ +##---------------------- +## General configurations +version=5.0.0-SNAPSHOT + +# Maximum allowed file size for the upload (10485760 = 10 Mb). Default value for "apsFileUpload" Interceptors +file.upload.maxSize=10485760 +appBuilderIntegrationEnabled=false +appBuilderBaseURL=http://localhost:3000 +##---------------------- +## ImageMagick configuration + +# set this parameter to true if imagemagick is installed on the system and you need to use it +imagemagick.enabled=false +# +#parameters to use ImageMagick on Unix like system +imagemagick.windows=false +imagemagick.path=null + +profile.portDataSourceClassName=${profile.database.driverClassName} +profile.servDataSourceClassName=${profile.database.driverClassName} + +# +#parameters to use in windows system +#attention on the imagemagick.path parameter +#in windows system a command convert exist this is the reason why it's necessary to +#declare to full path where ImageMagick is installed +#windows config example +# +#imagemagick.windows=true +#imagemagick.path=C:\\Programmi\\ImageMagick-6.6.3-Q16 + +##---------------------- +## Portal Page configuration + +page.mimeType.allowedValues=application/json,application/xhtml+xml,application/xml,text/html,text/xml +page.charset.allowedValues=iso-8859-1,utf-8 + +# showlets.viewer deprecated +showlets.viewer=content_viewer +widgets.viewer=content_viewer +# showlets.stock deprecated +showlets.stock=formAction,login_form,messages_system,entando_apis +widgets.stock=formAction,login_form,messages_system,entando_apis + +widgets.internalServlet=formAction + +##---------------------- +## Security configuration + +csp.header.enabled=${CSP_HEADER_ENABLED:true} +csp.header.extraConfig='strict-dynamic' https: 'self'; object-src 'none'; base-uri 'self' + +##---------------------- +## CMS configuration + +jacms.frontend.userfilter.dateFormat=yyyy-MM-dd + +jacms.publicContentSearcher.forceCaseInsensitiveLikeSearch=false +jacms.workContentSearcher.forceCaseInsensitiveLikeSearch=false + +jacms.imageResource.allowedExtensions=jpg,jpeg,png +jacms.attachResource.allowedExtensions=pdf,xls,doc,ppt,txt,rtf,sxw,sxc,odt,ods,odp,tar,gz,zip,rar,flv,swf,avi,wmv,ogg,mp3,wav,ogm,mov,iso,nrg,docx,docm,xlsx,xlsm,xlsb,pptx,pptm,ppsx,ppsm,sldx,sldm +jacms.imgMetadata.ignoreKeys=Blue TRC,Red TRC,Green TRC + +##---------------------- +## Database configuration + +## migration strategy - disabled|auto|generate_sql +db.migration.strategy=auto + +db.restore.enabled=true + +# Database Environment - test|develop|production +db.environment=test + +##---------------------- +## OAuth2 configuration + +oauth2.accessToken.validitySeconds=3600 +oauth2.refreshToken.validitySeconds=86400 diff --git a/contentworkflow-plugin/src/test/config/entando_logo.jpg b/contentworkflow-plugin/src/test/config/entando_logo.jpg new file mode 100644 index 0000000000..e69de29bb2 diff --git a/contentworkflow-plugin/src/test/config/resources/cms/documents/text_resource.txt b/contentworkflow-plugin/src/test/config/resources/cms/documents/text_resource.txt new file mode 100644 index 0000000000..68e6c2ef76 --- /dev/null +++ b/contentworkflow-plugin/src/test/config/resources/cms/documents/text_resource.txt @@ -0,0 +1,2 @@ +Entando is a low-code, component-based platform that opens the door for accelerated development of cloud Modern Applications that leverage the full potential of continuous integration/continuous delivery, devops, containers, and microservices. Entando unleashes developer creativity, freeing them to work lighter, faster and more efficiently. +Modern enterprises that want to emerge or survive are faced with the challenge of generating new product and service ideas, and getting them on the market faster than competitors. The Entando platform provides the tools to rapid prototyping applications, accelerate time to market, scale applications as the business grows, and deliver a unified and device-agnostic experience to end users across the enterprise. diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/TestContentManager.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/TestContentManager.java new file mode 100644 index 0000000000..72194f9d6c --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/TestContentManager.java @@ -0,0 +1,87 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.content; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.agiletec.aps.BaseTestCase; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.aps.system.services.group.Group; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.WorkflowSearchFilter; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + */ +public class TestContentManager extends BaseTestCase { + + @BeforeEach + protected void init() throws Exception { + super.setUp(); + try { + this._contentSearcherManager = (IContentSearcherManager) this.getService(JpcontentworkflowSystemConstants.CONTENT_SEARCHER_MANAGER); + } catch (Throwable t) { + throw new Exception(t); + } + } + + @Test + public void testLoadContentsId() throws ApsSystemException { + List workflowFilters = new ArrayList(); + + Collection userGroupCodes = new ArrayList(); + userGroupCodes.add(Group.FREE_GROUP_NAME); + List contentsId = this._contentSearcherManager.loadContentsId(workflowFilters, null, null, userGroupCodes); + assertEquals(0, contentsId.size()); + + WorkflowSearchFilter f1 = new WorkflowSearchFilter(); + f1.setTypeCode("ART"); + f1.addAllowedStep(Content.STATUS_READY); + workflowFilters.add(f1); + contentsId = this._contentSearcherManager.loadContentsId(workflowFilters, null, null, userGroupCodes); + assertEquals(1, contentsId.size()); + + WorkflowSearchFilter f2 = new WorkflowSearchFilter(); + f2.setTypeCode("RAH"); + f2.addAllowedStep(Content.STATUS_DRAFT); + workflowFilters.add(f2); + contentsId = this._contentSearcherManager.loadContentsId(workflowFilters, null, null, userGroupCodes); + assertEquals(2, contentsId.size()); + + WorkflowSearchFilter f3 = new WorkflowSearchFilter(); + f3.setTypeCode("EVN"); + f3.addAllowedStep(Content.STATUS_READY); + workflowFilters.add(f3); + contentsId = this._contentSearcherManager.loadContentsId(workflowFilters, null, null, userGroupCodes); + assertEquals(2, contentsId.size()); + } + + private IContentSearcherManager _contentSearcherManager = null; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/TestContentSearcherDAO.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/TestContentSearcherDAO.java new file mode 100644 index 0000000000..17b3533eef --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/content/TestContentSearcherDAO.java @@ -0,0 +1,86 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.content; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.sql.DataSource; + +import com.agiletec.aps.BaseTestCase; +import com.agiletec.aps.system.services.group.Group; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.WorkflowSearchFilter; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + */ +public class TestContentSearcherDAO extends BaseTestCase { + + @BeforeEach + public void init() throws Exception { + super.setUp(); + DataSource dataSource = (DataSource) this.getApplicationContext().getBean("portDataSource"); + ContentSearcherDAO searcherDAO = new ContentSearcherDAO(); + searcherDAO.setDataSource(dataSource); + this._searcherDAO = searcherDAO; + } + + @Test + public void testLoadContentsId() { + List workflowFilters = new ArrayList(); + + Collection userGroupCodes = new ArrayList(); + userGroupCodes.add(Group.FREE_GROUP_NAME); + List contentsId = this._searcherDAO.loadContentsId(workflowFilters, null, null, userGroupCodes); + assertEquals(0, contentsId.size()); + + WorkflowSearchFilter f1 = new WorkflowSearchFilter(); + f1.setTypeCode("ART"); + f1.addAllowedStep(Content.STATUS_READY); + workflowFilters.add(f1); + contentsId = this._searcherDAO.loadContentsId(workflowFilters, null, null, userGroupCodes); + assertEquals(1, contentsId.size()); + + WorkflowSearchFilter f2 = new WorkflowSearchFilter(); + f2.setTypeCode("RAH"); + f2.addAllowedStep(Content.STATUS_DRAFT); + workflowFilters.add(f2); + contentsId = this._searcherDAO.loadContentsId(workflowFilters, null, null, userGroupCodes); + assertEquals(2, contentsId.size()); + + WorkflowSearchFilter f3 = new WorkflowSearchFilter(); + f3.setTypeCode("EVN"); + f3.addAllowedStep(Content.STATUS_READY); + workflowFilters.add(f3); + contentsId = this._searcherDAO.loadContentsId(workflowFilters, null, null, userGroupCodes); + assertEquals(2, contentsId.size()); + } + + private IContentSearcherDAO _searcherDAO; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/TestWorkflowNotifierDAO.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/TestWorkflowNotifierDAO.java new file mode 100644 index 0000000000..ba47d570c6 --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/TestWorkflowNotifierDAO.java @@ -0,0 +1,126 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import javax.sql.DataSource; + +import com.agiletec.aps.BaseTestCase; +import com.agiletec.plugins.jpcontentworkflow.util.WorkflowNotifierTestHelper; + +import com.agiletec.aps.util.DateConverter; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.ContentStatusChangedEventInfo; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + */ +public class TestWorkflowNotifierDAO extends BaseTestCase { + + @BeforeEach + protected void init() throws Exception { + super.setUp(); + DataSource dataSource = (DataSource) this.getApplicationContext().getBean("servDataSource"); + WorkflowNotifierDAO notifierDao = new WorkflowNotifierDAO(); + notifierDao.setDataSource(dataSource); + this._notifierDao = notifierDao; + + this._helper = new WorkflowNotifierTestHelper(); + this._helper.setDataSource(dataSource); + this._helper.deleteContentEvents(); // Eventi rimossi nel caso qualche altro Test esterno li abbia generati + } + + @AfterEach + protected void dispose() throws Exception { + this._helper.deleteContentEvents(); + super.tearDown(); + } + + @Test + public void testSaveContentEvent() throws Throwable { + ContentStatusChangedEventInfo statusChangedInfo = this.prepareContentEventInfo(); + try { + this._notifierDao.saveContentEvent(statusChangedInfo); + Map> statusChangedInfos = this._notifierDao.getEventsToNotify(); + assertEquals(1, statusChangedInfos.size()); + List artStatusChangedInfos = statusChangedInfos.get("ART"); + assertEquals(1, artStatusChangedInfos.size()); + ContentStatusChangedEventInfo addedStatusChangedInfo = artStatusChangedInfos.get(0); + this.compareContentEvents(statusChangedInfo, addedStatusChangedInfo); + } catch (Throwable t) { + throw t; + } + } + + @Test + public void testSignNotifiedEvents() throws Throwable { + ContentStatusChangedEventInfo event = this.prepareContentEventInfo(); + try { + assertEquals(0, this._notifierDao.getEventsToNotify().size()); + this._notifierDao.saveContentEvent(event); + assertEquals(1, this._notifierDao.getEventsToNotify().size()); + + List contentEvents = new ArrayList(); + contentEvents.add(event); + this._notifierDao.signNotifiedEvents(contentEvents); + assertEquals(0, this._helper.getEventsToNotify().size()); + assertEquals(0, this._notifierDao.getEventsToNotify().size()); + assertEquals(1, this._helper.getNotifiedEvents().size()); + } catch (Throwable t) { + throw t; + } + } + + private void compareContentEvents(ContentStatusChangedEventInfo info1, ContentStatusChangedEventInfo info2) { + assertEquals(info1.getContentId(), info2.getContentId()); + assertEquals(info1.getContentTypeCode(), info2.getContentTypeCode()); + assertEquals(info1.getContentDescr(), info2.getContentDescr()); + assertEquals(DateConverter.getFormattedDate(info1.getDate(), "dd/MM/yyyy HH:mm"), + DateConverter.getFormattedDate(info2.getDate(), "dd/MM/yyyy HH:mm")); + assertEquals(info1.getMainGroup(), info2.getMainGroup()); + assertEquals(info1.getStatus(), info2.getStatus()); + } + + private ContentStatusChangedEventInfo prepareContentEventInfo() { + ContentStatusChangedEventInfo statusChangedInfo = new ContentStatusChangedEventInfo(); + statusChangedInfo.setContentId("ART1"); + statusChangedInfo.setContentTypeCode("ART"); + statusChangedInfo.setContentDescr("contentDescr"); + statusChangedInfo.setDate(new Date()); + statusChangedInfo.setMainGroup("free"); + statusChangedInfo.setStatus(Content.STATUS_DRAFT); + return statusChangedInfo; + } + + private IWorkflowNotifierDAO _notifierDao; + private WorkflowNotifierTestHelper _helper; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/TestWorkflowNotifierManager.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/TestWorkflowNotifierManager.java new file mode 100644 index 0000000000..a14908ac60 --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/TestWorkflowNotifierManager.java @@ -0,0 +1,198 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier; + +import java.util.Date; + +import javax.sql.DataSource; + +import com.agiletec.aps.BaseTestCase; +import com.agiletec.plugins.jpcontentworkflow.util.WorkflowNotifierTestHelper; + +import com.agiletec.aps.system.SystemConstants; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.plugins.jacms.aps.system.JacmsSystemConstants; +import com.agiletec.plugins.jacms.aps.system.services.content.IContentManager; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.NotifierConfig; +import com.agiletec.plugins.jpmail.aps.services.JpmailSystemConstants; +import com.agiletec.plugins.jpmail.aps.services.mail.IMailManager; +import com.agiletec.plugins.jpmail.aps.services.mail.MailManager; +import org.entando.entando.ent.exception.EntException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + */ +public class TestWorkflowNotifierManager extends BaseTestCase { + + @BeforeEach + protected void init() throws Exception { + super.setUp(); + this._configManager = (ConfigInterface) this.getService(SystemConstants.BASE_CONFIG_MANAGER); + this._notifierManager = (IWorkflowNotifierManager) this.getService(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_MANAGER); + this._contentManager = (IContentManager) this.getService(JacmsSystemConstants.CONTENT_MANAGER); + DataSource dataSource = (DataSource) this.getApplicationContext().getBean("servDataSource"); + this._helper = new WorkflowNotifierTestHelper(); + this._helper.setDataSource(dataSource); + this._helper.deleteContentEvents(); + this.activeMailManager(false); + } + + @AfterEach + protected void dispose() throws Exception { + this._helper.deleteContentEvents(); + this.activeMailManager(true); + super.tearDown(); + } + + @Test + public void testGetNotifierConfig() throws Throwable { + NotifierConfig notifierConfig = this._notifierManager.getNotifierConfig(); + assertFalse(notifierConfig.isActive()); + assertEquals(24, notifierConfig.getHoursDelay()); + assertEquals("CODE1", notifierConfig.getSenderCode()); + //assertEquals("email", notifierConfig.getMailAttrName()); + assertFalse(notifierConfig.isHtml()); + assertEquals("[My Own Portal]: A content changed", notifierConfig.getSubject()); + assertEquals("Hi {user},
    these contents require your attention

    ", notifierConfig.getHeader()); + assertEquals("
    Content {type} - {descr} - Status {status}
    ", notifierConfig.getTemplate()); + assertEquals("
    End (footer)", notifierConfig.getFooter()); + } + + @Test + public void testSetNotifierConfig() throws Throwable { + String config = this._configManager.getConfigItem(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM); + NotifierConfig originaryNotifierConfig = this._notifierManager.getNotifierConfig(); + NotifierConfig newNotifierConfig = this.prepareNotifierConfig(); + try { + this._notifierManager.saveNotifierConfig(newNotifierConfig); + NotifierConfig updatedNotifierConfig = this._notifierManager.getNotifierConfig(); + this.compareNotifiers(newNotifierConfig, updatedNotifierConfig); + + this._notifierManager.saveNotifierConfig(originaryNotifierConfig); + updatedNotifierConfig = this._notifierManager.getNotifierConfig(); + this.compareNotifiers(originaryNotifierConfig, updatedNotifierConfig); + } catch (Throwable t) { + throw t; + } finally { + this._configManager.updateConfigItem(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM, config); + } + } + + @Test + public void testSendEMails() throws Throwable { + String config = this._configManager.getConfigItem(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM); + NotifierConfig notifierConfig = this._notifierManager.getNotifierConfig(); + try { + this.addContentStatusChangedEvent("ART1", Content.STATUS_READY); + this.addContentStatusChangedEvent("ART180", Content.STATUS_DRAFT); + this.addContentStatusChangedEvent("EVN41", Content.STATUS_READY); + super.waitNotifyingThread(); + assertEquals(0, this._helper.getEventsToNotify().size()); + assertEquals(0, this._helper.getNotifiedEvents().size()); + + notifierConfig.setActive(true); + this._notifierManager.saveNotifierConfig(notifierConfig); + + this.addContentStatusChangedEvent("ART1", Content.STATUS_DRAFT); + this.addContentStatusChangedEvent("ART180", Content.STATUS_READY); + this.addContentStatusChangedEvent("EVN41", Content.STATUS_DRAFT); + super.waitNotifyingThread(); + assertEquals(2, this._helper.getEventsToNotify().size()); + assertEquals(0, this._helper.getNotifiedEvents().size()); + + this._notifierManager.sendMails(); + super.waitNotifyingThread(); + assertEquals(0, this._helper.getEventsToNotify().size()); + assertEquals(2, this._helper.getNotifiedEvents().size()); + } catch (Throwable t) { + this.addContentStatusChangedEvent("ART1", Content.STATUS_DRAFT); + this.addContentStatusChangedEvent("ART180", Content.STATUS_READY); + this.addContentStatusChangedEvent("EVN41", Content.STATUS_DRAFT); + throw t; + } finally { + this._configManager.updateConfigItem(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM, config); + } + } + + private NotifierConfig prepareNotifierConfig() { + NotifierConfig notifierConfig = new NotifierConfig(); + + notifierConfig.setActive(true); + notifierConfig.setHoursDelay(23); + notifierConfig.setStartScheduler(new Date()); + + notifierConfig.setSenderCode("CODE2"); + //notifierConfig.setMailAttrName("eMail"); + notifierConfig.setHtml(true); + notifierConfig.setSubject("Oggetto"); + notifierConfig.setHeader("header"); + notifierConfig.setTemplate("template"); + notifierConfig.setFooter("footer"); + + return notifierConfig; + } + + private void compareNotifiers(NotifierConfig nc1, NotifierConfig nc2) { + assertEquals(nc1.isActive(), nc2.isActive()); + assertEquals(nc1.getHoursDelay(), nc2.getHoursDelay()); + long time1 = nc1.getStartScheduler().getTime()/60000; + long time2 = nc2.getStartScheduler().getTime()/60000; + assertEquals(time1, time2); + assertEquals(nc1.getSenderCode(), nc2.getSenderCode()); + //assertEquals(nc1.getMailAttrName(), nc2.getMailAttrName()); + assertEquals(nc1.isHtml(), nc2.isHtml()); + assertEquals(nc1.getSubject(), nc2.getSubject()); + assertEquals(nc1.getHeader(), nc2.getHeader()); + assertEquals(nc1.getTemplate(), nc2.getTemplate()); + assertEquals(nc1.getFooter(), nc2.getFooter()); + } + + private String addContentStatusChangedEvent(String contentId, String status) throws EntException { + Content content = this._contentManager.loadContent(contentId, false); + String currentStatus = content.getStatus(); + content.setStatus(status); + this._contentManager.saveContent(content); + return currentStatus; + } + + + private void activeMailManager(boolean active) { + IMailManager mailManager = (IMailManager) this.getService(JpmailSystemConstants.MAIL_MANAGER); + if (mailManager instanceof MailManager) { + ((MailManager) mailManager).setActive(active); + } + } + + private ConfigInterface _configManager; + private IWorkflowNotifierManager _notifierManager; + private IContentManager _contentManager; + private WorkflowNotifierTestHelper _helper; + +} diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/parse/TestWorkflowNotifierDOM.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/parse/TestWorkflowNotifierDOM.java new file mode 100644 index 0000000000..907b563d10 --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/notifier/parse/TestWorkflowNotifierDOM.java @@ -0,0 +1,110 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.parse; + +import java.util.Date; + +import com.agiletec.aps.BaseTestCase; +import com.agiletec.aps.system.SystemConstants; +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.NotifierConfig; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + */ +public class TestWorkflowNotifierDOM extends BaseTestCase { + + @BeforeEach + protected void init() throws Exception { + super.setUp(); + this._configManager = (ConfigInterface) this.getService(SystemConstants.BASE_CONFIG_MANAGER); + } + + @Test + public void testExtractConfig() throws Throwable { + WorkflowNotifierDOM configDOM = new WorkflowNotifierDOM(); + String xml = this._configManager.getConfigItem(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM); + NotifierConfig notifierConfig = configDOM.extractConfig(xml); + assertFalse(notifierConfig.isActive()); + assertEquals(24, notifierConfig.getHoursDelay()); + assertTrue(notifierConfig.getStartScheduler().getTime()<(new Date()).getTime()); + assertEquals("CODE1", notifierConfig.getSenderCode()); + //assertEquals("email", notifierConfig.getMailAttrName()); + assertFalse(notifierConfig.isHtml()); + assertEquals("[My Own Portal]: A content changed", notifierConfig.getSubject()); + assertEquals("Hi {user},
    these contents require your attention

    ", notifierConfig.getHeader()); + assertEquals("
    Content {type} - {descr} - Status {status}
    ", notifierConfig.getTemplate()); + assertEquals("
    End (footer)", notifierConfig.getFooter()); + } + + @Test + public void testSetNotifierConfig() throws Throwable { + WorkflowNotifierDOM configDOM = new WorkflowNotifierDOM(); + + NotifierConfig newConfig = this.prepareNotifierConfig(); + String xml = configDOM.createConfigXml(newConfig); + + NotifierConfig extractedConfig = configDOM.extractConfig(xml); + this.compareNotifiers(newConfig, extractedConfig); + } + + private NotifierConfig prepareNotifierConfig() { + NotifierConfig notifierConfig = new NotifierConfig(); + + notifierConfig.setActive(true); + notifierConfig.setHoursDelay(23); + notifierConfig.setStartScheduler(new Date()); + + notifierConfig.setSenderCode("CODE2"); + //notifierConfig.setMailAttrName("eMail"); + notifierConfig.setHtml(true); + notifierConfig.setSubject("Oggetto"); + notifierConfig.setHeader("header"); + notifierConfig.setTemplate("template"); + notifierConfig.setFooter("footer"); + + return notifierConfig; + } + + private void compareNotifiers(NotifierConfig nc1, NotifierConfig nc2) { + assertEquals(nc1.isActive(), nc2.isActive()); + assertEquals(nc1.getHoursDelay(), nc2.getHoursDelay()); + long time1 = nc1.getStartScheduler().getTime()/60000; + long time2 = nc2.getStartScheduler().getTime()/60000; + assertEquals(time1, time2); + assertEquals(nc1.getSenderCode(), nc2.getSenderCode()); + //assertEquals(nc1.getMailAttrName(), nc2.getMailAttrName()); + assertEquals(nc1.isHtml(), nc2.isHtml()); + assertEquals(nc1.getSubject(), nc2.getSubject()); + assertEquals(nc1.getHeader(), nc2.getHeader()); + assertEquals(nc1.getTemplate(), nc2.getTemplate()); + assertEquals(nc1.getFooter(), nc2.getFooter()); + } + + private ConfigInterface _configManager; + +} diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/TestContentWorkflowManager.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/TestContentWorkflowManager.java new file mode 100644 index 0000000000..a691265da2 --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/aps/system/services/workflow/TestContentWorkflowManager.java @@ -0,0 +1,165 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow; + +import java.util.ArrayList; +import java.util.List; + +import com.agiletec.aps.BaseTestCase; +import com.agiletec.plugins.jpcontentworkflow.util.WorkflowTestHelper; + +import com.agiletec.aps.system.SystemConstants; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Step; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Workflow; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + */ +public class TestContentWorkflowManager extends BaseTestCase { + + @BeforeEach + protected void init() throws Exception { + super.setUp(); + ContentWorkflowManager workflowManager = (ContentWorkflowManager) this.getService(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_MANAGER); + this._workflowManager = workflowManager; + this._configManager = (ConfigInterface) this.getService(SystemConstants.BASE_CONFIG_MANAGER); + this._helper = new WorkflowTestHelper(workflowManager, this._configManager); + this._helper.setWorkflowConfig(); + } + + @AfterEach + protected void dispose() throws Exception { + this._helper.resetWorkflowConfig(); + super.tearDown(); + } + + @Test + public void testGetWorkflow() { + Workflow workflow = this._workflowManager.getWorkflow("ART"); + assertEquals("ART", workflow.getTypeCode()); + assertNull(workflow.getRole()); + List steps = workflow.getSteps(); + assertEquals(3, steps.size()); + Step step1 = workflow.getStep("step1"); + assertEquals("step1", step1.getCode()); + assertEquals("Step 1", step1.getDescr()); + assertEquals("pageManager", step1.getRole()); + + Step step2 = workflow.getStep("step2"); + assertEquals("step2", step2.getCode()); + assertEquals("Step 2", step2.getDescr()); + assertNull(step2.getRole()); + + Step step3 = workflow.getStep("step3"); + assertEquals("step3", step3.getCode()); + assertEquals("Step 3", step3.getDescr()); + assertEquals("supervisor", step3.getRole()); + + Workflow workflow2 = this._workflowManager.getWorkflow("EVN"); + assertEquals("pageManager", workflow2.getRole()); + assertEquals(0, workflow2.getSteps().size()); + + assertNotNull(this._workflowManager.getWorkflow("RAH")); + } + + @Test + public void testGetRole() { + assertNull(this._workflowManager.getRole("ART")); + + String role = this._workflowManager.getRole("EVN"); + assertEquals("pageManager", role); + } + + @Test + public void testUpdateRole() throws ApsSystemException { + String typeCode = "ART"; + String xml = this._configManager.getConfigItem(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_CONFIG_ITEM); + assertNull(this._workflowManager.getRole(typeCode)); + + this._workflowManager.updateRole(typeCode, "pageManager"); + String updatedXml = this._configManager.getConfigItem(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_CONFIG_ITEM); + assertEquals("pageManager", this._workflowManager.getRole(typeCode)); + assertFalse(xml.equals(updatedXml)); + + this._workflowManager.updateRole(typeCode, null); + assertNull(this._workflowManager.getRole(typeCode)); + } + + @Test + public void testGetSteps() { + List steps = this._workflowManager.getSteps("ART"); + assertEquals(3, steps.size()); + + steps = this._workflowManager.getSteps("EVN"); + assertEquals(0, steps.size()); + + steps = this._workflowManager.getSteps("RAH"); + assertEquals(0, steps.size()); + } + + @Test + public void testUpdateSteps() throws ApsSystemException { + String typeCode = "EVN"; + String xml = this._configManager.getConfigItem(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_CONFIG_ITEM); + assertEquals(0, this._workflowManager.getSteps(typeCode).size()); + + List steps = this.createSteps(); + this._workflowManager.updateSteps(typeCode, steps); + String updatedXml = this._configManager.getConfigItem(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_CONFIG_ITEM); + assertEquals(2, this._workflowManager.getSteps(typeCode).size()); + assertFalse(xml.equals(updatedXml)); + + this._workflowManager.updateSteps(typeCode, new ArrayList()); + assertEquals(0, this._workflowManager.getSteps(typeCode).size()); + } + + private List createSteps() { + List steps = new ArrayList(); + + Step step1 = new Step(); + step1.setCode("step_1"); + step1.setDescr("step_1 descr"); + step1.setRole("role1"); + steps.add(step1); + + Step step2 = new Step(); + step2.setCode("step_2"); + step2.setDescr("step_2 descr"); + step2.setRole("role2"); + steps.add(step2); + + return steps; + } + + private IContentWorkflowManager _workflowManager; + private ConfigInterface _configManager; + private WorkflowTestHelper _helper; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestContentAction.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestContentAction.java new file mode 100644 index 0000000000..22225fa99f --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestContentAction.java @@ -0,0 +1,195 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.content; + +import com.agiletec.ConfigTestUtils; +import java.util.HashMap; +import java.util.Map; + +import javax.sql.DataSource; + +import com.agiletec.plugins.jpcontentworkflow.util.WorkflowNotifierTestHelper; +import com.agiletec.plugins.jpcontentworkflow.util.WorkflowTestHelper; + +import com.agiletec.aps.system.SystemConstants; +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.aps.system.services.user.UserDetails; +import com.agiletec.apsadmin.system.ApsAdminSystemConstants; +import com.agiletec.plugins.jacms.aps.system.JacmsSystemConstants; +import com.agiletec.plugins.jacms.aps.system.services.content.IContentManager; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jacms.apsadmin.content.AbstractContentAction; +import com.agiletec.plugins.jacms.apsadmin.content.ContentActionConstants; +import com.agiletec.plugins.jacms.apsadmin.content.util.AbstractBaseTestContentAction; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.ContentWorkflowManager; +import org.apache.struts2.action.Action; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + * @author G.Cocco + */ +public class TestContentAction extends AbstractBaseTestContentAction { + + @BeforeEach + protected void init() throws Exception { + super.setUp(); + ContentWorkflowManager workflowManager = (ContentWorkflowManager) this.getService(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_MANAGER); + ConfigInterface configManager = (ConfigInterface) this.getService(SystemConstants.BASE_CONFIG_MANAGER); + DataSource portDataSource = (DataSource) this.getApplicationContext().getBean("portDataSource"); + this._helper = new WorkflowTestHelper(workflowManager, configManager, portDataSource); + + DataSource servDataSource = (DataSource) this.getApplicationContext().getBean("servDataSource"); + this._notifierHelper = new WorkflowNotifierTestHelper(); + this._notifierHelper.setDataSource(servDataSource); + + _contentManager = (IContentManager) this.getService(JacmsSystemConstants.CONTENT_MANAGER); + } + + @Test + public void testPreviousStep() throws Throwable { + this._notifierHelper.deleteContentEvents(); + this._helper.setWorkflowConfig(); + String contentId = "ART179"; + Content content = this._contentManager.loadContent(contentId, false); + assertEquals(Content.STATUS_DRAFT, content.getStatus()); + try { + Content modifiedContent = this._contentManager.loadContent(contentId, false); + modifiedContent.setStatus(Content.STATUS_READY); + this._contentManager.saveContent(modifiedContent); + + Map params = new HashMap(); + params.put("descr", content.getDescr()); + params.put("mainGroup", content.getMainGroup()); + params.put("Text:it_Titolo", "titolo"); + String result = this.executePreviousStep("admin", contentId, params); + assertEquals(Action.SUCCESS, result); + modifiedContent = this._contentManager.loadContent(contentId, false); + assertEquals("step3", modifiedContent.getStatus()); + + result = this.executePreviousStep("admin", contentId, params); + assertEquals(Action.SUCCESS, result); + modifiedContent = this._contentManager.loadContent(contentId, false); + assertEquals("step2", modifiedContent.getStatus()); + + result = this.executePreviousStep("admin", contentId, params); + assertEquals(Action.SUCCESS, result); + modifiedContent = this._contentManager.loadContent(contentId, false); + assertEquals("step1", modifiedContent.getStatus()); + + result = this.executePreviousStep("admin", contentId, params); + assertEquals(Action.SUCCESS, result); + modifiedContent = this._contentManager.loadContent(contentId, false); + assertEquals(Content.STATUS_DRAFT, modifiedContent.getStatus()); + + result = this.executePreviousStep("admin", contentId, params); + assertEquals(Action.INPUT, result); + } catch(Throwable t) { + throw t; + } finally { + this._contentManager.saveContent(content); + this._helper.resetWorkflowConfig(); + this._notifierHelper.deleteContentEvents(); + } + } + + @Test + public void testNextStep() throws Throwable { + this._notifierHelper.deleteContentEvents(); + this._helper.setWorkflowConfig(); + String contentId = "ART179"; + Content content = this._contentManager.loadContent(contentId, false); + assertEquals(Content.STATUS_DRAFT, content.getStatus()); + try { + Map params = new HashMap(); + params.put("descr", content.getDescr()); + params.put("mainGroup", content.getMainGroup()); + params.put("Text:it_Titolo", "titolo"); + String result = this.executeNextStep("admin", contentId, params); + assertEquals(Action.SUCCESS, result); + Content modifiedContent = this._contentManager.loadContent(contentId, false); + assertEquals("step1", modifiedContent.getStatus()); + + result = this.executeNextStep("admin", contentId, params); + assertEquals(Action.SUCCESS, result); + modifiedContent = this._contentManager.loadContent(contentId, false); + assertEquals("step2", modifiedContent.getStatus()); + + result = this.executeNextStep("admin", contentId, params); + assertEquals(Action.SUCCESS, result); + modifiedContent = this._contentManager.loadContent(contentId, false); + assertEquals("step3", modifiedContent.getStatus()); + + result = this.executeNextStep("admin", contentId, params); + assertEquals(Action.SUCCESS, result); + modifiedContent = this._contentManager.loadContent(contentId, false); + assertEquals(Content.STATUS_READY, modifiedContent.getStatus()); + + result = this.executeNextStep("admin", contentId, params); + assertEquals(Action.INPUT, result); + } catch(Throwable t) { + throw t; + } finally { + this._contentManager.saveContent(content); + this._helper.resetWorkflowConfig(); + this._notifierHelper.deleteContentEvents(); + } + } + + protected UserDetails getCurrentUser() { + UserDetails currentUser = (UserDetails) this.getRequest().getSession().getAttribute(SystemConstants.SESSIONPARAM_CURRENT_USER); + return currentUser; + } + + private String executePreviousStep(String currentUserName, String contentId, Map params) throws Throwable { + Content content = this._contentManager.loadContent(contentId, false); + String contentOnSessionMarker = AbstractContentAction.buildContentOnSessionMarker(content, ApsAdminSystemConstants.EDIT); + String contentOnSessionParam = ContentActionConstants.SESSION_PARAM_NAME_CURRENT_CONTENT_PREXIX + contentOnSessionMarker; + this.getRequest().getSession().setAttribute(contentOnSessionParam, content); + this.setUserOnSession(currentUserName); + this.initContentAction("/do/jacms/Content", "previousStep", contentOnSessionMarker); + this.addParameters(params); + String result = this.executeAction(); + return result; + } + + private String executeNextStep(String currentUserName, String contentId, Map params) throws Throwable { + Content content = this._contentManager.loadContent(contentId, false); + String contentOnSessionMarker = AbstractContentAction.buildContentOnSessionMarker(content, ApsAdminSystemConstants.EDIT); + String contentOnSessionParam = ContentActionConstants.SESSION_PARAM_NAME_CURRENT_CONTENT_PREXIX + contentOnSessionMarker; + this.getRequest().getSession().setAttribute(contentOnSessionParam, content); + this.setUserOnSession(currentUserName); + this.initContentAction("/do/jacms/Content", "nextStep", contentOnSessionMarker); + this.addParameters(params); + String result = this.executeAction(); + return result; + } + + private WorkflowTestHelper _helper; + private WorkflowNotifierTestHelper _notifierHelper; + private IContentManager _contentManager = null; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestContentFinderAction.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestContentFinderAction.java new file mode 100644 index 0000000000..38576ea74b --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestContentFinderAction.java @@ -0,0 +1,142 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.content; + +import com.agiletec.aps.system.SystemConstants; +import com.agiletec.aps.system.common.model.dao.SearcherDaoPaginatedResult; +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.apsadmin.ApsAdminBaseTestCase; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.ContentWorkflowManager; +import com.agiletec.plugins.jpcontentworkflow.util.WorkflowTestHelper; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.sql.DataSource; +import org.apache.struts2.action.Action; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + */ +public class TestContentFinderAction extends ApsAdminBaseTestCase { + + @BeforeEach + protected void init() throws Exception { + super.setUp(); + ContentWorkflowManager workflowManager = (ContentWorkflowManager) this.getService(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_MANAGER); + ConfigInterface configManager = (ConfigInterface) this.getService(SystemConstants.BASE_CONFIG_MANAGER); + DataSource dataSource = (DataSource) this.getApplicationContext().getBean("portDataSource"); + this._helper = new WorkflowTestHelper(workflowManager, configManager, dataSource); + } + + @Test + public void testSearch_1() throws Throwable { + try { + this._helper.setWorkflowConfig(); + this._helper.setContentStates(); + Map params = new HashMap<>(); + this.executeSearch("admin", params); + ContentFinderAction action = (ContentFinderAction) this.getAction(); + SearcherDaoPaginatedResult result = action.getPaginatedContentsId(10); + assertEquals(25, result.getCount().intValue()); + assertEquals(10, result.getList().size()); + this.executeSearch("editorCoach", params); + action = (ContentFinderAction) this.getAction(); + result = action.getPaginatedContentsId(10); + List contents = result.getList(); + assertEquals(2, result.getList().size()); + String[] contentsId = {"ART102", "ART112"}; + assertEquals(contentsId.length, contents.size()); + for (int i = 0; i < contentsId.length; i++) { + String contentId = contentsId[i]; + assertTrue(contents.contains(contentId)); + } + this.executeSearch("supervisorCoach", params); + action = (ContentFinderAction) this.getAction(); + result = action.getPaginatedContentsId(10); + assertEquals(4, result.getList().size()); + contents = result.getList(); + contentsId = new String[]{"ART102", "ART111", "ART112", "RAH101"}; + assertEquals(contentsId.length, contents.size()); + for (int i = 0; i < contentsId.length; i++) { + String contentId = contentsId[i]; + assertTrue(contents.contains(contentId)); + } + } catch (Throwable t) { + throw t; + } finally { + this._helper.resetWorkflowConfig(); + this._helper.resetContentStates(); + } + } + + @Test + public void testSearch_2() throws Throwable { + try { + this._helper.setWorkflowConfig(); + this._helper.setContentStates(); + Map params = new HashMap<>(); + this.executeSearch("admin", params); + ContentFinderAction action = (ContentFinderAction) this.getAction(); + List contents = action.getContents(); + assertEquals(25, contents.size()); + this.executeSearch("editorCoach", params); + action = (ContentFinderAction) this.getAction(); + contents = action.getContents(); + String[] contentsId = {"ART102", "ART112"}; + assertEquals(contentsId.length, contents.size()); + for (int i = 0; i < contentsId.length; i++) { + String contentId = contentsId[i]; + assertTrue(contents.contains(contentId)); + } + this.executeSearch("supervisorCoach", params); + action = (ContentFinderAction) this.getAction(); + contents = action.getContents(); + contentsId = new String[]{"ART102", "ART111", "ART112", "RAH101"}; + assertEquals(contentsId.length, contents.size()); + for (int i = 0; i < contentsId.length; i++) { + String contentId = contentsId[i]; + assertTrue(contents.contains(contentId)); + } + } catch (Throwable t) { + throw t; + } finally { + this._helper.resetWorkflowConfig(); + this._helper.resetContentStates(); + } + } + + private void executeSearch(String currentUserName, Map params) throws Throwable { + this.initAction("/do/jacms/Content", "search"); + this.setUserOnSession(currentUserName); + this.addParameters(params); + String result = this.executeAction(); + assertEquals(Action.SUCCESS, result); + } + + private WorkflowTestHelper _helper; + +} diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestIntroNewContentAction.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestIntroNewContentAction.java new file mode 100644 index 0000000000..074111b1f9 --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/content/TestIntroNewContentAction.java @@ -0,0 +1,110 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.content; + +import java.util.List; +import java.util.Map; + +import com.agiletec.apsadmin.ApsAdminBaseTestCase; +import com.agiletec.plugins.jpcontentworkflow.util.WorkflowTestHelper; + +import com.agiletec.aps.system.SystemConstants; +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jacms.aps.system.services.content.model.SmallContentType; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.ContentWorkflowManager; +import org.apache.struts2.action.Action; +import org.apache.struts2.ActionSupport; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + */ +public class TestIntroNewContentAction extends ApsAdminBaseTestCase { + + @BeforeEach + protected void init() throws Exception { + super.setUp(); + ContentWorkflowManager workflowManager = (ContentWorkflowManager) this.getService(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_MANAGER); + ConfigInterface configManager = (ConfigInterface) this.getService(SystemConstants.BASE_CONFIG_MANAGER); + this._helper = new WorkflowTestHelper(workflowManager, configManager); + this._helper.setWorkflowConfig(); + } + + @AfterEach + protected void dispose() throws Exception { + this._helper.resetWorkflowConfig(); + super.tearDown(); + } + + @Test + public void testOpenNew() throws Throwable { + String result = this.executeOpenNew("editorCoach"); + assertEquals(Action.SUCCESS, result); + JpCwIntroNewContentAction action = (JpCwIntroNewContentAction) this.getAction(); + List contentTypes = action.getContentTypes(); + assertEquals(3, contentTypes.size()); + for (int i=0; i> fieldErrors = action.getFieldErrors(); + List descrErrors = fieldErrors.get("contentTypeCode"); + assertEquals(1, descrErrors.size()); + } + + private String executeOpenNew(String currentUserName) throws Throwable { + this.initAction("/do/jacms/Content", "newJpCw"); + this.setUserOnSession(currentUserName); + return this.executeAction(); + } + + private String executeCreateNewVoid(String username, String contentType, String descr, String status, String contentMainGroup) throws Throwable { + //this.initAction("/do/jacms/Content", "createNewVoid"); + this.initAction("/do/jacms/Content", "createNewVoidJpCw"); + this.setUserOnSession(username); + this.addParameter("contentTypeCode", contentType); + this.addParameter("contentDescription", descr); + this.addParameter("contentStatus", status); + this.addParameter("contentMainGroup", contentMainGroup); + return this.executeAction(); + } + + private WorkflowTestHelper _helper; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/TestWorkflowNotifierConfigAction.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/TestWorkflowNotifierConfigAction.java new file mode 100644 index 0000000000..06d06b61f0 --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/notifier/TestWorkflowNotifierConfigAction.java @@ -0,0 +1,189 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.notifier; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.agiletec.aps.system.SystemConstants; +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.apsadmin.ApsAdminBaseTestCase; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.IWorkflowNotifierManager; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.NotifierConfig; +import org.apache.struts2.action.Action; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + */ +public class TestWorkflowNotifierConfigAction extends ApsAdminBaseTestCase { + + @BeforeEach + protected void init() throws Exception { + super.setUp(); + this._configManager = (ConfigInterface) this.getService(SystemConstants.BASE_CONFIG_MANAGER); + this._notifierManager = (IWorkflowNotifierManager) this.getService(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_MANAGER); + } + + @Test + public void testConfig() throws Throwable { + String result = this.executeConfig("supervisorCoach"); + assertEquals("userNotAllowed", result); + + result = this.executeConfig("admin"); + assertEquals(Action.SUCCESS, result); + WorkflowNotifierConfigAction action = (WorkflowNotifierConfigAction) this.getAction(); + NotifierConfig config = action.getConfig(); + assertFalse(config.isActive()); + assertEquals(24, config.getHoursDelay()); + assertEquals("CODE1", config.getSenderCode()); + //assertEquals("email", config.getMailAttrName()); + assertEquals("04/12/2008", action.getStartDate()); + assertEquals(16, action.getHour()); + assertEquals(8, action.getMinute()); + + assertFalse(config.isHtml()); + assertEquals("[My Own Portal]: A content changed", config.getSubject()); + assertEquals("Hi {user},
    these contents require your attention

    ", config.getHeader()); + assertEquals("
    Content {type} - {descr} - Status {status}
    ", config.getTemplate()); + assertEquals("
    End (footer)", config.getFooter()); + } + + @Test + public void testSaveFailure() throws Throwable { + Map params = new HashMap(); + String result = this.executeSave("supervisorCoach", params); + assertEquals("userNotAllowed", result); + + result = this.executeSave("admin", params); + assertEquals(Action.INPUT, result); + Map> fieldErrors = this.getAction().getFieldErrors(); + assertEquals(4, fieldErrors.size()); + + params.put("hour", "24"); + params.put("minute", "60"); + result = this.executeSave("admin", params); + assertEquals(Action.INPUT, result); + fieldErrors = this.getAction().getFieldErrors(); + assertEquals(6, fieldErrors.size()); + + params.put("config.hoursDelay", "24"); + params.put("hour", "23"); + params.put("minute", "59"); + result = this.executeSave("admin", params); + assertEquals(Action.INPUT, result); + fieldErrors = this.getAction().getFieldErrors(); + assertEquals(3, fieldErrors.size()); + + params.put("config.subject", ""); + params.put("config.template", ""); + result = this.executeSave("admin", params); + assertEquals(Action.INPUT, result); + fieldErrors = this.getAction().getFieldErrors(); + assertEquals(3, fieldErrors.size()); + + params.put("config.subject", "subject"); + params.put("config.template", "template"); + result = this.executeSave("admin", params); + assertEquals(Action.INPUT, result); + fieldErrors = this.getAction().getFieldErrors(); + assertEquals(1, fieldErrors.size()); + assertNotNull(fieldErrors.get("startDate")); + + params.put("startDate", "05/12/2008"); + params.put("hour", "24"); + result = this.executeSave("admin", params); + assertEquals(Action.INPUT, result); + fieldErrors = this.getAction().getFieldErrors(); + assertEquals(1, fieldErrors.size()); + assertNull(fieldErrors.get("startDate")); + assertNotNull(fieldErrors.get("hour")); + } + + @Test + public void testSave() throws Throwable { + String config = this._configManager.getConfigItem(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM); + try { + Map params = new HashMap(); + params.put("config.active", "true"); + params.put("config.senderCode", "CODE1"); + params.put("config.mailAttrName", "email"); + params.put("config.hoursDelay", "10"); + params.put("startDate", "19/11/2009"); + params.put("hour", "20"); + params.put("minute", "40"); + + params.put("config.html", "true"); + params.put("config.subject", "subject"); + params.put("config.header", "header"); + params.put("config.template", "template"); + params.put("config.footer", "footer"); + + String result = this.executeSave("admin", params); + assertEquals(Action.SUCCESS, result); + NotifierConfig updatedNotifierConfig = this._notifierManager.getNotifierConfig(); + + assertTrue(updatedNotifierConfig.isActive()); + assertEquals(10, updatedNotifierConfig.getHoursDelay()); + String startDate = DateFormatter.format(updatedNotifierConfig.getStartScheduler()); + assertEquals("19/11/2009 20:40", startDate); + assertEquals("CODE1", updatedNotifierConfig.getSenderCode()); + //assertEquals("email", updatedNotifierConfig.getMailAttrName()); + assertTrue(updatedNotifierConfig.isHtml()); + assertEquals("subject", updatedNotifierConfig.getSubject()); + assertEquals("header", updatedNotifierConfig.getHeader()); + assertEquals("template", updatedNotifierConfig.getTemplate()); + assertEquals("footer", updatedNotifierConfig.getFooter()); + } catch(Throwable t) { + throw t; + } finally { + this._configManager.updateConfigItem(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM, config); + } + } + + protected String executeConfig(String currentUserName) throws Throwable { + this.setUserOnSession(currentUserName); + this.initAction("/do/jpcontentworkflow/Notifier", "config"); + String result = this.executeAction(); + return result; + } + + protected String executeSave(String currentUserName, Map params) throws Throwable { + this.setUserOnSession(currentUserName); + this.initAction("/do/jpcontentworkflow/Notifier", "save"); + this.addParameters(params); + String result = this.executeAction(); + return result; + } + + private ConfigInterface _configManager; + private IWorkflowNotifierManager _notifierManager; + private static DateFormat DateFormatter = new SimpleDateFormat("dd/MM/yyyy HH:mm"); + +} diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/TestWorkflowListAction.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/TestWorkflowListAction.java new file mode 100644 index 0000000000..4d5bebaf49 --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/TestWorkflowListAction.java @@ -0,0 +1,119 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.workflow; + +import java.util.List; + +import com.agiletec.apsadmin.ApsAdminBaseTestCase; +import com.agiletec.plugins.jpcontentworkflow.util.WorkflowTestHelper; + +import com.agiletec.aps.system.SystemConstants; +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.apsadmin.system.BaseAction; +import com.agiletec.plugins.jacms.aps.system.services.content.model.SmallContentType; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.ContentWorkflowManager; +import org.apache.struts2.action.Action; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + */ +public class TestWorkflowListAction extends ApsAdminBaseTestCase { + + @BeforeEach + protected void init() throws Exception { + super.setUp(); + ContentWorkflowManager workflowManager = (ContentWorkflowManager) this.getService(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_MANAGER); + ConfigInterface configManager = (ConfigInterface) this.getService(SystemConstants.BASE_CONFIG_MANAGER); + this._helper = new WorkflowTestHelper(workflowManager, configManager); + this._helper.setWorkflowConfig(); + } + + @AfterEach + protected void dispose() throws Exception { + this._helper.resetWorkflowConfig(); + super.tearDown(); + } + + @Test + public void testSaveRoles() throws Throwable { + String result = this.executeList("admin"); + assertEquals(Action.SUCCESS, result); + WorkflowListAction action = (WorkflowListAction) this.getAction(); + assertNull(action.getRole("ART")); + String roleNameForEnv = action.getRole("EVN").getName(); + assertEquals("pageManager", roleNameForEnv); + + result = this.executeSaveRole("admin", "EVN", "supervisor"); + assertEquals(Action.SUCCESS, result); + action = (WorkflowListAction) this.getAction(); + assertEquals(1, action.getActionMessages().size()); + String newRoleNameForEnv = action.getRole("EVN").getName(); + assertEquals("supervisor", newRoleNameForEnv); + + result = this.executeSaveRole("admin", "EVN", "pageManager"); + assertEquals(Action.SUCCESS, result); + action = (WorkflowListAction) this.getAction(); + assertEquals(1, action.getActionMessages().size()); + String restoredRoleNameForEnv = action.getRole("EVN").getName(); + assertEquals("pageManager", restoredRoleNameForEnv); + } + + protected String executeSaveRole(String currentUserName, String typeCode, String role) throws Throwable { + this.setUserOnSession(currentUserName); + this.initAction("/do/jpcontentworkflow/Workflow", "saveRoles"); + this.addParameter(typeCode + "_authority", role); + return this.executeAction(); + } + + @Test + public void testListForAdminUser() throws Throwable { + String result = this.executeList("admin"); + assertEquals(Action.SUCCESS, result); + WorkflowListAction action = (WorkflowListAction) this.getAction(); + List contentTypes = action.getContentTypes(); + assertNotNull(contentTypes.get(0)); + assertNull(action.getRole("ART")); + assertEquals("pageManager", action.getRole("EVN").getName()); + } + + @Test + public void testListForNotAllowedUser() throws Throwable { + String result = this.executeList("editorCustomers"); + assertEquals(BaseAction.USER_NOT_ALLOWED, result); + } + + protected String executeList(String currentUserName) throws Throwable { + this.initAction("/do/jpcontentworkflow/Workflow", "list"); + this.setUserOnSession(currentUserName); + String result = this.executeAction(); + return result; + } + + private WorkflowTestHelper _helper; + +} diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/TestWorkflowStepAction.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/TestWorkflowStepAction.java new file mode 100644 index 0000000000..5cd89ff220 --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/apsadmin/workflow/TestWorkflowStepAction.java @@ -0,0 +1,324 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.apsadmin.workflow; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import com.agiletec.apsadmin.ApsAdminBaseTestCase; +import com.agiletec.plugins.jpcontentworkflow.util.WorkflowTestHelper; + +import com.agiletec.aps.system.SystemConstants; +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.plugins.jacms.aps.system.services.content.model.SmallContentType; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.ContentWorkflowManager; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.IContentWorkflowManager; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Step; +import org.apache.struts2.action.Action; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author E.Santoboni + */ +public class TestWorkflowStepAction extends ApsAdminBaseTestCase { + + @BeforeEach + protected void init() throws Exception { + super.setUp(); + ContentWorkflowManager workflowManager = (ContentWorkflowManager) this.getService(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_MANAGER); + this._workflowManager = workflowManager; + ConfigInterface configManager = (ConfigInterface) this.getService(SystemConstants.BASE_CONFIG_MANAGER); + this._helper = new WorkflowTestHelper(workflowManager, configManager); + this._helper.setWorkflowConfig(); + } + + @AfterEach + protected void dispose() throws Exception { + this._helper.resetWorkflowConfig(); + super.tearDown(); + } + + @Test + public void testEditSteps() throws Throwable { + String typeCode = "ART"; + String result = this.executeEditSteps("admin", typeCode); + assertEquals(Action.SUCCESS, result); + WorkflowStepAction action = (WorkflowStepAction) this.getAction(); + SmallContentType contentType = action.getContentType(); + assertEquals(typeCode, contentType.getCode()); + assertEquals(typeCode, action.getTypeCode()); + assertEquals(3, action.getSteps().size()); + } + + @Test + public void testMoveStep() throws Throwable { + String typeCode = "ART"; + WorkflowStepAction action = (WorkflowStepAction) this.executeSuccessfulEditSteps(typeCode); + + String result = this.executeMoveStep("admin", typeCode, WorkflowStepAction.MOVEMENT_DOWN_CODE, "0", action.getSteps()); + assertEquals(Action.SUCCESS, result); + action = (WorkflowStepAction) this.getAction(); + SmallContentType contentType = action.getContentType(); + assertEquals(typeCode, contentType.getCode()); + assertEquals(typeCode, action.getTypeCode()); + List steps = action.getSteps(); + assertEquals(3, steps.size()); + assertEquals("step2", steps.get(0).getCode()); + assertEquals("step1", steps.get(1).getCode()); + assertEquals("step3", steps.get(2).getCode()); + + result = this.executeMoveStep("admin", typeCode, WorkflowStepAction.MOVEMENT_UP_CODE, "1", steps); + assertEquals(Action.SUCCESS, result); + action = (WorkflowStepAction) this.getAction(); + steps = action.getSteps(); + assertEquals(3, steps.size()); + assertEquals("step1", steps.get(0).getCode()); + assertEquals("step2", steps.get(1).getCode()); + assertEquals("step3", steps.get(2).getCode()); + + result = this.executeMoveStep("admin", typeCode, WorkflowStepAction.MOVEMENT_UP_CODE, "0", steps); + assertEquals(Action.SUCCESS, result); + action = (WorkflowStepAction) this.getAction(); + steps = action.getSteps(); + assertEquals(3, steps.size()); + assertEquals("step1", steps.get(0).getCode()); + assertEquals("step2", steps.get(1).getCode()); + assertEquals("step3", steps.get(2).getCode()); + + result = this.executeMoveStep("admin", typeCode, WorkflowStepAction.MOVEMENT_DOWN_CODE, "2", steps); + assertEquals(Action.SUCCESS, result); + action = (WorkflowStepAction) this.getAction(); + steps = action.getSteps(); + assertEquals(3, steps.size()); + assertEquals("step1", steps.get(0).getCode()); + assertEquals("step2", steps.get(1).getCode()); + assertEquals("step3", steps.get(2).getCode()); + } + + @Test + public void testRemoveStep() throws Throwable { + String typeCode = "ART"; + WorkflowStepAction updateAction = (WorkflowStepAction) this.executeSuccessfulEditSteps(typeCode); + assertEquals(3, updateAction.getSteps().size()); + + String result = this.executeRemoveStep("admin", typeCode, "step1", updateAction.getSteps()); + assertEquals(Action.SUCCESS, result); + WorkflowStepAction action = (WorkflowStepAction) this.getAction(); + SmallContentType contentType = action.getContentType(); + assertEquals(typeCode, contentType.getCode()); + assertEquals(typeCode, action.getTypeCode()); + List steps = action.getSteps(); + assertEquals(2, steps.size()); + assertEquals("step2", steps.get(0).getCode()); + assertEquals("Step 2", steps.get(0).getDescr()); + assertEquals(null, steps.get(0).getRole()); + assertEquals("step3", steps.get(1).getCode()); + assertEquals("Step 3", steps.get(1).getDescr()); + assertEquals("supervisor", steps.get(1).getRole()); + } + + @Test + public void testAddStep() throws Throwable { + String typeCode = "ART"; + WorkflowStepAction action = (WorkflowStepAction) this.executeSuccessfulEditSteps(typeCode); + assertEquals(3, action.getSteps().size()); + + String result = this.executeAddStep("admin", typeCode, "step4", "Step 4", "supervisor", action.getSteps()); + assertEquals(Action.SUCCESS, result); + action = (WorkflowStepAction) this.getAction(); + List steps = action.getSteps(); + assertEquals(4, steps.size()); + assertEquals("step1", steps.get(0).getCode()); + assertEquals("step2", steps.get(1).getCode()); + assertEquals("step3", steps.get(2).getCode()); + Step step = steps.get(3); + assertEquals("step4", step.getCode()); + assertEquals("step4", step.getCode()); + assertEquals("Step 4", step.getDescr()); + assertEquals("supervisor", step.getRole()); + } + + @Test + public void testSave() throws Throwable { + String typeCode = "ART"; + List originarySteps = this._workflowManager.getSteps(typeCode); + List steps = this.prepareSteps(5); + + String result = this.executeSave("admin", typeCode, steps); + assertEquals(Action.SUCCESS, result); + List savedSteps = this._workflowManager.getSteps(typeCode); + this.compareSteps(steps, savedSteps); + + result = this.executeSave("admin", typeCode, originarySteps); + assertEquals(Action.SUCCESS, result); + savedSteps = this._workflowManager.getSteps(typeCode); + this.compareSteps(originarySteps, savedSteps); + } + + protected String executeEditSteps(String currentUserName, String typeCode) throws Throwable { + this.setUserOnSession(currentUserName); + this.initAction("/do/jpcontentworkflow/Workflow", "editSteps"); + if (typeCode != null) { + this.addParameter("typeCode", typeCode); + } + String result = this.executeAction(); + return result; + } + + protected Action executeSuccessfulEditSteps(String typeCode) throws Throwable { + String result = this.executeEditSteps("admin", typeCode); + assertEquals(Action.SUCCESS, result); + WorkflowStepAction action = (WorkflowStepAction) this.getAction(); + return action; + } + + protected String executeMoveStep(String currentUserName, String typeCode, String movement, String elementIndex, List steps) throws Throwable { + this.setUserOnSession(currentUserName); + this.initAction("/do/jpcontentworkflow/Workflow", "moveStep"); + if (typeCode != null) { + this.addParameter("typeCode", typeCode); + } + if (movement != null) { + this.addParameter("movement", movement); + } + if (elementIndex != null) { + this.addParameter("elementIndex", elementIndex); + } + this.addSteps(steps); + String result = this.executeAction(); + return result; + } + + protected String executeRemoveStep(String currentUserName, String typeCode, String stepCode, List steps) throws Throwable { + this.setUserOnSession(currentUserName); + this.initAction("/do/jpcontentworkflow/Workflow", "removeStep"); + if (typeCode != null) { + this.addParameter("typeCode", typeCode); + } + if (stepCode != null) { + this.addParameter("stepCode", stepCode); + } + this.addSteps(steps); + String result = this.executeAction(); + return result; + } + + protected String executeAddStep(String currentUserName, String typeCode, String stepCode, + String stepDescr, String stepRole, List steps) throws Throwable { + this.setUserOnSession(currentUserName); + this.initAction("/do/jpcontentworkflow/Workflow", "addStep"); + if (typeCode != null) { + this.addParameter("typeCode", typeCode); + } + if (stepCode != null) { + this.addParameter("stepCode", stepCode); + } + if (stepDescr != null) { + this.addParameter("stepDescr", stepDescr); + } + if (stepRole != null) { + this.addParameter("stepRole", stepRole); + } + this.addSteps(steps); + String result = this.executeAction(); + return result; + } + + protected String executeSave(String currentUserName, String typeCode, List steps) throws Throwable { + this.setUserOnSession(currentUserName); + this.initAction("/do/jpcontentworkflow/Workflow", "saveSteps"); + if (typeCode != null) { + this.addParameter("typeCode", typeCode); + } + this.addSteps(steps); + String result = this.executeAction(); + return result; + } + + protected void addSteps(List steps) { + if (steps != null) { + Iterator stepsIter = steps.iterator(); + while (stepsIter.hasNext()) { + Step step = stepsIter.next(); + String code = step.getCode(); + if (step.getDescr() != null) { + this.addParameter(code + "_SEP_descr", step.getDescr()); + } + if (step.getRole() != null) { + this.addParameter(code + "_SEP_role", step.getRole()); + } + } + String codes = this.concatCodes(steps); + this.addParameter("stepCodes", codes); + } + } + + protected String concatCodes(List steps) { + String codes = ""; + if (steps != null) { + Iterator stepsIter = steps.iterator(); + while (stepsIter.hasNext()) { + Step step = stepsIter.next(); + codes += step.getCode(); + if (stepsIter.hasNext()) { + codes += ","; + } + } + } + return codes; + } + + protected List prepareSteps(int size) { + List steps = new ArrayList(size); + for (int i = 0; i < size; i++) { + Step step = new Step(); + step.setCode("step" + i); + step.setDescr("Step " + i); + step.setRole("supervisor"); + steps.add(step); + } + return steps; + } + + protected void compareSteps(List steps1, List steps2) { + assertEquals(steps1.size(), steps2.size()); + Iterator steps1Iter = steps1.iterator(); + Iterator steps2Iter = steps2.iterator(); + while (steps1Iter.hasNext()) { + Step step1 = steps1Iter.next(); + Step step2 = steps2Iter.next(); + assertEquals(step1.getCode(), step2.getCode()); + assertEquals(step1.getDescr(), step2.getDescr()); + assertEquals(step1.getRole(), step2.getRole()); + } + } + + private IContentWorkflowManager _workflowManager; + private WorkflowTestHelper _helper; + +} diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/util/WorkflowNotifierTestHelper.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/util/WorkflowNotifierTestHelper.java new file mode 100644 index 0000000000..131ff098dc --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/util/WorkflowNotifierTestHelper.java @@ -0,0 +1,126 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.util; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.agiletec.aps.system.common.AbstractDAO; +import com.agiletec.aps.system.exception.ApsSystemException; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.ContentStatusChangedEventInfo; + +/** + * @author E.Santoboni + */ +public class WorkflowNotifierTestHelper extends AbstractDAO { + + public void deleteContentEvents() throws Exception { + Connection conn = null; + PreparedStatement stat = null; + try { + conn = this.getConnection(); + stat = conn.prepareStatement(DELETE_CONTENT_EVENTS); + stat.executeUpdate(); + } catch (Exception e) { + throw e; + } finally { + this.closeDaoResources(null, stat, conn); + } + } + + public Map> getEventsToNotify() throws ApsSystemException { + Map> eventsToNotify = new HashMap<>(); + Connection conn = null; + Statement stat = null; + ResultSet res = null; + try { + conn = this.getConnection(); + stat = conn.createStatement(); + res = stat.executeQuery(LOAD_CONTENTS_TO_BE_NOTIFY); + eventsToNotify = this.extractContentMailInfoFromResultSet(res); + } catch (Throwable t) { + this.processDaoException(t, "Errore in caricamento contenuti da notificare", "getContentsToNotify"); + } finally { + this.closeDaoResources(res, stat, conn); + } + return eventsToNotify; + } + + public Map> getNotifiedEvents() throws Throwable { + Map> eventsToNotify = new HashMap>(); + Connection conn = null; + Statement stat = null; + ResultSet res = null; + try { + conn = this.getConnection(); + stat = conn.createStatement(); + res = stat.executeQuery(LOAD_NOTIFIED_CONTENTS); + eventsToNotify = this.extractContentMailInfoFromResultSet(res); + } catch (Throwable t) { + this.processDaoException(t, "Errore in caricamento contenuti da notificare", "getContentsToNotify"); + } finally { + this.closeDaoResources(res, stat, conn); + } + return eventsToNotify; + } + + private Map> extractContentMailInfoFromResultSet(ResultSet res) throws SQLException { + Map> eventsToNotify = new HashMap>(); + while (res.next()) { + ContentStatusChangedEventInfo event = new ContentStatusChangedEventInfo(); + event.setId(res.getInt(1)); + event.setDate(res.getDate(2)); + event.setContentId(res.getString(3)); + String contentType = res.getString(4); + event.setContentTypeCode(contentType); + event.setContentDescr(res.getString(5)); + event.setMainGroup(res.getString(6)); + event.setStatus(res.getString(7)); + List contentTypeEvents = (List) eventsToNotify.get(contentType); + if (contentTypeEvents == null) { + contentTypeEvents = new ArrayList<>(); + eventsToNotify.put(contentType, contentTypeEvents); + } + contentTypeEvents.add(event); + } + return eventsToNotify; + } + + private final String LOAD_CONTENTS_TO_BE_NOTIFY = + "SELECT id, eventdate, contentid, contenttype, descr, maingroup, status " + + "FROM jpcontentworkflow_events WHERE notified = 0"; + + private final String LOAD_NOTIFIED_CONTENTS = + "SELECT id, eventdate, contentid, contenttype, descr, maingroup, status " + + "FROM jpcontentworkflow_events WHERE notified = 1 "; + + private final String DELETE_CONTENT_EVENTS = + "DELETE FROM jpcontentworkflow_events"; + +} diff --git a/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/util/WorkflowTestHelper.java b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/util/WorkflowTestHelper.java new file mode 100644 index 0000000000..c542f1b019 --- /dev/null +++ b/contentworkflow-plugin/src/test/java/com/agiletec/plugins/jpcontentworkflow/util/WorkflowTestHelper.java @@ -0,0 +1,117 @@ +/* + * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.agiletec.plugins.jpcontentworkflow.util; + +import java.sql.Connection; +import java.sql.Statement; + +import javax.sql.DataSource; + +import com.agiletec.aps.system.services.baseconfig.ConfigInterface; +import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; +import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants; +import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.ContentWorkflowManager; + +/** + * @author E.Santoboni + */ +public class WorkflowTestHelper { + + public WorkflowTestHelper(ContentWorkflowManager workflowManager, ConfigInterface configManager) { + this(workflowManager, configManager, null); + } + + public WorkflowTestHelper(ContentWorkflowManager workflowManager, ConfigInterface configManager, DataSource dataSource) { + this._workflowManager = workflowManager; + this._configManager = configManager; + this._dataSource = dataSource; + } + + public void setWorkflowConfig() throws Exception { + this.updateConfig(SET_CONFIG); + } + + public void resetWorkflowConfig() throws Exception { + this.updateConfig(RESET_CONFIG); + this.updateConfig(RESET_CONFIG); + } + + public void setContentStates() throws Exception { + this.executeQuery(SET_STATES_1); + this.executeQuery(SET_STATES_2); + this.executeQuery(SET_STATES_3); + this.executeQuery(SET_STATES_4); + } + + public void resetContentStates() throws Exception { + this.executeQuery(RESET_STATES_1); + this.executeQuery(RESET_STATES_2); + } + + private void executeQuery(String query) throws Exception { + Connection conn = this._dataSource.getConnection(); + Statement stat = conn.createStatement(); + stat.execute(query); + stat.close(); + conn.close(); + } + + private void updateConfig(String config) throws Exception { + this._configManager.updateConfigItem(JpcontentworkflowSystemConstants.CONTENT_WORKFLOW_CONFIG_ITEM, config); + this._workflowManager.init(); + } + + private static final String SET_STATES_1 = + "UPDATE contents SET status = 'step1' WHERE contentid = 'ART104'"; + private static final String SET_STATES_2 = + "UPDATE contents SET status = 'step3' WHERE contentid = 'ART111'"; + private static final String SET_STATES_3 = + "UPDATE contents SET status = 'step2' WHERE contentid = 'ART102'"; + private static final String SET_STATES_4 = + "UPDATE contents SET status = '" + Content.STATUS_READY + "' WHERE contentid = 'RAH101' "; + + private static final String RESET_STATES_1 = + "UPDATE contents SET status = '" + Content.STATUS_DRAFT + "' WHERE " + + "contentid = 'ART102' OR contentid = 'ART104' OR contentid = 'RAH101'"; + + private static final String RESET_STATES_2 = + "UPDATE contents SET status = '" + Content.STATUS_READY + "' WHERE " + + "contentid = 'ART111'"; + + private static final String SET_CONFIG = + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + private static final String RESET_CONFIG = + ""; + + private ContentWorkflowManager _workflowManager; + private ConfigInterface _configManager; + private DataSource _dataSource; + +} \ No newline at end of file diff --git a/contentworkflow-plugin/src/test/resources/spring/propertyPlaceholder.xml b/contentworkflow-plugin/src/test/resources/spring/propertyPlaceholder.xml new file mode 100644 index 0000000000..6244066d90 --- /dev/null +++ b/contentworkflow-plugin/src/test/resources/spring/propertyPlaceholder.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/engine/src/main/java/org/entando/entando/aps/util/UrlUtils.java b/engine/src/main/java/org/entando/entando/aps/util/UrlUtils.java index 565ebe7d22..1ed36d4725 100644 --- a/engine/src/main/java/org/entando/entando/aps/util/UrlUtils.java +++ b/engine/src/main/java/org/entando/entando/aps/util/UrlUtils.java @@ -13,9 +13,10 @@ */ package org.entando.entando.aps.util; +import com.agiletec.aps.system.ApsSystemUtils.ApsDeepDebug; import com.google.common.net.HttpHeaders; -import java.io.File; +import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; @@ -24,9 +25,9 @@ import java.util.List; import java.util.Optional; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.owasp.encoder.Encode; @@ -44,6 +45,8 @@ public final class UrlUtils { public static final String HTTPS_SCHEME = "https"; private static final String PATH_SEPARATOR = "/"; + public static final String FF_RELATIVE_COMPOSE_URL = System.getenv("ENTANDO_FF_RELATIVE_COMPOSE_URL"); + private UrlUtils(){} public static boolean urlContains(String baseUrl, String targetUrl, boolean baseIncludesBase) { @@ -78,6 +81,55 @@ private static String normalizePathForComparison(@Nullable String path) { return (path.endsWith(PATH_SEPARATOR)) ? path : path + PATH_SEPARATOR; } + public static String determineFullFrontendURL(HttpServletRequest req) { + String base = determineFrontendURL(req); + String query = req.getQueryString(); + return base + ((query != null) ? "?" + query : ""); + } + + /** + * Returns the actual URL fetched by the browser, without the query part. + *
    +     * The term "FrontendURL" refers to the URL fetched by the browser,
    +     * which may or may not be aligned with the data (e.g. HOST header)
    +     * received the server when reverse proxies are in the way.
    +     * This function in fact assists in the proper generation of links
    +     * and redirect locations.
    +     * 
    + */ + + public static String determineFrontendURL(HttpServletRequest req) { + URL url = determineFrontendUrlObject(req); + String path = req.getRequestURI(); + return url.getProtocol() + "://" + + url.getHost() + + ((url.getPort() != -1) ? ":" + url.getPort() : "") + + ((path != null) ? path : ""); + } + + public static String determineFrontendServerName(HttpServletRequest request) { + return determineFrontendUrlObject(request).getHost(); + } + + /** + * Returns a URL object that stores information about the frontendURL + * (see determineFrontendURL) + */ + public static URL determineFrontendUrlObject(HttpServletRequest request) { + String host, scheme = request.getScheme(); + Optional port; + + host = getHostFromXHeader(request).orElse(request.getServerName()); + scheme = getProtoFromXHeader(request).orElse(scheme); + port = Optional.of(getPortFromXHeader(request).orElse(request.getServerPort())); + + if (Boolean.parseBoolean(System.getenv(ENTANDO_APP_USE_TLS))) { + scheme = HTTPS_SCHEME; + } + + return generateUrl(scheme, host, port, request); + } + public static String fetchScheme(HttpServletRequest request){ return getProtoFromEnv().filter(UrlUtils::isHttps) .orElseGet(() -> getProtoFromXHeader(request).filter(UrlUtils::isHttps).orElse(request.getScheme())); @@ -203,7 +255,11 @@ private static URI getUri(String url) { public static URL composeBaseUrl(HttpServletRequest request){ String reqScheme = UrlUtils.fetchScheme(request); - String serverName = UrlUtils.fetchServer(request); + + String serverName = (StringUtils.isBlank(FF_RELATIVE_COMPOSE_URL) || !FF_RELATIVE_COMPOSE_URL.equalsIgnoreCase("false")) + ? UrlUtils.determineFrontendServerName(request) + : UrlUtils.fetchServer(request); + Optional port = UrlUtils.fetchPort(request); return generateUrl(reqScheme, serverName, port, request); @@ -286,4 +342,9 @@ public URI build() { } } + public static void sendRedirect(HttpServletResponse response, String url) throws IOException { + ApsDeepDebug.print("ALL-REDIRECTS:SEND", "", url); + //response.sendRedirect(url); + response.sendRedirect(response.encodeRedirectURL(url)); + } } diff --git a/engine/src/main/java/org/entando/entando/web/system/SystemController.java b/engine/src/main/java/org/entando/entando/web/system/SystemController.java index 9a580ae95b..9004c84025 100644 --- a/engine/src/main/java/org/entando/entando/web/system/SystemController.java +++ b/engine/src/main/java/org/entando/entando/web/system/SystemController.java @@ -27,12 +27,17 @@ import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; @RestController @RequestMapping(value = "/system") public class SystemController { - static final String CONTENT_SCHEDULER_CODE="jpcontentscheduler"; + static final HashMap CMS_PLUGINS = new HashMap<>(Map.of( + "jpcontentscheduler", "contentSchedulerPluginInstalled", + "jpcontentworkflow", "contentWorkFlowPluginInstalled" + )); + @Autowired private IComponentManager componentManager; @@ -41,10 +46,10 @@ public class SystemController { @GetMapping(value = "/report", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity>> getReport() { - Map report = new HashMap<>(); - - boolean componentInstalled = componentManager.isComponentInstalled(CONTENT_SCHEDULER_CODE); - report.put("contentSchedulerPluginInstalled", componentInstalled); + Map report = + CMS_PLUGINS.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getValue, + k -> componentManager.isComponentInstalled(k.getKey()))); return new ResponseEntity<>(new SimpleRestResponse<>(report), HttpStatus.OK); } diff --git a/mail-plugin/src/main/java/com/agiletec/plugins/jpmail/apsadmin/mail/mailConfig.xml b/mail-plugin/src/main/java/com/agiletec/plugins/jpmail/apsadmin/mail/mailConfig.xml index 8e20b3464c..d52f7089f1 100644 --- a/mail-plugin/src/main/java/com/agiletec/plugins/jpmail/apsadmin/mail/mailConfig.xml +++ b/mail-plugin/src/main/java/com/agiletec/plugins/jpmail/apsadmin/mail/mailConfig.xml @@ -57,7 +57,7 @@ admin.jpmail.MailConfig.entrySender - viewSenders + viewSenders superuser @@ -69,7 +69,7 @@ viewSenders - viewSenders + viewSenders superuser diff --git a/pom.xml b/pom.xml index 15887d86f5..54a142dc2c 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,7 @@ seo-plugin versioning-plugin contentscheduler-plugin + contentworkflow-plugin solr-plugin webapp diff --git a/seo-plugin/src/main/java/org/entando/entando/plugins/jpseo/apsadmin/portal/page.xml b/seo-plugin/src/main/java/org/entando/entando/plugins/jpseo/apsadmin/portal/page.xml index ee696d73d2..3d73c2ef9f 100644 --- a/seo-plugin/src/main/java/org/entando/entando/plugins/jpseo/apsadmin/portal/page.xml +++ b/seo-plugin/src/main/java/org/entando/entando/plugins/jpseo/apsadmin/portal/page.xml @@ -8,7 +8,7 @@ - + /do/Page systemParams diff --git a/solr-plugin/src/main/java/org/entando/entando/plugins/jpsolr/apsadmin/config/solr.xml b/solr-plugin/src/main/java/org/entando/entando/plugins/jpsolr/apsadmin/config/solr.xml index 536f9d4667..96ced07fb9 100644 --- a/solr-plugin/src/main/java/org/entando/entando/plugins/jpsolr/apsadmin/config/solr.xml +++ b/solr-plugin/src/main/java/org/entando/entando/plugins/jpsolr/apsadmin/config/solr.xml @@ -22,7 +22,7 @@ - config + config superuser diff --git a/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/config/config.xml b/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/config/config.xml index ffa4555c32..fbfc3b9212 100644 --- a/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/config/config.xml +++ b/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/config/config.xml @@ -16,7 +16,7 @@ - systemParams + systemParams superuser diff --git a/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/resource/resource.xml b/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/resource/resource.xml index 0cb1db7427..68e3c09316 100644 --- a/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/resource/resource.xml +++ b/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/resource/resource.xml @@ -36,7 +36,7 @@ - + list ${resourceTypeCode} @@ -44,7 +44,7 @@ - + list ${resourceTypeCode} diff --git a/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/versioning/versioning.xml b/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/versioning/versioning.xml index d5bb9ed215..8d7db604d5 100644 --- a/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/versioning/versioning.xml +++ b/versioning-plugin/src/main/java/com/agiletec/plugins/jpversioning/apsadmin/versioning/versioning.xml @@ -29,7 +29,7 @@ - + history ${backId} ${contentId} @@ -49,7 +49,7 @@ - + /do/jacms/Content entryContent ${contentOnSessionMarker} diff --git a/webapp/pom.xml b/webapp/pom.xml index b145f6d23e..20eedf6efa 100644 --- a/webapp/pom.xml +++ b/webapp/pom.xml @@ -384,6 +384,40 @@ + + contentworkflow + + + org.entando.entando.plugins + entando-plugin-jpcontentworkflow + ${project.version} + + + + + + maven-resources-plugin + + + copy-contentworkflow-resources + prepare-package + + copy-resources + + + ${basedir}/target/${project.build.finalName} + + + ${basedir}/../contentworkflow-plugin/src/main/webapp + + + + + + + + + build-ootb-widgets