From edc4510b5962c01bff0656774bdecac590263bde Mon Sep 17 00:00:00 2001 From: Matt Rajkowski Date: Sun, 22 Mar 2026 15:24:56 -0400 Subject: [PATCH 1/2] Sets policy values --- .../simisinc/platform/ApplicationInfo.java | 2 +- .../application/json/JsonCommand.java | 2 +- .../widgets/admin/PermissionGroupsWidget.java | 45 +++ .../admin/cms/SubFolderFormWidget.java | 24 +- .../widgets/cms/BlogsListJsonService.java | 41 +- .../widgets/cms/BlogsPostsJsonService.java | 29 +- .../cms/CalendarsEventsJsonService.java | 28 +- .../widgets/cms/CalendarsListJsonService.java | 44 +-- .../widgets/cms/ContentGetJsonService.java | 51 +-- .../widgets/cms/ContentListAjax.java | 27 +- .../widgets/cms/ContentListJsonService.java | 59 +-- .../cms/ContentPreviewJsonService.java | 47 +-- .../cms/ContentPublishJsonService.java | 55 +-- .../cms/ContentSaveDraftJsonService.java | 51 +-- .../widgets/cms/DocumentAnalyticsAjax.java | 19 +- .../widgets/cms/DocumentContentAjax.java | 28 +- .../widgets/cms/DocumentCreateFolderAjax.java | 21 +- .../cms/DocumentCreateSubfolderAjax.java | 28 +- .../widgets/cms/DocumentDeleteFolderAjax.java | 28 +- .../cms/DocumentFileAnalyticsAjax.java | 16 +- .../widgets/cms/DocumentFileListAjax.java | 16 +- .../widgets/cms/DocumentFileVersionsAjax.java | 16 +- .../widgets/cms/DocumentLibraryAjax.java | 16 +- .../widgets/cms/DocumentSubfoldersAjax.java | 16 +- .../widgets/cms/DocumentUserGroupsAjax.java | 16 +- .../widgets/cms/FolderDetailsAjax.java | 25 +- .../cms/FolderGroupDeleteJsonService.java | 17 +- .../cms/FolderGroupSaveJsonService.java | 17 +- .../widgets/cms/FolderGroupsListAjax.java | 25 +- .../cms/FolderGuestAccessSaveJsonService.java | 28 +- .../widgets/cms/FolderSaveAjax.java | 32 +- .../widgets/cms/ImageContentAjax.java | 24 +- .../widgets/cms/ImageDeleteAjax.java | 28 +- .../widgets/cms/ImageLibraryAjax.java | 18 +- .../widgets/cms/ImageMetadataAjax.java | 28 +- .../widgets/cms/ImageScaleDownAjax.java | 27 +- .../widgets/cms/ImageThumbnailAjax.java | 24 +- .../widgets/cms/ImageUploadAjax.java | 49 +-- .../widgets/cms/ImageVersionDeleteAjax.java | 35 +- .../widgets/cms/ImageVersionRevertAjax.java | 28 +- .../widgets/cms/ImageVersionsAjax.java | 20 +- .../cms/PageAddToHierarchyJsonService.java | 51 +-- .../widgets/cms/PageChildrenJsonService.java | 47 +-- .../cms/PageContentBlocksJsonService.java | 55 +-- .../PageRemoveFromHierarchyJsonService.java | 46 +-- .../widgets/cms/PageReorderJsonService.java | 71 ++-- .../widgets/cms/PrototypeWidget.java | 4 +- .../widgets/cms/SaveStylesheetAjax.java | 43 +-- .../widgets/cms/SaveWebPageAjax.java | 51 +-- .../widgets/cms/SaveWebPageInfoAjax.java | 73 ++-- .../cms/SitemapCreateItemJsonService.java | 51 +-- .../cms/SitemapCreateTabJsonService.java | 43 +-- .../cms/SitemapDeleteItemJsonService.java | 48 +-- .../cms/SitemapDeleteTabJsonService.java | 52 +-- .../cms/SitemapReorderItemJsonService.java | 49 +-- .../cms/SitemapReorderTabJsonService.java | 49 +-- .../cms/SitemapStructureJsonService.java | 41 +- .../cms/SitemapUpdateItemJsonService.java | 45 +-- .../cms/SitemapUpdateTabJsonService.java | 47 +-- .../widgets/cms/StylesheetAjax.java | 35 +- .../widgets/cms/WebPageContentAjax.java | 29 +- .../widgets/cms/WebPageInfoAjax.java | 39 +- .../widgets/cms/WebPageListAjax.java | 19 +- .../editor/CRMCustomersJsonService.java | 11 +- .../CRMFormSubmissionDetailJsonService.java | 26 +- .../CRMFormSubmissionUpdateJsonService.java | 29 +- .../editor/CRMFormSubmissionsJsonService.java | 21 +- .../editor/CRMFormsListJsonService.java | 37 +- .../CRMMailingListMembersJsonService.java | 25 +- .../editor/CRMMailingListsJsonService.java | 20 +- .../widgets/editor/CRMSaveCustomerAjax.java | 37 +- .../editor/CRMSaveMailingListAjax.java | 33 +- .../editor/CRMSavePricingRuleAjax.java | 33 +- .../widgets/editor/CRMSaveProductAjax.java | 25 +- .../editor/CRMSaveProductCategoryAjax.java | 33 +- .../editor/CRMSaveSalesTaxNexusAjax.java | 25 +- .../editor/CRMSaveShippingRateAjax.java | 45 +-- ...dpoint.java => StaticSiteJsonService.java} | 55 ++- .../widgets/editor/VisualCRMEditorWidget.java | 6 + .../editor/VisualContentEditorWidget.java | 37 +- .../editor/VisualDataEditorWidget.java | 6 + .../editor/VisualDocumentEditorWidget.java | 6 + .../editor/VisualImageEditorWidget.java | 6 + .../editor/VisualPageEditorWidget.java | 6 + .../editor/VisualWorkflowEditorWidget.java | 5 +- .../WEB-INF/json-services/json-services.xml | 11 +- .../WEB-INF/jsp/admin/permission-groups.jsp | 50 +++ .../permission-groups/component-groups.xml | 362 ++++++++++++++++++ .../policies/site-blog-editor.cedar | 14 + .../policies/site-content-editor.cedar | 15 + .../policies/visual-content-editor.cedar | 16 + .../policies/visual-crm-editor.cedar | 17 + .../policies/visual-data-editor.cedar | 14 + .../policies/visual-document-editor.cedar | 14 + .../policies/visual-image-editor.cedar | 13 + .../policies/visual-web-sync-editor.cedar | 13 + .../policies/visual-workflow-editor.cedar | 12 + .../WEB-INF/web-layouts/page/admin-layout.xml | 11 + .../webapp/WEB-INF/widgets/widget-library.xml | 1 + 99 files changed, 1665 insertions(+), 1563 deletions(-) create mode 100644 src/main/java/com/simisinc/platform/presentation/widgets/admin/PermissionGroupsWidget.java rename src/main/java/com/simisinc/platform/presentation/widgets/editor/{StaticSiteEndpoint.java => StaticSiteJsonService.java} (87%) create mode 100644 src/main/webapp/WEB-INF/jsp/admin/permission-groups.jsp create mode 100644 src/main/webapp/WEB-INF/permission-groups/component-groups.xml create mode 100644 src/main/webapp/WEB-INF/permission-groups/policies/site-blog-editor.cedar create mode 100644 src/main/webapp/WEB-INF/permission-groups/policies/site-content-editor.cedar create mode 100644 src/main/webapp/WEB-INF/permission-groups/policies/visual-content-editor.cedar create mode 100644 src/main/webapp/WEB-INF/permission-groups/policies/visual-crm-editor.cedar create mode 100644 src/main/webapp/WEB-INF/permission-groups/policies/visual-data-editor.cedar create mode 100644 src/main/webapp/WEB-INF/permission-groups/policies/visual-document-editor.cedar create mode 100644 src/main/webapp/WEB-INF/permission-groups/policies/visual-image-editor.cedar create mode 100644 src/main/webapp/WEB-INF/permission-groups/policies/visual-web-sync-editor.cedar create mode 100644 src/main/webapp/WEB-INF/permission-groups/policies/visual-workflow-editor.cedar diff --git a/src/main/java/com/simisinc/platform/ApplicationInfo.java b/src/main/java/com/simisinc/platform/ApplicationInfo.java index 5c654c72..16aeda3d 100644 --- a/src/main/java/com/simisinc/platform/ApplicationInfo.java +++ b/src/main/java/com/simisinc/platform/ApplicationInfo.java @@ -32,7 +32,7 @@ public class ApplicationInfo { // Use: Change the date, increment the decimal on same day updates // then reset back to 10000 // VERSION = "--------.10000"; - public static final String VERSION = "20260305.10000"; + public static final String VERSION = "20260317.10000"; /** * Outputs the version from the command line diff --git a/src/main/java/com/simisinc/platform/application/json/JsonCommand.java b/src/main/java/com/simisinc/platform/application/json/JsonCommand.java index 781f908f..76972847 100644 --- a/src/main/java/com/simisinc/platform/application/json/JsonCommand.java +++ b/src/main/java/com/simisinc/platform/application/json/JsonCommand.java @@ -32,7 +32,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; /** - * Functinos for working with JSON data + * Functions for working with JSON data * * @author matt rajkowski * @created 9/9/19 10:47 AM diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/admin/PermissionGroupsWidget.java b/src/main/java/com/simisinc/platform/presentation/widgets/admin/PermissionGroupsWidget.java new file mode 100644 index 00000000..1e7a077b --- /dev/null +++ b/src/main/java/com/simisinc/platform/presentation/widgets/admin/PermissionGroupsWidget.java @@ -0,0 +1,45 @@ +/* + * Copyright 2026 Matt Rajkowski (https://github.com/rajkowski) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.simisinc.platform.presentation.widgets.admin; + +import com.simisinc.platform.application.admin.PermissionEngine; +import com.simisinc.platform.presentation.controller.WidgetContext; +import com.simisinc.platform.presentation.widgets.GenericWidget; + +/** + * Read-only admin view of loaded Cedar permission groups and their component members. + * + * @author matt rajkowski + * @created 3/6/26 8:00 AM + */ +public class PermissionGroupsWidget extends GenericWidget { + + static final long serialVersionUID = 7812340985623401287L; + static String JSP = "/admin/permission-groups.jsp"; + + @Override + public WidgetContext execute(WidgetContext context) { + if (!context.hasRole("admin")) { + LOG.debug("No permission to: " + PermissionGroupsWidget.class.getSimpleName()); + return context; + } + context.getRequest().setAttribute("permissionGroupList", PermissionEngine.getAllGroups()); + context.getRequest().setAttribute("icon", context.getPreferences().get("icon")); + context.getRequest().setAttribute("title", context.getPreferences().get("title")); + context.setJsp(JSP); + return context; + } +} diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/admin/cms/SubFolderFormWidget.java b/src/main/java/com/simisinc/platform/presentation/widgets/admin/cms/SubFolderFormWidget.java index 016c91f7..9799347a 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/admin/cms/SubFolderFormWidget.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/admin/cms/SubFolderFormWidget.java @@ -16,15 +16,21 @@ package com.simisinc.platform.presentation.widgets.admin.cms; -import com.simisinc.platform.application.DataException; -import com.simisinc.platform.application.cms.*; -import com.simisinc.platform.domain.model.cms.SubFolder; -import com.simisinc.platform.presentation.widgets.GenericWidget; -import com.simisinc.platform.presentation.controller.WidgetContext; +import java.lang.reflect.InvocationTargetException; + import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang3.StringUtils; -import java.lang.reflect.InvocationTargetException; +import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; +import com.simisinc.platform.application.cms.CheckFolderPermissionCommand; +import com.simisinc.platform.application.cms.FolderException; +import com.simisinc.platform.application.cms.LoadSubFolderCommand; +import com.simisinc.platform.application.cms.SaveSubFolderCommand; +import com.simisinc.platform.application.cms.UrlCommand; +import com.simisinc.platform.domain.model.cms.SubFolder; +import com.simisinc.platform.presentation.controller.WidgetContext; +import com.simisinc.platform.presentation.widgets.GenericWidget; /** * Widget for displaying a system administration form to add/update sub-folders @@ -65,7 +71,7 @@ public WidgetContext execute(WidgetContext context) { } // Check permissions - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { if (!CheckFolderPermissionCommand.userHasAddPermission(subFolder.getFolderId(), context.getUserId())) { return null; } @@ -87,7 +93,7 @@ public WidgetContext post(WidgetContext context) throws InvocationTargetExceptio String returnPage = UrlCommand.getValidReturnPage(context.getParameter("returnPage")); // Check permissions - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { if (!CheckFolderPermissionCommand.userHasAddPermission(subFolderBean.getFolderId(), context.getUserId())) { return null; } @@ -112,7 +118,7 @@ public WidgetContext post(WidgetContext context) throws InvocationTargetExceptio if (StringUtils.isNotBlank(returnPage)) { context.setRedirect(returnPage); } else { -// context.setRedirect("/admin/folder-details?folderId=" + subFolder.getFolderId()); + // context.setRedirect("/admin/folder-details?folderId=" + subFolder.getFolderId()); context.setRedirect("/admin/sub-folder-details?subFolderId=" + subFolder.getId() + "&folderId=" + subFolder.getFolderId()); } return context; diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/BlogsListJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/BlogsListJsonService.java index 0adb34e8..e3d33ba9 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/BlogsListJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/BlogsListJsonService.java @@ -22,11 +22,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Blog; import com.simisinc.platform.infrastructure.persistence.cms.BlogRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX GET requests for /json/blogs/list endpoint @@ -35,7 +36,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class BlogsListJsonService extends GenericWidget { +public class BlogsListJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(BlogsListJsonService.class); @@ -46,11 +47,12 @@ public class BlogsListJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + BlogsListJsonService.class.getSimpleName()); + return context.writeError("Permission denied"); } try { @@ -79,33 +81,12 @@ public WidgetContext execute(WidgetContext context) { json.append("]"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error loading blogs: " + e.getMessage(), e); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/BlogsPostsJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/BlogsPostsJsonService.java index 61aa599f..75ec8488 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/BlogsPostsJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/BlogsPostsJsonService.java @@ -22,12 +22,13 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.BlogPost; import com.simisinc.platform.infrastructure.persistence.cms.BlogPostRepository; import com.simisinc.platform.infrastructure.persistence.cms.BlogPostSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX GET requests for /json/blogs/posts endpoint @@ -36,7 +37,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class BlogsPostsJsonService extends GenericWidget { +public class BlogsPostsJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(BlogsPostsJsonService.class); @@ -47,11 +48,11 @@ public class BlogsPostsJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - // Return empty array on permission denied for FullCalendar + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + BlogsPostsJsonService.class.getSimpleName()); context.setJson("[]"); return context; } @@ -59,7 +60,7 @@ public WidgetContext execute(WidgetContext context) { try { // Get comma-separated blog IDs String blogIdsParam = context.getParameter("blogIds"); - + if (StringUtils.isBlank(blogIdsParam)) { // Return empty array for FullCalendar context.setJson("[]"); @@ -83,13 +84,14 @@ public WidgetContext execute(WidgetContext context) { boolean first = true; for (long blogId : blogIds) { - if (blogId <= 0) continue; - + if (blogId <= 0) + continue; + // Load blog posts for this blog using BlogPostSpecification BlogPostSpecification spec = new BlogPostSpecification(); spec.setBlogId(blogId); List posts = BlogPostRepository.findAll(spec, null); - + if (posts != null && !posts.isEmpty()) { for (BlogPost post : posts) { if (!first) { @@ -101,7 +103,7 @@ public WidgetContext execute(WidgetContext context) { json.append("\"id\": ").append(post.getId()).append(","); json.append("\"title\": \"").append(JsonCommand.toJson(post.getTitle())).append("\","); json.append("\"blogId\": ").append(blogId).append(","); - + if (post.getPublished() != null) { json.append("\"publishDate\": \"").append(JsonCommand.toJson(post.getPublished().toString())).append("\","); } else if (post.getStartDate() != null) { @@ -113,7 +115,7 @@ public WidgetContext execute(WidgetContext context) { json.append("\"created\": \"").append(JsonCommand.toJson(post.getCreated().toString())).append("\","); } json.append("\"content\": \"").append(JsonCommand.toJson(StringUtils.defaultString(post.getBody()))).append("\""); - + json.append("}"); } } @@ -127,7 +129,6 @@ public WidgetContext execute(WidgetContext context) { } catch (Exception e) { LOG.error("Error loading blog posts: " + e.getMessage(), e); - // Return empty array on error for FullCalendar context.setJson("[]"); return context; } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/CalendarsEventsJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/CalendarsEventsJsonService.java index 7d5477b1..00e1ad3c 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/CalendarsEventsJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/CalendarsEventsJsonService.java @@ -22,12 +22,13 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.CalendarEvent; import com.simisinc.platform.infrastructure.persistence.cms.CalendarEventRepository; import com.simisinc.platform.infrastructure.persistence.cms.CalendarEventSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX GET requests for /json/calendars/events endpoint @@ -36,7 +37,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class CalendarsEventsJsonService extends GenericWidget { +public class CalendarsEventsJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(CalendarsEventsJsonService.class); @@ -47,11 +48,11 @@ public class CalendarsEventsJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - // Return empty array on permission denied for FullCalendar + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CalendarsEventsJsonService.class.getSimpleName()); context.setJson("[]"); return context; } @@ -59,7 +60,7 @@ public WidgetContext execute(WidgetContext context) { try { // Get comma-separated calendar IDs String calendarIdsParam = context.getParameter("calendarIds"); - + if (StringUtils.isBlank(calendarIdsParam)) { // Return empty array for FullCalendar context.setJson("[]"); @@ -83,13 +84,14 @@ public WidgetContext execute(WidgetContext context) { boolean first = true; for (long calendarId : calendarIds) { - if (calendarId <= 0) continue; - + if (calendarId <= 0) + continue; + // Load events for this calendar using CalendarEventSpecification CalendarEventSpecification spec = new CalendarEventSpecification(); spec.setCalendarId(calendarId); List events = CalendarEventRepository.findAll(spec, null); - + if (events != null && !events.isEmpty()) { for (CalendarEvent event : events) { if (!first) { @@ -101,7 +103,7 @@ public WidgetContext execute(WidgetContext context) { json.append("\"id\": ").append(event.getId()).append(","); json.append("\"title\": \"").append(JsonCommand.toJson(event.getTitle())).append("\","); json.append("\"calendarId\": ").append(calendarId).append(","); - + if (event.getStartDate() != null) { json.append("\"startDate\": \"").append(JsonCommand.toJson(event.getStartDate().toString())).append("\","); } else { @@ -113,7 +115,7 @@ public WidgetContext execute(WidgetContext context) { json.append("\"endDate\": \"\","); } json.append("\"description\": \"").append(JsonCommand.toJson(StringUtils.defaultString(event.getSummary()))).append("\""); - + json.append("}"); } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/CalendarsListJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/CalendarsListJsonService.java index 450700c8..3d36e866 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/CalendarsListJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/CalendarsListJsonService.java @@ -22,11 +22,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Calendar; import com.simisinc.platform.infrastructure.persistence.cms.CalendarRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX GET requests for /json/calendars/list endpoint @@ -35,7 +36,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class CalendarsListJsonService extends GenericWidget { +public class CalendarsListJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(CalendarsListJsonService.class); @@ -46,11 +47,12 @@ public class CalendarsListJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CalendarsListJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -72,40 +74,20 @@ public WidgetContext execute(WidgetContext context) { json.append("{"); json.append("\"id\": ").append(calendar.getId()).append(","); json.append("\"title\": \"").append(JsonCommand.toJson(calendar.getName())).append("\","); - json.append("\"description\": \"").append(JsonCommand.toJson(StringUtils.defaultString(calendar.getDescription()))).append("\""); + json.append("\"description\": \"").append(JsonCommand.toJson(StringUtils.defaultString(calendar.getDescription()))) + .append("\""); json.append("}"); } } json.append("]"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error loading calendars: " + e.getMessage(), e); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentGetJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentGetJsonService.java index 3fa4df04..a5500a62 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentGetJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentGetJsonService.java @@ -22,14 +22,15 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.TinyMceCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Content; import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.cms.ContentRepository; import com.simisinc.platform.infrastructure.persistence.cms.ContentSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX GET requests for /json/content/get endpoint @@ -38,7 +39,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class ContentGetJsonService extends GenericWidget { +public class ContentGetJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(ContentGetJsonService.class); @@ -49,22 +50,23 @@ public class ContentGetJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ContentGetJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { // Get content by uniqueId long contentId = context.getParameterAsLong("contentId", -1); String uniqueId = context.getParameter("uniqueId"); - + Content content = loadContentByIdOrUniqueId(contentId, uniqueId); if (content == null) { - return writeError(context, "Content not found"); + return context.writeError("Content not found"); } // Build JSON response @@ -72,7 +74,7 @@ public WidgetContext execute(WidgetContext context) { json.append("{"); json.append("\"id\": ").append(content.getId()).append(","); json.append("\"unique_id\": \"").append(JsonCommand.toJson(content.getUniqueId())).append("\","); - + // Include published content, prepared for editor if (StringUtils.isNotBlank(content.getContent())) { String preparedContent = TinyMceCommand.prepareContentForEditor(content.getContent()); @@ -80,7 +82,7 @@ public WidgetContext execute(WidgetContext context) { } else { json.append("\"content\": \"\","); } - + // Include draft content if exists, prepared for editor if (StringUtils.isNotBlank(content.getDraftContent())) { String preparedDraft = TinyMceCommand.prepareContentForEditor(content.getDraftContent()); @@ -88,7 +90,7 @@ public WidgetContext execute(WidgetContext context) { } else { json.append("\"draft_content\": \"\","); } - + // Include metadata if (content.getCreated() != null) { json.append("\"created\": \"").append(JsonCommand.toJson(content.getCreated().toString())).append("\","); @@ -100,11 +102,11 @@ public WidgetContext execute(WidgetContext context) { json.append("\"modified_by\": ").append(content.getModifiedBy()); json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error getting content: " + e.getMessage(), e); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } } @@ -124,25 +126,4 @@ private Content loadContentByIdOrUniqueId(long contentId, String uniqueId) { return null; } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentListAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentListAjax.java index 04b7815e..61addb54 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentListAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentListAjax.java @@ -16,15 +16,19 @@ package com.simisinc.platform.presentation.widgets.cms; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.HtmlCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Content; import com.simisinc.platform.infrastructure.persistence.cms.ContentRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; -import org.apache.commons.lang3.StringUtils; - -import java.util.List; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns a list of content items for the visual page editor @@ -32,16 +36,17 @@ * @author matt rajkowski * @created 1/3/26 10:00 AM */ -public class ContentListAjax extends GenericWidget { +public class ContentListAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; + protected static Log LOG = LogFactory.getLog(ContentListAjax.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"contentList\":[]}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ContentListAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Retrieve all content diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentListJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentListJsonService.java index 013d483a..eec12eeb 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentListJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentListJsonService.java @@ -22,11 +22,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.LoadContentListCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Content; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX GET requests for /json/content/list endpoint @@ -35,7 +36,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class ContentListJsonService extends GenericWidget { +public class ContentListJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(ContentListJsonService.class); @@ -46,11 +47,12 @@ public class ContentListJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ContentListJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -78,34 +80,34 @@ public WidgetContext execute(WidgetContext context) { json.append("{"); json.append("\"id\": ").append(content.getId()).append(","); json.append("\"unique_id\": \"").append(JsonCommand.toJson(content.getUniqueId())).append("\","); - + // Include modified date if available if (content.getModified() != null) { json.append("\"modified\": \"").append(JsonCommand.toJson(content.getModified().toString())).append("\","); } - + // Indicate if draft exists boolean hasDraft = StringUtils.isNotBlank(content.getDraftContent()); json.append("\"draft_content\": ").append(hasDraft).append(","); - + // Include highlight if available (from search) if (StringUtils.isNotBlank(content.getHighlight())) { json.append("\"highlight\": \"").append(JsonCommand.toJson(content.getHighlight())).append("\","); } - + // Include preview of content (first 160 chars) String preview = ""; if (StringUtils.isNotBlank(content.getContent())) { - preview = content.getContent().length() > 160 - ? content.getContent().substring(0, 160) + "..." + preview = content.getContent().length() > 160 + ? content.getContent().substring(0, 160) + "..." : content.getContent(); preview = preview.replaceAll("<[^>]*>", ""); } json.append("\"content\": \"").append(JsonCommand.toJson(preview)).append("\""); - + json.append("}"); } - + // Check if there are more results boolean hasMore = contentList.size() >= limit; json.append("]"); @@ -115,7 +117,7 @@ public WidgetContext execute(WidgetContext context) { meta.append("\"limit\": ").append(limit).append(","); meta.append("\"hasMore\": ").append(hasMore); meta.append("}"); - return writeOk(context, json.toString(), meta.toString()); + return context.writeOk(json.toString(), meta.toString()); } else { json.append("]"); StringBuilder meta = new StringBuilder(); @@ -124,34 +126,13 @@ public WidgetContext execute(WidgetContext context) { meta.append("\"limit\": ").append(limit).append(","); meta.append("\"hasMore\": false"); meta.append("}"); - return writeOk(context, json.toString(), meta.toString()); + return context.writeOk(json.toString(), meta.toString()); } } catch (Exception e) { LOG.error("Error loading content list: " + e.getMessage(), e); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentPreviewJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentPreviewJsonService.java index 91d2b380..e5a15297 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentPreviewJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentPreviewJsonService.java @@ -22,14 +22,15 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.ResolveContentDirectivesCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Content; import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.cms.ContentRepository; import com.simisinc.platform.infrastructure.persistence.cms.ContentSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX GET requests for /json/content/preview endpoint @@ -38,7 +39,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class ContentPreviewJsonService extends GenericWidget { +public class ContentPreviewJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(ContentPreviewJsonService.class); @@ -49,11 +50,12 @@ public class ContentPreviewJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ContentPreviewJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -64,12 +66,12 @@ public WidgetContext execute(WidgetContext context) { Content content = loadContentByIdOrUniqueId(contentId, uniqueId); if (content == null) { - return writeError(context, "Content not found"); + return context.writeError("Content not found"); } // Get the content to preview (prefer draft if exists) - String contentToPreview = StringUtils.isNotBlank(content.getDraftContent()) - ? content.getDraftContent() + String contentToPreview = StringUtils.isNotBlank(content.getDraftContent()) + ? content.getDraftContent() : content.getContent(); if (StringUtils.isBlank(contentToPreview)) { @@ -83,11 +85,11 @@ public WidgetContext execute(WidgetContext context) { StringBuilder json = new StringBuilder(); json.append("\"").append(JsonCommand.toJson(resolvedContent)).append("\""); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error generating preview: " + e.getMessage(), e); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } } @@ -107,25 +109,4 @@ private Content loadContentByIdOrUniqueId(long contentId, String uniqueId) { return null; } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentPublishJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentPublishJsonService.java index 11fb2daa..de97b47b 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentPublishJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentPublishJsonService.java @@ -23,6 +23,7 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.PublishContentCommand; import com.simisinc.platform.application.cms.SaveContentCommand; import com.simisinc.platform.application.cms.TinyMceCommand; @@ -31,8 +32,8 @@ import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.cms.ContentRepository; import com.simisinc.platform.infrastructure.persistence.cms.ContentSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/content/publish endpoint @@ -41,7 +42,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class ContentPublishJsonService extends GenericWidget { +public class ContentPublishJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(ContentPublishJsonService.class); @@ -52,11 +53,12 @@ public class ContentPublishJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ContentPublishJsonService.class.getSimpleName()); + return context.writeError("Permission denied"); } try { @@ -74,13 +76,13 @@ public WidgetContext post(WidgetContext context) { Content contentBean = loadContentByIdOrUniqueId(contentId, uniqueId); if (contentBean == null) { if (StringUtils.isBlank(uniqueId)) { - return writeError(context, "Content uniqueId is required"); + return context.writeError("Content uniqueId is required"); } contentBean = new Content(); contentBean.setUniqueId(uniqueId); contentBean.setCreatedBy(context.getUserId()); } - + contentBean.setContent(contentHtml); contentBean.setModifiedBy(context.getUserId()); @@ -88,7 +90,7 @@ public WidgetContext post(WidgetContext context) { Content savedContent = SaveContentCommand.saveContent(contentBean, false); if (savedContent == null) { - return writeError(context, "Failed to publish content"); + return context.writeError("Failed to publish content"); } // Build success response @@ -102,7 +104,7 @@ public WidgetContext post(WidgetContext context) { } json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } else { // Publish existing draft @@ -113,13 +115,13 @@ public WidgetContext post(WidgetContext context) { } } if (StringUtils.isBlank(uniqueId)) { - return writeError(context, "Content uniqueId is required"); + return context.writeError("Content uniqueId is required"); } boolean published = PublishContentCommand.publishContent(uniqueId); if (!published) { - return writeError(context, "Failed to publish content"); + return context.writeError("Failed to publish content"); } // Load the updated content @@ -136,15 +138,15 @@ public WidgetContext post(WidgetContext context) { } json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } } catch (DataException e) { LOG.warn("Validation error publishing content: " + e.getMessage()); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } catch (Exception e) { LOG.error("Error publishing content: " + e.getMessage(), e); - return writeError(context, "An unexpected error occurred while publishing content"); + return context.writeError("An unexpected error occurred while publishing content"); } } @@ -164,25 +166,4 @@ private Content loadContentByIdOrUniqueId(long contentId, String uniqueId) { return null; } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentSaveDraftJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentSaveDraftJsonService.java index c65ba63b..a0703902 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentSaveDraftJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ContentSaveDraftJsonService.java @@ -23,6 +23,7 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.SaveContentCommand; import com.simisinc.platform.application.cms.TinyMceCommand; import com.simisinc.platform.application.json.JsonCommand; @@ -30,8 +31,8 @@ import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.cms.ContentRepository; import com.simisinc.platform.infrastructure.persistence.cms.ContentSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/content/save-draft endpoint @@ -40,7 +41,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class ContentSaveDraftJsonService extends GenericWidget { +public class ContentSaveDraftJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(ContentSaveDraftJsonService.class); @@ -48,14 +49,15 @@ public class ContentSaveDraftJsonService extends GenericWidget { /** * Handles POST requests to save content as draft * - * @param context the widget context + * @param context the JSON service context * @return context with JSON response */ - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ContentSaveDraftJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -75,13 +77,13 @@ public WidgetContext post(WidgetContext context) { Content contentBean = loadContentByIdOrUniqueId(contentId, uniqueId); if (contentBean == null) { if (StringUtils.isBlank(uniqueId)) { - return writeError(context, "Content uniqueId is required"); + return context.writeError("Content uniqueId is required"); } contentBean = new Content(); contentBean.setUniqueId(uniqueId); contentBean.setCreatedBy(context.getUserId()); } - + contentBean.setDraftContent(contentHtml); contentBean.setModifiedBy(context.getUserId()); @@ -89,7 +91,7 @@ public WidgetContext post(WidgetContext context) { Content savedContent = SaveContentCommand.saveContent(contentBean, true); if (savedContent == null) { - return writeError(context, "Failed to save draft"); + return context.writeError("Failed to save draft"); } // Build success response @@ -103,14 +105,14 @@ public WidgetContext post(WidgetContext context) { } json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (DataException e) { LOG.warn("Validation error saving draft: " + e.getMessage()); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } catch (Exception e) { LOG.error("Error saving draft: " + e.getMessage(), e); - return writeError(context, "An unexpected error occurred while saving draft"); + return context.writeError("An unexpected error occurred while saving draft"); } } @@ -130,25 +132,4 @@ private Content loadContentByIdOrUniqueId(long contentId, String uniqueId) { return null; } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentAnalyticsAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentAnalyticsAjax.java index 74e6de4e..95294284 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentAnalyticsAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentAnalyticsAjax.java @@ -22,13 +22,14 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.FileItem; import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.cms.FileItemRepository; import com.simisinc.platform.infrastructure.persistence.cms.FileSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns top assets analytics for a document repository in the visual document editor @@ -36,19 +37,20 @@ * @author matt rajkowski * @created 2/19/26 */ -public class DocumentAnalyticsAjax extends GenericWidget { +public class DocumentAnalyticsAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908907L; private static Log LOG = LogFactory.getLog(DocumentAnalyticsAjax.class); @Override - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("DocumentAnalyticsAjax..."); - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"assets\":[]}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + DocumentAnalyticsAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long folderId = context.getParameterAsLong("folderId", -1); @@ -85,7 +87,8 @@ public WidgetContext execute(WidgetContext context) { first = false; sb.append("{"); sb.append("\"id\":").append(file.getId()).append(","); - sb.append("\"title\":\"").append(JsonCommand.toJson(StringUtils.defaultString(file.getTitle(), file.getFilename()))).append("\","); + sb.append("\"title\":\"").append(JsonCommand.toJson(StringUtils.defaultString(file.getTitle(), file.getFilename()))) + .append("\","); sb.append("\"filename\":\"").append(JsonCommand.toJson(StringUtils.defaultString(file.getFilename()))).append("\","); sb.append("\"mimeType\":\"").append(JsonCommand.toJson(StringUtils.defaultString(file.getMimeType()))).append("\","); sb.append("\"downloadCount\":").append(file.getDownloadCount()); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentContentAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentContentAjax.java index 7e960bcd..78890c60 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentContentAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentContentAjax.java @@ -20,11 +20,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.FileItem; import com.simisinc.platform.infrastructure.persistence.cms.FileItemRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns a single file's metadata for the visual document editor @@ -32,31 +33,30 @@ * @author matt rajkowski * @created 1/22/26 10:20 AM */ -public class DocumentContentAjax extends GenericWidget { +public class DocumentContentAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(DocumentContentAjax.class); @Override - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("DocumentContentAjax..."); - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + DocumentContentAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long fileId = context.getParameterAsLong("fileId", -1); if (fileId == -1) { - context.setJson("{\"error\":\"fileId required\"}"); - return context; + return context.writeError("File ID required"); } FileItem fileItem = FileItemRepository.findById(fileId); if (fileItem == null) { - context.setJson("{\"error\":\"File not found\"}"); - return context; + return context.writeError("File not found"); } StringBuilder sb = new StringBuilder(); @@ -74,8 +74,10 @@ public WidgetContext execute(WidgetContext context) { sb.append("\"versionCount\":").append(fileItem.getVersionCount()).append(","); sb.append("\"downloadCount\":").append(fileItem.getDownloadCount()).append(","); sb.append("\"summary\":\"").append(JsonCommand.toJson(StringUtils.defaultString(fileItem.getSummary()))).append("\","); - sb.append("\"created\":\"").append(fileItem.getCreated() != null ? JsonCommand.toJson(fileItem.getCreated().toString()) : "").append("\","); - sb.append("\"modified\":\"").append(fileItem.getModified() != null ? JsonCommand.toJson(fileItem.getModified().toString()) : "").append("\""); + sb.append("\"created\":\"").append(fileItem.getCreated() != null ? JsonCommand.toJson(fileItem.getCreated().toString()) : "") + .append("\","); + sb.append("\"modified\":\"").append(fileItem.getModified() != null ? JsonCommand.toJson(fileItem.getModified().toString()) : "") + .append("\""); sb.append("}"); context.setJson(sb.toString()); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentCreateFolderAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentCreateFolderAjax.java index 65112d2f..4b5ffc8e 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentCreateFolderAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentCreateFolderAjax.java @@ -20,37 +20,36 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.SaveFolderCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Folder; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Creates a new folder for the visual document editor */ -public class DocumentCreateFolderAjax extends GenericWidget { +public class DocumentCreateFolderAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908897L; private static Log LOG = LogFactory.getLog(DocumentCreateFolderAjax.class); @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("DocumentCreateFolderAjax..."); - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + DocumentCreateFolderAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } String name = context.getParameter("name"); if (StringUtils.isBlank(name)) { - context.setJson("{\"success\":false,\"message\":\"Folder name is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder name is required"); } Folder folderBean = new Folder(); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentCreateSubfolderAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentCreateSubfolderAjax.java index c2ce6c20..1786eb2b 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentCreateSubfolderAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentCreateSubfolderAjax.java @@ -16,41 +16,41 @@ package com.simisinc.platform.presentation.widgets.cms; -import com.simisinc.platform.application.cms.SaveSubFolderCommand; -import com.simisinc.platform.application.json.JsonCommand; -import com.simisinc.platform.domain.model.cms.SubFolder; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; +import com.simisinc.platform.application.cms.SaveSubFolderCommand; +import com.simisinc.platform.application.json.JsonCommand; +import com.simisinc.platform.domain.model.cms.SubFolder; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; + /** * Creates a new subfolder for the visual document editor */ -public class DocumentCreateSubfolderAjax extends GenericWidget { +public class DocumentCreateSubfolderAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908896L; private static Log LOG = LogFactory.getLog(DocumentCreateSubfolderAjax.class); @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("DocumentCreateSubfolderAjax..."); - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"status\":0,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + DocumentCreateSubfolderAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long folderId = context.getParameterAsLong("folderId", -1); String name = context.getParameter("name"); if (folderId <= 0 || StringUtils.isBlank(name)) { - context.setJson("{\"status\":0,\"message\":\"Folder and name are required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder and name are required"); } SubFolder subFolderBean = new SubFolder(); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentDeleteFolderAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentDeleteFolderAjax.java index 7aa0fbe5..7209d4ad 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentDeleteFolderAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentDeleteFolderAjax.java @@ -20,11 +20,12 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.DeleteFolderCommand; import com.simisinc.platform.domain.model.cms.Folder; import com.simisinc.platform.infrastructure.persistence.cms.FolderRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Deletes a folder (repository) in the visual document editor @@ -32,34 +33,30 @@ * @author matt rajkowski * @created 2/19/26 */ -public class DocumentDeleteFolderAjax extends GenericWidget { +public class DocumentDeleteFolderAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908899L; private static Log LOG = LogFactory.getLog(DocumentDeleteFolderAjax.class); @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("DocumentDeleteFolderAjax..."); - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + DocumentDeleteFolderAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long folderId = context.getParameterAsLong("folderId", -1); if (folderId == -1) { - context.setJson("{\"success\":false,\"message\":\"Folder ID required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder ID required"); } Folder folder = FolderRepository.findById(folderId); if (folder == null) { - context.setJson("{\"success\":false,\"message\":\"Folder not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder not found"); } try { @@ -72,8 +69,7 @@ public WidgetContext post(WidgetContext context) { } } catch (DataException e) { LOG.warn("Error deleting folder: " + e.getMessage()); - context.setJson("{\"success\":false,\"message\":\"" + e.getMessage() + "\"}"); - context.setSuccess(false); + return context.writeError(e.getMessage()); } return context; diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileAnalyticsAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileAnalyticsAjax.java index b9e99f04..1391cf17 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileAnalyticsAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileAnalyticsAjax.java @@ -24,13 +24,14 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.FileItem; import com.simisinc.platform.domain.model.dashboard.StatisticsData; import com.simisinc.platform.infrastructure.persistence.cms.FileItemRepository; import com.simisinc.platform.infrastructure.persistence.cms.WebPageHitRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns analytics for a specific file in the visual document editor, querying web_page_hits @@ -39,20 +40,21 @@ * @author matt rajkowski * @created 2/19/26 */ -public class DocumentFileAnalyticsAjax extends GenericWidget { +public class DocumentFileAnalyticsAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908911L; private static Log LOG = LogFactory.getLog(DocumentFileAnalyticsAjax.class); private static final String EMPTY_RESPONSE = "{\"totalHits\":0,\"recentHits\":[],\"monthlyData\":[]}"; @Override - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("DocumentFileAnalyticsAjax..."); - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson(EMPTY_RESPONSE); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + DocumentFileAnalyticsAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long fileId = context.getParameterAsLong("fileId", -1); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileListAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileListAjax.java index 3cec00f4..a6b4bf83 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileListAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileListAjax.java @@ -22,14 +22,15 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.FileItem; import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.cms.FileItemRepository; import com.simisinc.platform.infrastructure.persistence.cms.FileSpecification; +import com.simisinc.platform.presentation.controller.JsonServiceContext; import com.simisinc.platform.presentation.controller.UserSession; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns file list data for a folder for the visual document editor @@ -37,19 +38,20 @@ * @author matt rajkowski * @created 1/22/26 10:15 AM */ -public class DocumentFileListAjax extends GenericWidget { +public class DocumentFileListAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(DocumentFileListAjax.class); @Override - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("DocumentFileListAjax..."); - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"files\":[],\"total\":0}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + DocumentFileListAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long folderId = context.getParameterAsLong("folderId", -1); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileVersionsAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileVersionsAjax.java index aace4a91..bcfdb17f 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileVersionsAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentFileVersionsAjax.java @@ -22,12 +22,13 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.FileVersion; import com.simisinc.platform.infrastructure.persistence.cms.FileVersionRepository; import com.simisinc.platform.infrastructure.persistence.cms.FileVersionSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns version history for a file item in the visual document editor @@ -35,19 +36,20 @@ * @author matt rajkowski * @created 2/19/26 */ -public class DocumentFileVersionsAjax extends GenericWidget { +public class DocumentFileVersionsAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908903L; private static Log LOG = LogFactory.getLog(DocumentFileVersionsAjax.class); @Override - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("DocumentFileVersionsAjax..."); - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"versions\":[]}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + DocumentFileVersionsAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long fileId = context.getParameterAsLong("fileId", -1); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentLibraryAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentLibraryAjax.java index 9d199ade..399163a8 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentLibraryAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentLibraryAjax.java @@ -23,14 +23,15 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Folder; import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.cms.FolderRepository; import com.simisinc.platform.infrastructure.persistence.cms.FolderSpecification; +import com.simisinc.platform.presentation.controller.JsonServiceContext; import com.simisinc.platform.presentation.controller.UserSession; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns folder metadata for the visual document editor @@ -38,20 +39,21 @@ * @author matt rajkowski * @created 1/22/26 10:10 AM */ -public class DocumentLibraryAjax extends GenericWidget { +public class DocumentLibraryAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(DocumentLibraryAjax.class); @Override - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("DocumentLibraryAjax..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"folders\":[],\"total\":0}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + DocumentLibraryAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } String searchTerm = context.getParameter("search"); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentSubfoldersAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentSubfoldersAjax.java index dce301d5..d385fdce 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentSubfoldersAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentSubfoldersAjax.java @@ -22,31 +22,33 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.SubFolder; import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.cms.SubFolderRepository; import com.simisinc.platform.infrastructure.persistence.cms.SubFolderSpecification; +import com.simisinc.platform.presentation.controller.JsonServiceContext; import com.simisinc.platform.presentation.controller.UserSession; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns subfolder metadata for the visual document editor */ -public class DocumentSubfoldersAjax extends GenericWidget { +public class DocumentSubfoldersAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908895L; private static Log LOG = LogFactory.getLog(DocumentSubfoldersAjax.class); @Override - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("DocumentSubfoldersAjax..."); - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"subfolders\":[],\"total\":0}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + DocumentSubfoldersAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long folderId = context.getParameterAsLong("folderId", -1); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentUserGroupsAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentUserGroupsAjax.java index 79bb099f..66626b19 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentUserGroupsAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/DocumentUserGroupsAjax.java @@ -21,10 +21,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.Group; import com.simisinc.platform.infrastructure.persistence.GroupRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns all system user groups for folder permission setup in the visual document editor @@ -32,19 +33,20 @@ * @author matt rajkowski * @created 2/19/26 */ -public class DocumentUserGroupsAjax extends GenericWidget { +public class DocumentUserGroupsAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908908L; private static Log LOG = LogFactory.getLog(DocumentUserGroupsAjax.class); @Override - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("DocumentUserGroupsAjax..."); - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"groups\":[]}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + DocumentUserGroupsAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } List allGroups = GroupRepository.findAll(); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderDetailsAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderDetailsAjax.java index 9b630743..dc12c694 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderDetailsAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderDetailsAjax.java @@ -19,10 +19,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.Folder; import com.simisinc.platform.infrastructure.persistence.cms.FolderRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns folder details for the visual document editor @@ -30,37 +31,33 @@ * @author matt rajkowski * @created 1/22/26 11:00 AM */ -public class FolderDetailsAjax extends GenericWidget { +public class FolderDetailsAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908894L; private static Log LOG = LogFactory.getLog(FolderDetailsAjax.class); @Override - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("FolderDetailsAjax..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\":false, \"error\": \"Access denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + FolderDetailsAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long folderId = context.getParameterAsLong("folderId", -1); if (folderId == -1) { - context.setJson("{\"success\":false, \"error\": \"Folder ID required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder ID required"); } // @todo check access Folder folder = FolderRepository.findById(folderId); if (folder == null) { - context.setJson("{\"success\":false, \"error\": \"Folder not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder not found"); } StringBuilder json = new StringBuilder(); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupDeleteJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupDeleteJsonService.java index b72a17e0..bd68c4b4 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupDeleteJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupDeleteJsonService.java @@ -19,9 +19,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.infrastructure.persistence.cms.FolderGroupRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Deletes folder group permissions in the visual document editor @@ -29,21 +30,21 @@ * @author matt rajkowski * @created 1/22/26 11:20 AM */ -public class FolderGroupDeleteJsonService extends GenericWidget { +public class FolderGroupDeleteJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908897L; private static Log LOG = LogFactory.getLog(FolderGroupDeleteJsonService.class); @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("FolderGroupDeleteAjax..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\": false, \"error\": \"Access denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + FolderGroupDeleteJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } long id = context.getParameterAsLong("id", -1); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupSaveJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupSaveJsonService.java index 1a91d0a5..65f1482e 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupSaveJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupSaveJsonService.java @@ -19,12 +19,13 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.Folder; import com.simisinc.platform.domain.model.cms.FolderGroup; import com.simisinc.platform.infrastructure.persistence.cms.FolderGroupRepository; import com.simisinc.platform.infrastructure.persistence.cms.FolderRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Saves folder group permissions in the visual document editor @@ -32,21 +33,21 @@ * @author matt rajkowski * @created 1/22/26 11:15 AM */ -public class FolderGroupSaveJsonService extends GenericWidget { +public class FolderGroupSaveJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908896L; private static Log LOG = LogFactory.getLog(FolderGroupSaveJsonService.class); @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("FolderGroupSaveAjax..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\": false, \"error\": \"Access denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + FolderGroupSaveJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } long folderId = context.getParameterAsLong("folderId", -1); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupsListAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupsListAjax.java index c310e63b..8f58960b 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupsListAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGroupsListAjax.java @@ -21,14 +21,15 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.Group; import com.simisinc.platform.domain.model.cms.Folder; import com.simisinc.platform.domain.model.cms.FolderGroup; import com.simisinc.platform.infrastructure.persistence.GroupRepository; import com.simisinc.platform.infrastructure.persistence.cms.FolderGroupRepository; import com.simisinc.platform.infrastructure.persistence.cms.FolderRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns folder groups and available groups for the visual document editor @@ -36,38 +37,34 @@ * @author matt rajkowski * @created 1/22/26 11:10 AM */ -public class FolderGroupsListAjax extends GenericWidget { +public class FolderGroupsListAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908895L; private static Log LOG = LogFactory.getLog(FolderGroupsListAjax.class); private static final String JSON_ID = "\"id\":"; @Override - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("FolderGroupsListAjax..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\": false, \"error\": \"Access denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + FolderGroupsListAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long folderId = context.getParameterAsLong("folderId", -1); if (folderId == -1) { - context.setJson("{\"success\": false, \"error\": \"Folder ID required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder ID required"); } // @todo check access Folder folder = FolderRepository.findById(folderId); if (folder == null) { - context.setJson("{\"success\": false, \"error\": \"Folder not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder not found"); } // Get folder groups and all groups diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGuestAccessSaveJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGuestAccessSaveJsonService.java index 80e9b4d7..d4de9238 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGuestAccessSaveJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderGuestAccessSaveJsonService.java @@ -19,10 +19,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.Folder; import com.simisinc.platform.infrastructure.persistence.cms.FolderRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Saves folder guest access settings in the visual document editor @@ -30,35 +31,31 @@ * @author matt rajkowski * @created 2/23/26 7:00 PM */ -public class FolderGuestAccessSaveJsonService extends GenericWidget { +public class FolderGuestAccessSaveJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(FolderGuestAccessSaveJsonService.class); @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("FolderGuestAccessSaveJsonService..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\": false, \"error\": \"Access denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + FolderGuestAccessSaveJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } long folderId = context.getParameterAsLong("folderId", -1); if (folderId == -1) { - context.setJson("{\"success\": false, \"error\": \"Folder ID required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder ID required"); } Folder folder = FolderRepository.findById(folderId); if (folder == null) { - context.setJson("{\"success\": false, \"error\": \"Folder not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder not found"); } int guestPrivacyType = context.getParameterAsInt("guestPrivacyType", -1); @@ -66,8 +63,7 @@ public WidgetContext post(WidgetContext context) { if (FolderRepository.updateGuestAccess(folderId, guestPrivacyType)) { context.setJson("{\"success\": true, \"message\": \"Guest access saved\"}"); } else { - context.setJson("{\"success\": false, \"message\": \"Failed to save guest access\"}"); - context.setSuccess(false); + return context.writeError("Failed to save guest access"); } return context; diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderSaveAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderSaveAjax.java index 372a7078..e7f5d773 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderSaveAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/FolderSaveAjax.java @@ -20,10 +20,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.Folder; import com.simisinc.platform.infrastructure.persistence.cms.FolderRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Saves folder details in the visual document editor @@ -31,42 +32,36 @@ * @author matt rajkowski * @created 1/22/26 11:25 AM */ -public class FolderSaveAjax extends GenericWidget { +public class FolderSaveAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908898L; private static Log LOG = LogFactory.getLog(FolderSaveAjax.class); @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("FolderSaveAjax..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\": false, \"error\": \"Access denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + FolderSaveAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long folderId = context.getParameterAsLong("id", -1); if (folderId == -1) { - context.setJson("{\"success\": false, \"error\": \"Folder 'ID' required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder ID required"); } Folder folder = FolderRepository.findById(folderId); if (folder == null) { - context.setJson("{\"success\": false, \"error\": \"Folder not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder not found"); } String name = StringUtils.trimToNull(context.getParameter("name")); if (StringUtils.isBlank(name)) { - context.setJson("{\"success\": false, \"error\": \"Folder name is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Folder name is required"); } folder.setName(name); @@ -78,8 +73,7 @@ public WidgetContext post(WidgetContext context) { if (saved != null) { context.setJson("{\"success\": true, \"message\": \"Folder saved successfully\"}"); } else { - context.setJson("{\"success\": false, \"message\": \"Failed to save folder\"}"); - context.setSuccess(false); + return context.writeError("Failed to save folder"); } return context; diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageContentAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageContentAjax.java index 8ef3ff96..cd5e4c3d 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageContentAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageContentAjax.java @@ -20,11 +20,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Image; import com.simisinc.platform.infrastructure.persistence.cms.ImageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns a single image's data for the visual image editor @@ -33,36 +34,33 @@ * @author matt rajkowski * @created 1/21/26 9:15 PM */ -public class ImageContentAjax extends GenericWidget { +public class ImageContentAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(ImageContentAjax.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("ImageContentAjax..."); - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.debug("No permission to access image content"); - context.setJson("{}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ImageContentAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Get the image ID long imageId = context.getParameterAsLong("imageId", -1); if (imageId == -1) { LOG.debug("Image ID not provided"); - context.setJson("{\"error\":\"Image ID required\"}"); - return context; + return context.writeError("Image ID required"); } // Retrieve the image Image image = ImageRepository.findById(imageId); if (image == null) { LOG.debug("Image not found for ID: " + imageId); - context.setJson("{\"error\":\"Image not found\"}"); - return context; + return context.writeError("Image not found"); } // Build JSON response with image details diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageDeleteAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageDeleteAjax.java index 6cbd826f..529b7b39 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageDeleteAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageDeleteAjax.java @@ -19,11 +19,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.DeleteImageCommand; import com.simisinc.platform.domain.model.cms.Image; import com.simisinc.platform.infrastructure.persistence.cms.ImageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Deletes an image in the visual image editor @@ -31,35 +32,31 @@ * @author matt rajkowski * @created 1/31/26 9:35 AM */ -public class ImageDeleteAjax extends GenericWidget { +public class ImageDeleteAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908895L; private static Log LOG = LogFactory.getLog(ImageDeleteAjax.class); @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("ImageDeleteAjax..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\": false, \"error\": \"Access denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ImageDeleteAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long imageId = context.getParameterAsLong("id", -1); if (imageId == -1) { - context.setJson("{\"success\": false, \"error\": \"Image 'ID' required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Image ID required"); } Image image = ImageRepository.findById(imageId); if (image == null) { - context.setJson("{\"success\": false, \"error\": \"Image not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Image not found"); } try { @@ -68,8 +65,7 @@ public WidgetContext post(WidgetContext context) { context.setJson("{\"success\": true, \"message\": \"Image deleted successfully\"}"); } catch (Exception e) { LOG.error("Error deleting image", e); - context.setJson("{\"success\": false, \"error\": \"Failed to delete image: " + e.getMessage() + "\"}"); - context.setSuccess(false); + return context.writeError("Failed to delete image: " + e.getMessage()); } return context; diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageLibraryAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageLibraryAjax.java index fe5acd99..04b3f6aa 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageLibraryAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageLibraryAjax.java @@ -22,13 +22,14 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Image; import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.cms.ImageRepository; import com.simisinc.platform.infrastructure.persistence.cms.ImageSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns image library data for the visual image editor @@ -37,20 +38,19 @@ * @author matt rajkowski * @created 1/21/26 9:00 PM */ -public class ImageLibraryAjax extends GenericWidget { +public class ImageLibraryAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(ImageLibraryAjax.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("ImageLibraryAjax..."); - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.debug("No permission to access image library"); - context.setJson("{\"images\":[],\"total\":0}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ImageLibraryAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Get pagination parameters diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageMetadataAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageMetadataAjax.java index 1808d862..c7cba5a0 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageMetadataAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageMetadataAjax.java @@ -20,10 +20,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.Image; import com.simisinc.platform.infrastructure.persistence.cms.ImageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Saves image metadata (title, alt text, description) in the visual image editor @@ -31,35 +32,31 @@ * @author matt rajkowski * @created 1/31/26 9:30 AM */ -public class ImageMetadataAjax extends GenericWidget { +public class ImageMetadataAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908894L; private static Log LOG = LogFactory.getLog(ImageMetadataAjax.class); @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("ImageMetadataAjax..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\": false, \"error\": \"Access denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ImageMetadataAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long imageId = context.getParameterAsLong("id", -1); if (imageId == -1) { - context.setJson("{\"success\": false, \"error\": \"Image 'ID' required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Image ID required"); } Image image = ImageRepository.findById(imageId); if (image == null) { - context.setJson("{\"success\": false, \"error\": \"Image not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Image not found"); } image.setTitle(StringUtils.trimToNull(context.getParameter("title"))); @@ -72,8 +69,7 @@ public WidgetContext post(WidgetContext context) { if (saved != null) { context.setJson("{\"success\": true, \"message\": \"Image metadata saved successfully\"}"); } else { - context.setJson("{\"success\": false, \"message\": \"Failed to save image metadata\"}"); - context.setSuccess(false); + return context.writeError("Failed to save image metadata"); } return context; diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageScaleDownAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageScaleDownAjax.java index 27f1f5dd..f9c8ca02 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageScaleDownAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageScaleDownAjax.java @@ -20,12 +20,13 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.ScaleDownImageCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Image; import com.simisinc.platform.infrastructure.persistence.cms.ImageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Scales down an image proportionally and saves it as a new version @@ -33,44 +34,40 @@ * @author matt rajkowski * @created 2/4/26 11:30 PM */ -public class ImageScaleDownAjax extends GenericWidget { +public class ImageScaleDownAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908895L; private static Log LOG = LogFactory.getLog(ImageScaleDownAjax.class); - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("ImageScaleDownAjax..."); // Check permissions - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.warn("User does not have permission to scale images"); - context.setJson("{\"status\":\"error\",\"message\":\"Permission denied\"}"); - return context; + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ImageScaleDownAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Get the image ID long imageId = context.getParameterAsLong("imageId", -1); if (imageId == -1) { LOG.warn("Image ID not provided"); - context.setJson("{\"status\":\"error\",\"message\":\"Image ID is required\"}"); - return context; + return context.writeError("Image ID required"); } // Get the scale percentage int scalePercentage = context.getParameterAsInt("scalePercentage", -1); if (scalePercentage == -1 || scalePercentage >= 100 || scalePercentage < 10) { LOG.warn("Invalid scale percentage: " + scalePercentage); - context.setJson("{\"status\":\"error\",\"message\":\"Scale percentage must be between 10 and 99\"}"); - return context; + return context.writeError("Scale percentage must be between 10 and 99"); } // Load the image Image image = ImageRepository.findById(imageId); if (image == null) { LOG.warn("Image not found: " + imageId); - context.setJson("{\"status\":\"error\",\"message\":\"Image not found\"}"); - return context; + return context.writeError("Image not found"); } try { @@ -96,7 +93,7 @@ public WidgetContext post(WidgetContext context) { } catch (DataException e) { LOG.error("Error scaling image " + imageId, e); - context.setJson("{\"status\":\"error\",\"message\":\"" + JsonCommand.toJson(e.getMessage()) + "\"}"); + return context.writeError("Failed to scale image: " + e.getMessage()); } return context; diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageThumbnailAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageThumbnailAjax.java index af9a054e..755c4c43 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageThumbnailAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageThumbnailAjax.java @@ -20,12 +20,13 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.GenerateThumbnailCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Image; import com.simisinc.platform.infrastructure.persistence.cms.ImageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Generates a thumbnail for an image @@ -33,36 +34,33 @@ * @author matt rajkowski * @created 1/31/26 4:45 PM */ -public class ImageThumbnailAjax extends GenericWidget { +public class ImageThumbnailAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908894L; private static Log LOG = LogFactory.getLog(ImageThumbnailAjax.class); - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("ImageThumbnailAjax..."); // Check permissions - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.warn("User does not have permission to generate thumbnails"); - context.setJson("{\"status\":\"error\",\"message\":\"Permission denied\"}"); - return context; + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ImageThumbnailAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Get the image ID long imageId = context.getParameterAsLong("imageId", -1); if (imageId == -1) { LOG.warn("Image ID not provided"); - context.setJson("{\"status\":\"error\",\"message\":\"Image ID is required\"}"); - return context; + return context.writeError("Image ID required"); } // Load the image Image image = ImageRepository.findById(imageId); if (image == null) { LOG.warn("Image not found: " + imageId); - context.setJson("{\"status\":\"error\",\"message\":\"Image not found\"}"); - return context; + return context.writeError("Image not found"); } try { @@ -92,7 +90,7 @@ public WidgetContext post(WidgetContext context) { } catch (DataException e) { LOG.error("Error generating thumbnail for image " + imageId, e); - context.setJson("{\"status\":\"error\",\"message\":\"" + JsonCommand.toJson(e.getMessage()) + "\"}"); + return context.writeError("Failed to generate thumbnail: " + e.getMessage()); } return context; diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageUploadAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageUploadAjax.java index 58120bab..3b2559e5 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageUploadAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageUploadAjax.java @@ -30,6 +30,7 @@ import org.thymeleaf.util.StringUtils; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.SaveImageCommand; import com.simisinc.platform.application.cms.SaveImageVersionCommand; import com.simisinc.platform.application.cms.ValidateImageCommand; @@ -38,8 +39,8 @@ import com.simisinc.platform.domain.model.cms.Image; import com.simisinc.platform.domain.model.cms.ImageVersion; import com.simisinc.platform.infrastructure.persistence.cms.ImageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles multiple image uploads for the image editor @@ -47,7 +48,7 @@ * @author matt rajkowski * @created 2/3/26 8:00 PM */ -public class ImageUploadAjax extends GenericWidget { +public class ImageUploadAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(ImageUploadAjax.class); @@ -58,15 +59,15 @@ public class ImageUploadAjax extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { // /json/imageUpload LOG.debug("ImageUploadAjax..."); - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\": false, \"error\": \"You do not have permission to upload images.\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ImageUploadAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } StringBuilder jsonResponse = new StringBuilder(); @@ -78,7 +79,7 @@ public WidgetContext post(WidgetContext context) { // Check if this is a version upload (imageId parameter present) long imageId = context.getParameterAsLong("imageId", -1); boolean isVersionUpload = (imageId > -1); - + // Get all file parts from the request Collection fileParts = context.getParts(); List uploadedImages = new ArrayList<>(); @@ -143,7 +144,7 @@ public WidgetContext post(WidgetContext context) { if (existingImage == null) { throw new DataException("Image not found with ID: " + imageId); } - + ImageVersion versionBean = new ImageVersion(); versionBean.setFilename(imageBean.getFilename()); versionBean.setFileServerPath(imageBean.getFileServerPath()); @@ -152,7 +153,7 @@ public WidgetContext post(WidgetContext context) { versionBean.setWidth(imageBean.getWidth()); versionBean.setHeight(imageBean.getHeight()); versionBean.setCreatedBy(context.getUserId()); - + ImageVersion version = SaveImageVersionCommand.addNewVersion(imageId, versionBean); if (version == null) { LOG.warn("Failed to save image version: " + submittedFilename); @@ -161,11 +162,11 @@ public WidgetContext post(WidgetContext context) { } continue; } - + // Add the updated image to the response uploadedImages.add(existingImage); LOG.debug("Uploaded image version: " + version.getFilename() + " for image ID: " + imageId); - + } else { // Save as a new image Image image = SaveImageCommand.saveImage(imageBean); @@ -220,30 +221,16 @@ public WidgetContext post(WidgetContext context) { jsonResponse.append("]"); jsonResponse.append("}"); + context.setJson(jsonResponse.toString()); + return context; } catch (DataException e) { LOG.warn("Error during image upload: " + e.getMessage()); - jsonResponse = new StringBuilder(); - jsonResponse.append("{"); - jsonResponse.append("\"success\": false,"); - jsonResponse.append("\"error\": \"").append(JsonCommand.toJson(e.getMessage())).append("\""); - jsonResponse.append("}"); - context.setJson(jsonResponse.toString()); - context.setSuccess(false); - return context; + return context.writeError("Failed to upload image: " + e.getMessage()); } catch (Exception e) { LOG.error("Unexpected error during image upload: " + e.getMessage(), e); - jsonResponse = new StringBuilder(); - jsonResponse.append("{"); - jsonResponse.append("\"success\": false,"); - jsonResponse.append("\"error\": \"An unexpected error occurred during image upload\""); - jsonResponse.append("}"); - context.setJson(jsonResponse.toString()); - context.setSuccess(false); - return context; + return context.writeError("An unexpected error occurred during image upload"); } - context.setJson(jsonResponse.toString()); - return context; } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionDeleteAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionDeleteAjax.java index 19428e95..fb930a1d 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionDeleteAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionDeleteAjax.java @@ -19,10 +19,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.ImageVersion; import com.simisinc.platform.infrastructure.persistence.cms.ImageVersionRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Deletes an image version in the visual image editor @@ -30,53 +31,45 @@ * @author matt rajkowski * @created 1/31/26 9:50 AM */ -public class ImageVersionDeleteAjax extends GenericWidget { +public class ImageVersionDeleteAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908898L; private static Log LOG = LogFactory.getLog(ImageVersionDeleteAjax.class); @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("ImageVersionDeleteAjax..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\": false, \"error\": \"Access denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ImageVersionDeleteAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long versionId = context.getParameterAsLong("versionId", -1); if (versionId == -1) { - context.setJson("{\"success\": false, \"error\": \"Version 'ID' required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Version ID required"); } ImageVersion version = ImageVersionRepository.findById(versionId); if (version == null) { - context.setJson("{\"success\": false, \"error\": \"Version not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Version not found"); } // Prevent deleting the current version if (version.getIsCurrent()) { - context.setJson("{\"success\": false, \"error\": \"Cannot delete the current version\"}"); - context.setSuccess(false); - return context; + return context.writeError("Cannot delete the current version"); } try { ImageVersionRepository.remove(version); context.setJson("{\"success\": true, \"message\": \"Version deleted successfully\"}"); + return context; } catch (Exception e) { LOG.error("Error deleting version", e); - context.setJson("{\"success\": false, \"error\": \"Failed to delete version: " + e.getMessage() + "\"}"); - context.setSuccess(false); + return context.writeError("Failed to delete version: " + e.getMessage()); } - - return context; } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionRevertAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionRevertAjax.java index fed5a950..3977d997 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionRevertAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionRevertAjax.java @@ -20,10 +20,11 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.SetCurrentImageVersionCommand; import com.simisinc.platform.domain.model.cms.Image; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Reverts an image to a previous version in the visual image editor @@ -31,21 +32,21 @@ * @author matt rajkowski * @created 1/31/26 9:45 AM */ -public class ImageVersionRevertAjax extends GenericWidget { +public class ImageVersionRevertAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908897L; private static Log LOG = LogFactory.getLog(ImageVersionRevertAjax.class); @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("ImageVersionRevertAjax..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\": false, \"error\": \"Access denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ImageVersionRevertAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long imageId = context.getParameterAsLong("imageId", -1); @@ -61,20 +62,17 @@ public WidgetContext post(WidgetContext context) { Image image = SetCurrentImageVersionCommand.setCurrentVersion(imageId, versionId, context.getUserId()); if (image != null) { context.setJson("{\"success\": true, \"message\": \"Reverted to version " + image.getVersionNumber() + "\"}"); + return context; } else { - context.setJson("{\"success\": false, \"error\": \"Failed to update image\"}"); - context.setSuccess(false); + return context.writeError("Failed to update image"); } } catch (DataException e) { LOG.error("Error reverting version", e); - context.setJson("{\"success\": false, \"error\": \"" + e.getMessage() + "\"}"); - context.setSuccess(false); + return context.writeError(e.getMessage()); } catch (Exception e) { LOG.error("Error reverting version", e); - context.setJson("{\"success\": false, \"error\": \"Failed to revert: " + e.getMessage() + "\"}"); - context.setSuccess(false); + return context.writeError("Failed to revert: " + e.getMessage()); } - return context; } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionsAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionsAjax.java index 9bda3151..0d2ceaf0 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionsAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/ImageVersionsAjax.java @@ -22,11 +22,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.ImageVersion; import com.simisinc.platform.infrastructure.persistence.cms.ImageVersionRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns image version history for the visual image editor @@ -34,27 +35,26 @@ * @author matt rajkowski * @created 1/31/26 9:40 AM */ -public class ImageVersionsAjax extends GenericWidget { +public class ImageVersionsAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908896L; private static Log LOG = LogFactory.getLog(ImageVersionsAjax.class); @Override - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("ImageVersionsAjax..."); // Restrict access to editors - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"versions\":[]}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + ImageVersionsAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long imageId = context.getParameterAsLong("imageId", -1); if (imageId == -1) { - context.setJson("{\"success\": false, \"error\": \"Image 'ID' required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Image ID required"); } // Query versions diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageAddToHierarchyJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageAddToHierarchyJsonService.java index cc385fb7..c48cc1fc 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageAddToHierarchyJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageAddToHierarchyJsonService.java @@ -22,7 +22,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.simisinc.platform.application.json.JsonCommand; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.WebPage; import com.simisinc.platform.domain.model.cms.WebPageHierarchy; import com.simisinc.platform.infrastructure.database.AutoRollback; @@ -30,8 +30,8 @@ import com.simisinc.platform.infrastructure.database.DB; import com.simisinc.platform.infrastructure.persistence.cms.WebPageHierarchyRepository; import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/pages/add-to-hierarchy endpoint @@ -40,7 +40,7 @@ * @author matt rajkowski * @created 2/7/26 5:00 PM */ -public class PageAddToHierarchyJsonService extends GenericWidget { +public class PageAddToHierarchyJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(PageAddToHierarchyJsonService.class); @@ -51,11 +51,12 @@ public class PageAddToHierarchyJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + PageAddToHierarchyJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -63,12 +64,12 @@ public WidgetContext post(WidgetContext context) { long parentPageId = context.getParameterAsLong("parentPageId", -1); if (pageId == -1) { - return writeError(context, "Page ID is required"); + return context.writeError("Page ID is required"); } WebPage page = WebPageRepository.findById(pageId); if (page == null) { - return writeError(context, "Page not found"); + return context.writeError("Page not found"); } Long parentId = parentPageId > 0 ? parentPageId : null; @@ -79,14 +80,14 @@ public WidgetContext post(WidgetContext context) { WebPageHierarchy existingRecord = WebPageHierarchyRepository.findByPageId(connection, pageId); if (existingRecord != null) { - return writeOk(context, "{\"message\":\"Page is already in hierarchy\"}", null); + return context.writeOk("{\"message\":\"Page is already in hierarchy\"}", null); } WebPageHierarchy parentRecord = null; if (parentId != null) { parentRecord = WebPageHierarchyRepository.findByPageId(connection, parentId); if (parentRecord == null) { - return writeError(context, "Parent page not found in hierarchy"); + return context.writeError("Parent page not found in hierarchy"); } } @@ -108,33 +109,11 @@ public WidgetContext post(WidgetContext context) { transaction.commit(); } - return writeOk(context, "{\"message\":\"Page added to hierarchy\"}", null); + return context.writeOk("{\"message\":\"Page added to hierarchy\"}", null); } catch (Exception e) { LOG.error("Error adding page to hierarchy: " + e.getMessage(), e); - return writeError(context, "An unexpected error occurred"); + return context.writeError("An unexpected error occurred"); } } - - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(message) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageChildrenJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageChildrenJsonService.java index 15fb9c9c..9a65c0f6 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageChildrenJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageChildrenJsonService.java @@ -22,11 +22,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.LoadPageTreeCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.PageTreeNode; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX GET requests for /json/pages/children endpoint @@ -35,7 +36,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class PageChildrenJsonService extends GenericWidget { +public class PageChildrenJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(PageChildrenJsonService.class); @@ -46,20 +47,22 @@ public class PageChildrenJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + PageChildrenJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { // Get parent ID parameter (null means root level pages) String parentIdParam = context.getParameter("parentId"); Long parentId = null; - + // Handle various "no parent" values: null, "null", "0", "undefined", empty string - if (StringUtils.isNotBlank(parentIdParam) && !"null".equals(parentIdParam) && !"0".equals(parentIdParam) && !"undefined".equals(parentIdParam)) { + if (StringUtils.isNotBlank(parentIdParam) && !"null".equals(parentIdParam) && !"0".equals(parentIdParam) + && !"undefined".equals(parentIdParam)) { parentId = Long.parseLong(parentIdParam); } @@ -89,33 +92,11 @@ public WidgetContext execute(WidgetContext context) { json.append("]"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error loading page children: " + e.getMessage(), e); - return writeError(context, e.getMessage()); - } - } - - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); + return context.writeError(e.getMessage()); } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageContentBlocksJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageContentBlocksJsonService.java index ddef1a72..0f61431c 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageContentBlocksJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageContentBlocksJsonService.java @@ -30,6 +30,7 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.LoadUserCommand; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.LoadContentCommand; import com.simisinc.platform.application.cms.WebPageXmlLayoutCommand; import com.simisinc.platform.application.json.JsonCommand; @@ -38,11 +39,11 @@ import com.simisinc.platform.domain.model.cms.WebPage; import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; import com.simisinc.platform.presentation.controller.Column; +import com.simisinc.platform.presentation.controller.JsonServiceContext; import com.simisinc.platform.presentation.controller.Page; import com.simisinc.platform.presentation.controller.Section; import com.simisinc.platform.presentation.controller.Widget; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns the content blocks referenced by a page's XML layout @@ -51,7 +52,7 @@ * @author matt rajkowski * @created 2/14/26 10:00 AM */ -public class PageContentBlocksJsonService extends GenericWidget { +public class PageContentBlocksJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908894L; private static Log LOG = LogFactory.getLog(PageContentBlocksJsonService.class); @@ -65,23 +66,24 @@ public class PageContentBlocksJsonService extends GenericWidget { // Pattern to match ${uniqueId:example-include} private static final Pattern DIRECTIVE_PATTERN = Pattern.compile("\\$\\{uniqueId:([^}]+)\\}"); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { // Check permissions - if (!context.hasRole("admin") && !context.hasRole("content-manager") && !context.hasRole("content-editor")) { - return writeError(context, "Permission denied"); + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + PageContentBlocksJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { String link = context.getParameter("link"); if (StringUtils.isBlank(link)) { - return writeError(context, "Page link is required"); + return context.writeError("Page link is required"); } // Load the web page WebPage webPage = WebPageRepository.findByLink(link); if (webPage == null) { - return writeError(context, "Page not found"); + return context.writeError("Page not found"); } // Collect unique content IDs from the page layout with fallback HTML @@ -114,7 +116,7 @@ public WidgetContext execute(WidgetContext context) { StringBuilder dataJson = new StringBuilder(); dataJson.append("["); boolean first = true; - + // Add existing content blocks for (Content content : allContentBlocks) { if (!first) { @@ -123,7 +125,7 @@ public WidgetContext execute(WidgetContext context) { first = false; appendContentJson(dataJson, content); } - + // Add referenced blocks that don't have records yet (marked as "new") for (Map.Entry entry : uniqueIdToFallbackHtml.entrySet()) { String uniqueId = entry.getKey(); @@ -136,14 +138,14 @@ public WidgetContext execute(WidgetContext context) { appendNewContentJson(dataJson, uniqueId, fallbackHtml); } } - + dataJson.append("]"); - return writeOk(context, dataJson.toString(), null); + return context.writeOk(dataJson.toString(), null); } catch (Exception e) { LOG.error("Error loading page content blocks: " + e.getMessage(), e); - return writeError(context, "Error loading content blocks"); + return context.writeError("Error loading content blocks"); } } @@ -252,38 +254,17 @@ private void appendNewContentJson(StringBuilder json, String uniqueId, String fa json.append("\"id\":-1,"); json.append("\"uniqueId\":\"").append(JsonCommand.toJson(uniqueId)).append("\","); json.append("\"isNew\":true,"); - + // Use fallback HTML for snippet if available String snippet = StringUtils.isNotBlank(fallbackHtml) ? StringUtils.truncate(fallbackHtml, 120) : "No content yet"; json.append("\"snippet\":\"").append(JsonCommand.toJson(snippet)).append("\","); - + // Include the full fallback HTML json.append("\"fallbackHtml\":\"").append(JsonCommand.toJson(StringUtils.defaultString(fallbackHtml))).append("\","); - + json.append("\"hasDraft\":false,"); json.append("\"modified\":\"\","); json.append("\"modifiedBy\":\"\""); json.append("}"); } - - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageRemoveFromHierarchyJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageRemoveFromHierarchyJsonService.java index 9da11651..519f4573 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageRemoveFromHierarchyJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageRemoveFromHierarchyJsonService.java @@ -22,14 +22,14 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.simisinc.platform.application.json.JsonCommand; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.WebPageHierarchy; import com.simisinc.platform.infrastructure.database.AutoRollback; import com.simisinc.platform.infrastructure.database.AutoStartTransaction; import com.simisinc.platform.infrastructure.database.DB; import com.simisinc.platform.infrastructure.persistence.cms.WebPageHierarchyRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/pages/remove-from-hierarchy endpoint @@ -38,7 +38,7 @@ * @author matt rajkowski * @created 2/7/26 5:00 PM */ -public class PageRemoveFromHierarchyJsonService extends GenericWidget { +public class PageRemoveFromHierarchyJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(PageRemoveFromHierarchyJsonService.class); @@ -49,17 +49,18 @@ public class PageRemoveFromHierarchyJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + PageRemoveFromHierarchyJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { long pageId = context.getParameterAsLong("pageId", -1); if (pageId == -1) { - return writeError(context, "Page ID is required"); + return context.writeError("Page ID is required"); } try (Connection connection = DB.getConnection(); @@ -68,40 +69,19 @@ public WidgetContext post(WidgetContext context) { WebPageHierarchy record = WebPageHierarchyRepository.findByPageId(connection, pageId); if (record == null || StringUtils.isBlank(record.getPath())) { - return writeError(context, "Page hierarchy record not found"); + return context.writeError("Page hierarchy record not found"); } WebPageHierarchyRepository.removeByPath(connection, record.getPath()); transaction.commit(); } - return writeOk(context, "{\"message\":\"Page removed from hierarchy\"}", null); + return context.writeOk("{\"message\":\"Page removed from hierarchy\"}", null); } catch (Exception e) { LOG.error("Error removing page from hierarchy: " + e.getMessage(), e); - return writeError(context, "An unexpected error occurred"); + return context.writeError("An unexpected error occurred"); } } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageReorderJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageReorderJsonService.java index e5b6dd3a..a248c382 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageReorderJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PageReorderJsonService.java @@ -19,11 +19,10 @@ import java.sql.Connection; import java.sql.Timestamp; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.simisinc.platform.application.json.JsonCommand; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.WebPage; import com.simisinc.platform.domain.model.cms.WebPageHierarchy; import com.simisinc.platform.infrastructure.database.AutoRollback; @@ -31,8 +30,8 @@ import com.simisinc.platform.infrastructure.database.DB; import com.simisinc.platform.infrastructure.persistence.cms.WebPageHierarchyRepository; import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/pages/reorder endpoint @@ -41,7 +40,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class PageReorderJsonService extends GenericWidget { +public class PageReorderJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(PageReorderJsonService.class); @@ -52,11 +51,12 @@ public class PageReorderJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + PageReorderJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -65,13 +65,13 @@ public WidgetContext post(WidgetContext context) { String position = context.getParameter("position"); // 'before', 'after', 'inside' if (pageId == -1) { - return writeError(context, "Page ID is required"); + return context.writeError("Page ID is required"); } // Load the page WebPage page = WebPageRepository.findById(pageId); if (page == null) { - return writeError(context, "Page not found"); + return context.writeError("Page not found"); } Long newParentId = null; @@ -85,7 +85,7 @@ public WidgetContext post(WidgetContext context) { WebPageHierarchy currentRecord = WebPageHierarchyRepository.findByPageId(connection, pageId); if (currentRecord == null) { - return writeError(context, "Page hierarchy record not found"); + return context.writeError("Page hierarchy record not found"); } oldPath = currentRecord.getPath(); @@ -96,10 +96,11 @@ public WidgetContext post(WidgetContext context) { newParentId = targetPageId; WebPageHierarchy targetRecord = WebPageHierarchyRepository.findByPageId(connection, targetPageId); if (targetRecord == null) { - return writeError(context, "Target page not found in hierarchy"); + return context.writeError("Target page not found in hierarchy"); } - if (targetRecord.getPath() != null && currentRecord.getPath() != null && targetRecord.getPath().startsWith(currentRecord.getPath())) { - return writeError(context, "Cannot move a page beneath its own descendant"); + if (targetRecord.getPath() != null && currentRecord.getPath() != null + && targetRecord.getPath().startsWith(currentRecord.getPath())) { + return context.writeError("Cannot move a page beneath its own descendant"); } newSortOrder = WebPageHierarchyRepository.getNextSortOrder(connection, newParentId); newDepth = targetRecord.getDepth() + 1; @@ -107,11 +108,11 @@ public WidgetContext post(WidgetContext context) { // Insert before or after the target as sibling WebPageHierarchy targetRecord = WebPageHierarchyRepository.findByPageId(connection, targetPageId); if (targetRecord == null) { - return writeError(context, "Target page not found in hierarchy"); + return context.writeError("Target page not found in hierarchy"); } newParentId = targetRecord.getParentPageId(); newDepth = targetRecord.getDepth(); - + // Shift sort orders to make space if ("before".equals(position)) { newSortOrder = targetRecord.getSortOrder(); @@ -125,10 +126,11 @@ public WidgetContext post(WidgetContext context) { newParentId = targetPageId; WebPageHierarchy targetRecord = WebPageHierarchyRepository.findByPageId(connection, targetPageId); if (targetRecord == null) { - return writeError(context, "Target page not found in hierarchy"); + return context.writeError("Target page not found in hierarchy"); } - if (targetRecord.getPath() != null && currentRecord.getPath() != null && targetRecord.getPath().startsWith(currentRecord.getPath())) { - return writeError(context, "Cannot move a page beneath its own descendant"); + if (targetRecord.getPath() != null && currentRecord.getPath() != null + && targetRecord.getPath().startsWith(currentRecord.getPath())) { + return context.writeError("Cannot move a page beneath its own descendant"); } newSortOrder = WebPageHierarchyRepository.getNextSortOrder(connection, newParentId); newDepth = targetRecord.getDepth() + 1; @@ -138,7 +140,7 @@ public WidgetContext post(WidgetContext context) { newSortOrder = WebPageHierarchyRepository.getNextSortOrder(connection, null); newDepth = 0; } else { - return writeError(context, "Invalid target page ID"); + return context.writeError("Invalid target page ID"); } String parentPath = "/"; @@ -158,7 +160,7 @@ public WidgetContext post(WidgetContext context) { WebPageHierarchy updatedRecord = WebPageHierarchyRepository.save(connection, currentRecord); if (updatedRecord == null) { - return writeError(context, "Failed to update page hierarchy"); + return context.writeError("Failed to update page hierarchy"); } if (oldPath != null && !oldPath.equals(newPath)) { @@ -179,33 +181,12 @@ public WidgetContext post(WidgetContext context) { json.append("\"message\": \"Page reordered successfully\""); json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error reordering page: " + e.getMessage(), e); - return writeError(context, "An unexpected error occurred"); - } - } - - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); + return context.writeError("An unexpected error occurred"); } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PrototypeWidget.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PrototypeWidget.java index b2867117..19849416 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/PrototypeWidget.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/PrototypeWidget.java @@ -18,6 +18,7 @@ import com.simisinc.platform.presentation.controller.WidgetContext; import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.application.admin.PermissionEngine; /** * Shows up for CMS managers @@ -34,7 +35,8 @@ public class PrototypeWidget extends GenericWidget { public WidgetContext execute(WidgetContext context) { // This widget is only for admins and content managers - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { return null; } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveStylesheetAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveStylesheetAjax.java index 86a3c277..15020f5d 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveStylesheetAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveStylesheetAjax.java @@ -20,13 +20,14 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Stylesheet; import com.simisinc.platform.domain.model.cms.WebPage; import com.simisinc.platform.infrastructure.persistence.cms.StylesheetRepository; import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Saves a web page's stylesheet/CSS from the visual page editor CSS tab @@ -35,21 +36,19 @@ * @author matt rajkowski * @created 1/10/26 10:00 AM */ -public class SaveStylesheetAjax extends GenericWidget { +public class SaveStylesheetAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908897L; private static Log LOG = LogFactory.getLog(SaveStylesheetAjax.class); - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("SaveStylesheetAjax..."); - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.debug("No permission to save stylesheet"); - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SaveStylesheetAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Determine the page link @@ -57,18 +56,14 @@ public WidgetContext post(WidgetContext context) { LOG.debug("Saving stylesheet for: " + webPageLink); if (StringUtils.isBlank(webPageLink)) { LOG.debug("Page link is empty"); - context.setJson("{\"success\":false,\"message\":\"Page link is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Link is required"); } // Retrieve the existing web page WebPage page = WebPageRepository.findByLink(webPageLink); if (page == null) { LOG.debug("Web page not found for link: " + webPageLink); - context.setJson("{\"success\":false,\"message\":\"Page not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Page not found"); } // Get the CSS content from the request @@ -103,6 +98,7 @@ public WidgetContext post(WidgetContext context) { sb.append("}"); context.setJson(sb.toString()); LOG.debug("Stylesheet saved successfully for page: " + webPageLink); + return context; } else { // If CSS was blank and stylesheet was removed, that's still a success if (StringUtils.isBlank(css)) { @@ -116,23 +112,14 @@ public WidgetContext post(WidgetContext context) { sb.append("}"); context.setJson(sb.toString()); LOG.debug("Stylesheet removed for page: " + webPageLink); + return context; } else { - context.setJson("{\"success\":false,\"message\":\"Failed to save stylesheet\"}"); - context.setSuccess(false); - LOG.debug("Save returned null for page: " + webPageLink); + return context.writeError("Failed to save stylesheet"); } } } catch (Exception e) { LOG.error("Error saving stylesheet: " + e.getMessage(), e); - StringBuilder sb = new StringBuilder(); - sb.append("{"); - sb.append("\"success\":false,"); - sb.append("\"message\":\"").append(JsonCommand.toJson("Error saving stylesheet: " + e.getMessage())).append("\""); - sb.append("}"); - context.setJson(sb.toString()); - context.setSuccess(false); + return context.writeError("Error saving stylesheet: " + e.getMessage()); } - - return context; } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveWebPageAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveWebPageAjax.java index 92b474a8..f9e90cd9 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveWebPageAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveWebPageAjax.java @@ -21,13 +21,14 @@ import org.apache.commons.logging.LogFactory; import org.apache.commons.text.WordUtils; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.SaveWebPageCommand; import com.simisinc.platform.application.cms.WebPageJsonToXMLCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.WebPage; import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Saves a web page's layout from the visual page editor @@ -36,21 +37,19 @@ * @author matt rajkowski * @created 12/21/25 10:00 AM */ -public class SaveWebPageAjax extends GenericWidget { +public class SaveWebPageAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908894L; private static Log LOG = LogFactory.getLog(SaveWebPageAjax.class); - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("SaveWebPageAjax..."); - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.debug("No permission to save web page"); - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SaveWebPageAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Determine the page link @@ -58,9 +57,7 @@ public WidgetContext post(WidgetContext context) { LOG.debug("Saving page: " + webPageLink); if (StringUtils.isBlank(webPageLink)) { LOG.debug("Page link is empty"); - context.setJson("{\"success\":false,\"message\":\"Page link is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Link is required"); } // Retrieve the web page @@ -83,9 +80,7 @@ public WidgetContext post(WidgetContext context) { String designerData = context.getParameter("designerData"); if (StringUtils.isBlank(designerData)) { LOG.debug("No designer data provided"); - context.setJson("{\"success\":false,\"message\":\"Layout data is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Layout data is required"); } // Convert the JSON layout data to XML format @@ -94,14 +89,7 @@ public WidgetContext post(WidgetContext context) { pageXml = WebPageJsonToXMLCommand.convertDesignerJsonToXml(designerData); } catch (Exception e) { LOG.error("Error converting JSON layout to XML: " + e.getMessage(), e); - StringBuilder sb = new StringBuilder(); - sb.append("{"); - sb.append("\"success\":false,"); - sb.append("\"message\":\"").append(JsonCommand.toJson("Error processing layout: " + e.getMessage())).append("\""); - sb.append("}"); - context.setJson(sb.toString()); - context.setSuccess(false); - return context; + return context.writeError("Error processing layout: " + e.getMessage()); } page.setPageXml(pageXml); @@ -120,23 +108,14 @@ public WidgetContext post(WidgetContext context) { sb.append("}"); context.setJson(sb.toString()); LOG.debug("Page saved successfully: " + webPageLink); + return context; } else { - context.setJson("{\"success\":false,\"message\":\"Failed to save page\"}"); - context.setSuccess(false); - LOG.debug("Save returned null for page: " + webPageLink); + return context.writeError("Failed to save page"); } } catch (Exception e) { LOG.error("Error saving page: " + e.getMessage(), e); - StringBuilder sb = new StringBuilder(); - sb.append("{"); - sb.append("\"success\":false,"); - sb.append("\"message\":\"").append(JsonCommand.toJson(e.getMessage())).append("\""); - sb.append("}"); - context.setJson(sb.toString()); - context.setSuccess(false); + return context.writeError("Error saving page: " + e.getMessage()); } - - return context; } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveWebPageInfoAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveWebPageInfoAjax.java index 78efa033..8147ec41 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveWebPageInfoAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SaveWebPageInfoAjax.java @@ -16,18 +16,20 @@ package com.simisinc.platform.presentation.widgets.cms; +import java.math.BigDecimal; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.SaveWebPageCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.WebPage; import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.math.BigDecimal; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Saves a web page's metadata/info from the visual page editor Info tab @@ -36,21 +38,19 @@ * @author matt rajkowski * @created 1/10/26 10:00 AM */ -public class SaveWebPageInfoAjax extends GenericWidget { +public class SaveWebPageInfoAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908895L; private static Log LOG = LogFactory.getLog(SaveWebPageInfoAjax.class); - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { LOG.debug("SaveWebPageInfoAjax..."); - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.debug("No permission to save web page info"); - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SaveWebPageInfoAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Determine the page link @@ -58,54 +58,50 @@ public WidgetContext post(WidgetContext context) { LOG.debug("Saving page info for: " + webPageLink); if (StringUtils.isBlank(webPageLink)) { LOG.debug("Page link is empty"); - context.setJson("{\"success\":false,\"message\":\"Page link is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Link is required"); } // Retrieve the existing web page WebPage page = WebPageRepository.findByLink(webPageLink); if (page == null) { LOG.debug("Web page not found for link: " + webPageLink); - context.setJson("{\"success\":false,\"message\":\"Page not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Page not found"); } // Update the page info fields from the request page.setModifiedBy(context.getUserId()); - + // Title String title = context.getParameter("title"); page.setTitle(StringUtils.trimToNull(title)); - + // Keywords String keywords = context.getParameter("keywords"); page.setKeywords(StringUtils.trimToNull(keywords)); - + // Description String description = context.getParameter("description"); page.setDescription(StringUtils.trimToNull(description)); - + // Image URL (Open Graph) String imageUrl = context.getParameter("imageUrl"); page.setImageUrl(StringUtils.trimToNull(imageUrl)); - + // Draft (inverse of publish) String publishParam = context.getParameter("publish"); boolean publish = "true".equals(publishParam) || "1".equals(publishParam); page.setDraft(!publish); - + // Searchable String searchableParam = context.getParameter("searchable"); boolean searchable = "true".equals(searchableParam) || "1".equals(searchableParam); page.setSearchable(searchable); - + // Show in Sitemap String showInSitemapParam = context.getParameter("showInSitemap"); boolean showInSitemap = "true".equals(showInSitemapParam) || "1".equals(showInSitemapParam); page.setShowInSitemap(showInSitemap); - + // Sitemap Priority String sitemapPriorityParam = context.getParameter("sitemapPriority"); if (StringUtils.isNotBlank(sitemapPriorityParam)) { @@ -117,7 +113,7 @@ public WidgetContext post(WidgetContext context) { // Keep existing value } } - + // Sitemap Change Frequency String sitemapChangeFrequency = context.getParameter("sitemapChangeFrequency"); page.setSitemapChangeFrequency(StringUtils.trimToNull(sitemapChangeFrequency)); @@ -144,24 +140,11 @@ public WidgetContext post(WidgetContext context) { } } catch (DataException e) { LOG.error("Data validation error saving page info: " + e.getMessage()); - StringBuilder sb = new StringBuilder(); - sb.append("{"); - sb.append("\"success\":false,"); - sb.append("\"message\":\"").append(JsonCommand.toJson(e.getMessage())).append("\""); - sb.append("}"); - context.setJson(sb.toString()); - context.setSuccess(false); + return context.writeError("Data validation error: " + e.getMessage()); } catch (Exception e) { LOG.error("Error saving page info: " + e.getMessage(), e); - StringBuilder sb = new StringBuilder(); - sb.append("{"); - sb.append("\"success\":false,"); - sb.append("\"message\":\"").append(JsonCommand.toJson("Error saving page info: " + e.getMessage())).append("\""); - sb.append("}"); - context.setJson(sb.toString()); - context.setSuccess(false); + return context.writeError("Error saving page info: " + e.getMessage()); } - return context; } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapCreateItemJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapCreateItemJsonService.java index b3a5547c..772a0a54 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapCreateItemJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapCreateItemJsonService.java @@ -20,14 +20,15 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.SaveMenuTabCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.MenuItem; import com.simisinc.platform.domain.model.cms.MenuTab; import com.simisinc.platform.infrastructure.cache.CacheManager; import com.simisinc.platform.infrastructure.persistence.cms.MenuTabRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/sitemap/create-item endpoint @@ -36,7 +37,7 @@ * @author matt rajkowski * @created 2/9/26 8:30 PM */ -public class SitemapCreateItemJsonService extends GenericWidget { +public class SitemapCreateItemJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908894L; private static Log LOG = LogFactory.getLog(SitemapCreateItemJsonService.class); @@ -44,15 +45,16 @@ public class SitemapCreateItemJsonService extends GenericWidget { /** * Handles POST requests to create a new menu item * - * @param context the widget context + * @param context the JSON service context * @return context with JSON response */ @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SitemapCreateItemJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -62,7 +64,7 @@ public WidgetContext post(WidgetContext context) { String link = context.getParameter("link"); if (tabId == -1) { - return writeError(context, "Tab ID is required"); + return context.writeError("Tab ID is required"); } if (StringUtils.isBlank(title)) { @@ -70,18 +72,18 @@ public WidgetContext post(WidgetContext context) { } if (StringUtils.isBlank(link)) { - return writeError(context, "Link is required"); + return context.writeError("Link is required"); } // Load the menu tab MenuTab menuTab = MenuTabRepository.findById(tabId); if (menuTab == null) { - return writeError(context, "Menu tab not found"); + return context.writeError("Menu tab not found"); } // Check if this is the first tab and has a link of '/', if so, prevent adding items to it if (MenuTabRepository.findAll().get(0).getId() == tabId && "/".equals(menuTab.getLink())) { - return writeError(context, "Cannot add menu items to the home tab"); + return context.writeError("Cannot add menu items to the home tab"); } // Create the new menu item @@ -99,32 +101,11 @@ public WidgetContext post(WidgetContext context) { json.append("\"link\": \"").append(JsonCommand.toJson(savedItem.getLink())).append("\""); json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error creating menu item: " + e.getMessage(), e); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } } - - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapCreateTabJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapCreateTabJsonService.java index 9a00514f..a995c3c1 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapCreateTabJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapCreateTabJsonService.java @@ -20,12 +20,13 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.SaveMenuTabCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.MenuTab; import com.simisinc.platform.infrastructure.cache.CacheManager; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/sitemap/create-tab endpoint @@ -34,7 +35,7 @@ * @author matt rajkowski * @created 2/9/26 8:30 PM */ -public class SitemapCreateTabJsonService extends GenericWidget { +public class SitemapCreateTabJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(SitemapCreateTabJsonService.class); @@ -46,11 +47,12 @@ public class SitemapCreateTabJsonService extends GenericWidget { * @return context with JSON response */ @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SitemapCreateTabJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -59,7 +61,7 @@ public WidgetContext post(WidgetContext context) { String link = context.getParameter("link"); if (StringUtils.isBlank(title)) { - return writeError(context, "Tab title is required"); + return context.writeError("Tab title is required"); } // Create the new menu tab @@ -86,32 +88,11 @@ public WidgetContext post(WidgetContext context) { json.append("\"link\": \"").append(JsonCommand.toJson(savedTab.getLink())).append("\""); json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error creating menu tab: " + e.getMessage(), e); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } } - - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapDeleteItemJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapDeleteItemJsonService.java index 60c5306f..ff777cf6 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapDeleteItemJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapDeleteItemJsonService.java @@ -16,16 +16,15 @@ package com.simisinc.platform.presentation.widgets.cms; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.simisinc.platform.application.json.JsonCommand; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.MenuItem; import com.simisinc.platform.infrastructure.cache.CacheManager; import com.simisinc.platform.infrastructure.persistence.cms.MenuItemRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/sitemap/delete-item endpoint @@ -34,7 +33,7 @@ * @author matt rajkowski * @created 2/9/26 8:45 PM */ -public class SitemapDeleteItemJsonService extends GenericWidget { +public class SitemapDeleteItemJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908896L; private static Log LOG = LogFactory.getLog(SitemapDeleteItemJsonService.class); @@ -45,11 +44,12 @@ public class SitemapDeleteItemJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SitemapDeleteItemJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -57,48 +57,28 @@ public WidgetContext post(WidgetContext context) { long itemId = context.getParameterAsLong("itemId", -1); if (itemId == -1) { - return writeError(context, "Item ID is required"); + return context.writeError("Item ID is required"); } // Load the menu item MenuItem menuItem = MenuItemRepository.findById(itemId); if (menuItem == null) { - return writeError(context, "Menu item not found"); + return context.writeError("Menu item not found"); } // Delete the item if (MenuItemRepository.remove(menuItem)) { // Trigger cache refresh CacheManager.invalidateObjectCacheKey(CacheManager.MENU_TAB_LIST); - return writeOk(context, "{\"id\": " + itemId + "}", null); + return context.writeOk("{\"id\": " + itemId + "}", null); } else { - return writeError(context, "Failed to delete menu item"); + return context.writeError("Failed to delete menu item"); } } catch (Exception e) { LOG.error("Error deleting menu item: " + e.getMessage(), e); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapDeleteTabJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapDeleteTabJsonService.java index 8a512428..ec962a82 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapDeleteTabJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapDeleteTabJsonService.java @@ -16,16 +16,15 @@ package com.simisinc.platform.presentation.widgets.cms; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.simisinc.platform.application.json.JsonCommand; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.MenuTab; import com.simisinc.platform.infrastructure.cache.CacheManager; import com.simisinc.platform.infrastructure.persistence.cms.MenuTabRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/sitemap/delete-tab endpoint @@ -34,7 +33,7 @@ * @author matt rajkowski * @created 2/9/26 8:45 PM */ -public class SitemapDeleteTabJsonService extends GenericWidget { +public class SitemapDeleteTabJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908895L; private static Log LOG = LogFactory.getLog(SitemapDeleteTabJsonService.class); @@ -45,11 +44,12 @@ public class SitemapDeleteTabJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SitemapDeleteTabJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -57,53 +57,31 @@ public WidgetContext post(WidgetContext context) { long tabId = context.getParameterAsLong("tabId", -1); if (tabId == -1) { - return writeError(context, "Tab ID is required"); + return context.writeError("Tab ID is required"); } // Load the menu tab MenuTab menuTab = MenuTabRepository.findById(tabId); if (menuTab == null) { - return writeError(context, "Menu tab not found"); + return context.writeError("Menu tab not found"); } // Check if this is the first tab and has a link of '/', if so, deleting it if (MenuTabRepository.findAll().get(0).getId() == tabId && "/".equals(menuTab.getLink())) { - return writeError(context, "Cannot delete the home tab"); + return context.writeError("Cannot delete the home tab"); } // Delete the tab if (MenuTabRepository.remove(menuTab)) { // Trigger cache refresh CacheManager.invalidateObjectCacheKey(CacheManager.MENU_TAB_LIST); - return writeOk(context, "{\"id\": " + tabId + "}", null); + return context.writeOk("{\"id\": " + tabId + "}", null); } else { - return writeError(context, "Failed to delete menu tab"); + return context.writeError("Failed to delete menu tab"); } - } catch (Exception e) { LOG.error("Error deleting menu tab: " + e.getMessage(), e); - return writeError(context, e.getMessage()); - } - } - - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); + return context.writeError(e.getMessage()); } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapReorderItemJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapReorderItemJsonService.java index 0e02b477..32392747 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapReorderItemJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapReorderItemJsonService.java @@ -16,16 +16,15 @@ package com.simisinc.platform.presentation.widgets.cms; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.simisinc.platform.application.json.JsonCommand; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.MenuItem; import com.simisinc.platform.infrastructure.cache.CacheManager; import com.simisinc.platform.infrastructure.persistence.cms.MenuItemRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/sitemap/reorder-item endpoint @@ -34,7 +33,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class SitemapReorderItemJsonService extends GenericWidget { +public class SitemapReorderItemJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(SitemapReorderItemJsonService.class); @@ -45,11 +44,12 @@ public class SitemapReorderItemJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SitemapReorderItemJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -60,18 +60,18 @@ public WidgetContext post(WidgetContext context) { int newPosition = context.getParameterAsInt("newPosition", 0); if (itemId == -1) { - return writeError(context, "Item ID is required"); + return context.writeError("Item ID is required"); } // At least one of targetItemId or newMenuTabId must be provided if (targetItemId == -1 && newMenuTabId == -1) { - return writeError(context, "Target item or menu ID is required"); + return context.writeError("Target item or menu ID is required"); } // Load the menu item MenuItem item = MenuItemRepository.findById(itemId); if (item == null) { - return writeError(context, "Menu item not found"); + return context.writeError("Menu item not found"); } // If newMenuTabId is provided, update the menu ID @@ -105,33 +105,12 @@ public WidgetContext post(WidgetContext context) { json.append("\"order\": ").append(item.getItemOrder()); json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error reordering menu item: " + e.getMessage(), e); - return writeError(context, "An unexpected error occurred"); + return context.writeError("An unexpected error occurred"); } } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapReorderTabJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapReorderTabJsonService.java index fae26b75..943e931f 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapReorderTabJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapReorderTabJsonService.java @@ -19,16 +19,15 @@ import java.util.ArrayList; import java.util.List; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.simisinc.platform.application.json.JsonCommand; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.MenuTab; import com.simisinc.platform.infrastructure.cache.CacheManager; import com.simisinc.platform.infrastructure.persistence.cms.MenuTabRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/sitemap/reorder-tab endpoint @@ -37,7 +36,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class SitemapReorderTabJsonService extends GenericWidget { +public class SitemapReorderTabJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(SitemapReorderTabJsonService.class); @@ -48,11 +47,12 @@ public class SitemapReorderTabJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SitemapReorderTabJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -61,7 +61,7 @@ public WidgetContext post(WidgetContext context) { long targetTabId = context.getParameterAsLong("targetTabId", -1); if (tabId == -1 || targetTabId == -1) { - return writeError(context, "Tab ID and target tab ID are required"); + return context.writeError("Tab ID and target tab ID are required"); } // Load the dragged tab and target tab @@ -69,7 +69,7 @@ public WidgetContext post(WidgetContext context) { MenuTab targetTab = MenuTabRepository.findById(targetTabId); if (draggedTab == null || targetTab == null) { - return writeError(context, "One or both tabs not found"); + return context.writeError("One or both tabs not found"); } // Get all tabs sorted by current order @@ -88,7 +88,7 @@ public WidgetContext post(WidgetContext context) { } if (insertPosition == -1) { - return writeError(context, "Target tab not found in list"); + return context.writeError("Target tab not found in list"); } // Insert dragged tab at the target position @@ -111,33 +111,12 @@ public WidgetContext post(WidgetContext context) { json.append("\"order\": ").append(draggedTab.getTabOrder()); json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error reordering menu tab: " + e.getMessage(), e); - return writeError(context, "An unexpected error occurred"); + return context.writeError("An unexpected error occurred"); } } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapStructureJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapStructureJsonService.java index bda74649..a5e9073e 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapStructureJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapStructureJsonService.java @@ -22,6 +22,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.MenuItem; import com.simisinc.platform.domain.model.cms.MenuTab; @@ -29,8 +30,8 @@ import com.simisinc.platform.infrastructure.persistence.cms.MenuItemRepository; import com.simisinc.platform.infrastructure.persistence.cms.MenuTabRepository; import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX GET requests for /json/sitemap/structure endpoint @@ -39,7 +40,7 @@ * @author matt rajkowski * @created 2/7/26 3:00 PM */ -public class SitemapStructureJsonService extends GenericWidget { +public class SitemapStructureJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(SitemapStructureJsonService.class); @@ -50,11 +51,12 @@ public class SitemapStructureJsonService extends GenericWidget { * @param context the widget context * @return context with JSON response */ - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SitemapStructureJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -136,33 +138,12 @@ public WidgetContext execute(WidgetContext context) { json.append("]"); json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error loading sitemap structure: " + e.getMessage(), e); - return writeError(context, e.getMessage()); + return context.writeError("An unexpected error occurred"); } } - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } - } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapUpdateItemJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapUpdateItemJsonService.java index 973bc6d1..13fba319 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapUpdateItemJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapUpdateItemJsonService.java @@ -20,13 +20,14 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.SaveMenuTabCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.MenuItem; import com.simisinc.platform.infrastructure.cache.CacheManager; import com.simisinc.platform.infrastructure.persistence.cms.MenuItemRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/sitemap/update-item endpoint @@ -35,7 +36,7 @@ * @author matt rajkowski * @created 2/12/26 9:00 PM */ -public class SitemapUpdateItemJsonService extends GenericWidget { +public class SitemapUpdateItemJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908898L; private static Log LOG = LogFactory.getLog(SitemapUpdateItemJsonService.class); @@ -47,11 +48,12 @@ public class SitemapUpdateItemJsonService extends GenericWidget { * @return context with JSON response */ @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SitemapUpdateItemJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -59,13 +61,13 @@ public WidgetContext post(WidgetContext context) { long itemId = context.getParameterAsLong("itemId", -1); if (itemId == -1) { - return writeError(context, "Item ID is required"); + return context.writeError("Item ID is required"); } // Load the menu item MenuItem menuItem = MenuItemRepository.findById(itemId); if (menuItem == null) { - return writeError(context, "Menu item not found"); + return context.writeError("Menu item not found"); } // Get and validate update parameters @@ -107,32 +109,11 @@ public WidgetContext post(WidgetContext context) { } json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error updating menu item: " + e.getMessage(), e); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } } - - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapUpdateTabJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapUpdateTabJsonService.java index 2e832e83..1750e01c 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapUpdateTabJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/SitemapUpdateTabJsonService.java @@ -20,13 +20,14 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.SaveMenuTabCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.MenuTab; import com.simisinc.platform.infrastructure.cache.CacheManager; import com.simisinc.platform.infrastructure.persistence.cms.MenuTabRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Handles JSON/AJAX POST requests for /json/sitemap/update-tab endpoint @@ -35,7 +36,7 @@ * @author matt rajkowski * @created 2/12/26 9:00 PM */ -public class SitemapUpdateTabJsonService extends GenericWidget { +public class SitemapUpdateTabJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908897L; private static Log LOG = LogFactory.getLog(SitemapUpdateTabJsonService.class); @@ -47,11 +48,12 @@ public class SitemapUpdateTabJsonService extends GenericWidget { * @return context with JSON response */ @Override - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - // Check permissions - require admin or content-manager role - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - return writeError(context, "Permission denied"); + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + SitemapUpdateTabJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } try { @@ -59,18 +61,18 @@ public WidgetContext post(WidgetContext context) { long tabId = context.getParameterAsLong("tabId", -1); if (tabId == -1) { - return writeError(context, "Tab ID is required"); + return context.writeError("Tab ID is required"); } // Load the menu tab MenuTab menuTab = MenuTabRepository.findById(tabId); if (menuTab == null) { - return writeError(context, "Menu tab not found"); + return context.writeError("Menu tab not found"); } // Prevent updating the home tab if (MenuTabRepository.findAll().get(0).getId() == tabId && "/".equals(menuTab.getLink())) { - return writeError(context, "Cannot update the home tab"); + return context.writeError("Cannot update the home tab"); } // Get and validate update parameters @@ -111,32 +113,11 @@ public WidgetContext post(WidgetContext context) { } json.append("}"); - return writeOk(context, json.toString(), null); + return context.writeOk(json.toString(), null); } catch (Exception e) { LOG.error("Error updating menu tab: " + e.getMessage(), e); - return writeError(context, e.getMessage()); + return context.writeError(e.getMessage()); } } - - private WidgetContext writeOk(WidgetContext context, String dataJson, String metaJson) { - StringBuilder json = new StringBuilder(); - json.append("{"); - json.append("\"status\":\"ok\""); - if (dataJson != null) { - json.append(",\"data\":").append(dataJson); - } - if (metaJson != null) { - json.append(",\"meta\":").append(metaJson); - } - json.append("}"); - context.setJson(json.toString()); - return context; - } - - private WidgetContext writeError(WidgetContext context, String message) { - context.setJson("{\"status\":\"error\",\"error\":\"" + JsonCommand.toJson(StringUtils.defaultString(message)) + "\"}"); - context.setSuccess(false); - return context; - } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/StylesheetAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/StylesheetAjax.java index 326c04dc..4c2aea4c 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/StylesheetAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/StylesheetAjax.java @@ -16,16 +16,18 @@ package com.simisinc.platform.presentation.widgets.cms; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.Stylesheet; import com.simisinc.platform.domain.model.cms.WebPage; import com.simisinc.platform.infrastructure.persistence.cms.StylesheetRepository; import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns a web page's stylesheet/CSS for the visual page editor CSS tab @@ -34,20 +36,19 @@ * @author matt rajkowski * @created 1/10/26 10:00 AM */ -public class StylesheetAjax extends GenericWidget { +public class StylesheetAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908896L; private static Log LOG = LogFactory.getLog(StylesheetAjax.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("StylesheetAjax..."); - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.debug("No permission to access stylesheet"); - context.setJson("{\"error\":\"Permission denied\"}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + StylesheetAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Determine the page link @@ -55,16 +56,14 @@ public WidgetContext execute(WidgetContext context) { LOG.debug("Requested link: " + link); if (StringUtils.isBlank(link)) { LOG.debug("Link is empty"); - context.setJson("{\"error\":\"Link is required\"}"); - return context; + return context.writeError("Link is required"); } // Retrieve the web page to get its ID WebPage page = WebPageRepository.findByLink(link); if (page == null) { LOG.debug("Web page not found for link: " + link); - context.setJson("{\"error\":\"Page not found\"}"); - return context; + return context.writeError("Page not found"); } // Retrieve the stylesheet for this web page @@ -75,7 +74,7 @@ public WidgetContext execute(WidgetContext context) { sb.append("{"); sb.append("\"webPageId\":").append(page.getId()).append(","); sb.append("\"link\":\"").append(JsonCommand.toJson(page.getLink())).append("\","); - + if (stylesheet != null) { sb.append("\"id\":").append(stylesheet.getId()).append(","); sb.append("\"css\":\"").append(JsonCommand.toJson(StringUtils.defaultString(stylesheet.getCss()))).append("\","); @@ -85,7 +84,7 @@ public WidgetContext execute(WidgetContext context) { sb.append("\"css\":\"\","); sb.append("\"hasStylesheet\":false"); } - + sb.append("}"); context.setJson(sb.toString()); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageContentAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageContentAjax.java index c2ce316d..d8aedf5b 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageContentAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageContentAjax.java @@ -16,15 +16,17 @@ package com.simisinc.platform.presentation.widgets.cms; -import com.simisinc.platform.application.json.JsonCommand; -import com.simisinc.platform.domain.model.cms.WebPage; -import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; +import com.simisinc.platform.application.json.JsonCommand; +import com.simisinc.platform.domain.model.cms.WebPage; +import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; + /** * Returns a web page's content for the visual page editor * Only returns pages the user has permission to edit @@ -32,20 +34,19 @@ * @author matt rajkowski * @created 12/14/25 10:00 AM */ -public class WebPageContentAjax extends GenericWidget { +public class WebPageContentAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; private static Log LOG = LogFactory.getLog(WebPageContentAjax.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("WebPageContentAjax..."); - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.debug("No permission to access web page content"); - context.setJson("{}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + WebPageContentAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Determine the page link @@ -72,7 +73,7 @@ public WidgetContext execute(WidgetContext context) { sb.append("\"link\":\"").append(JsonCommand.toJson(page.getLink())).append("\","); String pageTitle = StringUtils.isNotBlank(page.getTitle()) ? page.getTitle() : page.getLink(); sb.append("\"title\":\"").append(JsonCommand.toJson(pageTitle)).append("\","); - + // Include the page XML String pageXml = page.getPageXml(); if (StringUtils.isNotBlank(pageXml)) { @@ -80,7 +81,7 @@ public WidgetContext execute(WidgetContext context) { } else { sb.append("\"pageXml\":\"\""); } - + sb.append("}"); context.setJson(sb.toString()); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageInfoAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageInfoAjax.java index 95d24c25..6a2de586 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageInfoAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageInfoAjax.java @@ -16,17 +16,19 @@ package com.simisinc.platform.presentation.widgets.cms; -import com.simisinc.platform.application.json.JsonCommand; -import com.simisinc.platform.domain.model.cms.SitemapChangeFrequencyOptions; -import com.simisinc.platform.domain.model.cms.WebPage; -import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import java.util.Map; + import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import java.util.Map; +import com.simisinc.platform.application.admin.PermissionEngine; +import com.simisinc.platform.application.json.JsonCommand; +import com.simisinc.platform.domain.model.cms.SitemapChangeFrequencyOptions; +import com.simisinc.platform.domain.model.cms.WebPage; +import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns a web page's metadata/info for the visual page editor Info tab @@ -35,20 +37,19 @@ * @author matt rajkowski * @created 1/10/26 10:00 AM */ -public class WebPageInfoAjax extends GenericWidget { +public class WebPageInfoAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908894L; private static Log LOG = LogFactory.getLog(WebPageInfoAjax.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { LOG.debug("WebPageInfoAjax..."); - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.debug("No permission to access web page info"); - context.setJson("{\"error\":\"Permission denied\"}"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + WebPageInfoAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Determine the page link @@ -80,9 +81,11 @@ public WidgetContext execute(WidgetContext context) { sb.append("\"draft\":").append(page.getDraft()).append(","); sb.append("\"searchable\":").append(page.isSearchable()).append(","); sb.append("\"showInSitemap\":").append(page.isShowInSitemap()).append(","); - sb.append("\"sitemapPriority\":").append(page.getSitemapPriority() != null ? page.getSitemapPriority().toString() : "0.5").append(","); - sb.append("\"sitemapChangeFrequency\":\"").append(JsonCommand.toJson(StringUtils.defaultString(page.getSitemapChangeFrequency()))).append("\","); - + sb.append("\"sitemapPriority\":").append(page.getSitemapPriority() != null ? page.getSitemapPriority().toString() : "0.5") + .append(","); + sb.append("\"sitemapChangeFrequency\":\"").append(JsonCommand.toJson(StringUtils.defaultString(page.getSitemapChangeFrequency()))) + .append("\","); + // Include sitemap change frequency options for the dropdown sb.append("\"sitemapChangeFrequencyOptions\":{"); boolean first = true; @@ -94,7 +97,7 @@ public WidgetContext execute(WidgetContext context) { first = false; } sb.append("}"); - + sb.append("}"); context.setJson(sb.toString()); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageListAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageListAjax.java index f485b0cc..106380b3 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageListAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/cms/WebPageListAjax.java @@ -20,13 +20,14 @@ import org.apache.commons.lang3.StringUtils; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.WebPage; import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.cms.WebPageRepository; import com.simisinc.platform.infrastructure.persistence.cms.WebPageSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * Returns a list of web pages for the visual page editor @@ -35,16 +36,16 @@ * @author matt rajkowski * @created 12/14/25 10:00 AM */ -public class WebPageListAjax extends GenericWidget { +public class WebPageListAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908893L; - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("[]"); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + WebPageListAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Get sort parameter (a-z, modified, hierarchy) @@ -55,7 +56,7 @@ public WidgetContext execute(WidgetContext context) { // specification.setEnabled(true); DataConstraints constraints = new DataConstraints(); - + // Set sorting based on parameter if ("modified".equals(sortBy)) { constraints.setColumnToSortBy("modified", "desc"); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMCustomersJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMCustomersJsonService.java index bba20a6d..39ef4311 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMCustomersJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMCustomersJsonService.java @@ -27,7 +27,7 @@ import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.ecommerce.CustomerRepository; import com.simisinc.platform.infrastructure.persistence.ecommerce.CustomerSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; +import com.simisinc.platform.presentation.controller.JsonServiceContext; import com.simisinc.platform.presentation.widgets.GenericWidget; /** @@ -41,12 +41,10 @@ public class CRMCustomersJsonService extends GenericWidget { static final long serialVersionUID = -8484048371911908902L; private static Log LOG = LogFactory.getLog(CRMCustomersJsonService.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { if (!context.hasRole("admin") && !context.hasRole("ecommerce-manager")) { - context.setJson("{\"error\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + return context.writeError("Permission Denied"); } int page = context.getParameterAsInt("page", 1); @@ -77,7 +75,8 @@ public WidgetContext execute(WidgetContext context) { sb.append("\"lastName\":\"").append(JsonCommand.toJson(StringUtils.defaultString(customer.getLastName()))).append("\","); sb.append("\"organization\":\"").append(JsonCommand.toJson(StringUtils.defaultString(customer.getOrganization()))).append("\","); sb.append("\"orderCount\":").append(customer.getOrderCount()).append(","); - sb.append("\"totalSpend\":").append(customer.getTotalSpend() != null ? customer.getTotalSpend().toPlainString() : "0").append(","); + sb.append("\"totalSpend\":").append(customer.getTotalSpend() != null ? customer.getTotalSpend().toPlainString() : "0") + .append(","); sb.append("\"created\":\"").append(customer.getCreated() != null ? customer.getCreated().toString() : "").append("\""); sb.append("}"); } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionDetailJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionDetailJsonService.java index 974fec3b..8765efe6 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionDetailJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionDetailJsonService.java @@ -20,12 +20,13 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.FormData; import com.simisinc.platform.domain.model.cms.FormField; import com.simisinc.platform.infrastructure.persistence.cms.FormDataRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to return the full detail of a single form submission @@ -33,17 +34,17 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMFormSubmissionDetailJsonService extends GenericWidget { +public class CRMFormSubmissionDetailJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908898L; private static Log LOG = LogFactory.getLog(CRMFormSubmissionDetailJsonService.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"error\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMFormSubmissionDetailJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } long submissionId = context.getParameterAsLong("id"); @@ -68,11 +69,14 @@ public WidgetContext execute(WidgetContext context) { sb.append("\"url\":\"").append(JsonCommand.toJson(StringUtils.defaultString(formData.getUrl()))).append("\","); sb.append("\"created\":\"").append(formData.getCreated() != null ? formData.getCreated().toString() : "").append("\","); sb.append("\"claimed\":").append(formData.getClaimed() != null).append(","); - sb.append("\"claimedDate\":").append(formData.getClaimed() != null ? "\"" + formData.getClaimed().toString() + "\"" : "null").append(","); + sb.append("\"claimedDate\":").append(formData.getClaimed() != null ? "\"" + formData.getClaimed().toString() + "\"" : "null") + .append(","); sb.append("\"dismissed\":").append(formData.getDismissed() != null).append(","); - sb.append("\"dismissedDate\":").append(formData.getDismissed() != null ? "\"" + formData.getDismissed().toString() + "\"" : "null").append(","); + sb.append("\"dismissedDate\":").append(formData.getDismissed() != null ? "\"" + formData.getDismissed().toString() + "\"" : "null") + .append(","); sb.append("\"processed\":").append(formData.getProcessed() != null).append(","); - sb.append("\"processedDate\":").append(formData.getProcessed() != null ? "\"" + formData.getProcessed().toString() + "\"" : "null").append(","); + sb.append("\"processedDate\":").append(formData.getProcessed() != null ? "\"" + formData.getProcessed().toString() + "\"" : "null") + .append(","); sb.append("\"flaggedAsSpam\":").append(formData.getFlaggedAsSpam()).append(","); // Build field array diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionUpdateJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionUpdateJsonService.java index 68568c90..5ad94d9a 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionUpdateJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionUpdateJsonService.java @@ -20,10 +20,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.domain.model.cms.FormData; import com.simisinc.platform.infrastructure.persistence.cms.FormDataRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to update the status of a form submission: claim, dismiss, or process @@ -31,33 +32,29 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMFormSubmissionUpdateJsonService extends GenericWidget { +public class CRMFormSubmissionUpdateJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908899L; private static Log LOG = LogFactory.getLog(CRMFormSubmissionUpdateJsonService.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"error\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMFormSubmissionUpdateJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } long submissionId = context.getParameterAsLong("id"); String action = context.getParameter("action"); if (submissionId == -1 || StringUtils.isBlank(action)) { - context.setJson("{\"error\":\"id and action are required\"}"); - context.setSuccess(false); - return context; + return context.writeError("id and action are required"); } FormData formData = FormDataRepository.findById(submissionId); if (formData == null) { - context.setJson("{\"error\":\"Submission not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Submission not found"); } long userId = context.getUserId(); @@ -80,9 +77,7 @@ public WidgetContext execute(WidgetContext context) { } if (!success) { - context.setJson("{\"error\":\"Action could not be completed\"}"); - context.setSuccess(false); - return context; + return context.writeError("Failed to update submission status. It may have already been updated by another user."); } context.setJson("{\"status\":\"ok\",\"id\":" + submissionId + ",\"action\":\"" + action + "\"}"); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionsJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionsJsonService.java index 5fbfe780..eb8a30ce 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionsJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormSubmissionsJsonService.java @@ -22,14 +22,15 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.FormData; import com.simisinc.platform.domain.model.cms.FormField; import com.simisinc.platform.infrastructure.database.DataConstraints; import com.simisinc.platform.infrastructure.persistence.cms.FormDataRepository; import com.simisinc.platform.infrastructure.persistence.cms.FormDataSpecification; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to list form submissions for a given form category @@ -37,24 +38,22 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMFormSubmissionsJsonService extends GenericWidget { +public class CRMFormSubmissionsJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908897L; private static Log LOG = LogFactory.getLog(CRMFormSubmissionsJsonService.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"error\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMFormSubmissionsJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } String formUniqueId = context.getParameter("formUniqueId"); if (StringUtils.isBlank(formUniqueId)) { - context.setJson("{\"error\":\"formUniqueId is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("Permission Denied"); } int page = context.getParameterAsInt("page", 1); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormsListJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormsListJsonService.java index 7620940d..be0678bc 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormsListJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMFormsListJsonService.java @@ -24,10 +24,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.infrastructure.database.DB; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to list all form categories (distinct form_unique_id values) with submission counts @@ -35,26 +36,26 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMFormsListJsonService extends GenericWidget { +public class CRMFormsListJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908896L; private static Log LOG = LogFactory.getLog(CRMFormsListJsonService.class); - private static final String SQL_QUERY = - "SELECT form_unique_id, " + - "COUNT(*) AS total, " + - "SUM(CASE WHEN claimed IS NULL AND dismissed IS NULL AND processed IS NULL AND flagged_as_spam = false THEN 1 ELSE 0 END) AS new_count, " + - "MAX(created) AS last_submission " + - "FROM form_data " + - "GROUP BY form_unique_id " + - "ORDER BY form_unique_id"; + private static final String SQL_QUERY = "SELECT form_unique_id, " + + "COUNT(*) AS total, " + + "SUM(CASE WHEN claimed IS NULL AND dismissed IS NULL AND processed IS NULL AND flagged_as_spam = false THEN 1 ELSE 0 END) AS new_count, " + + + "MAX(created) AS last_submission " + + "FROM form_data " + + "GROUP BY form_unique_id " + + "ORDER BY form_unique_id"; - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"error\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMFormsListJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } StringBuilder json = new StringBuilder(); @@ -82,9 +83,7 @@ public WidgetContext execute(WidgetContext context) { } } catch (SQLException se) { LOG.error("CRMFormsListJsonService SQL error: " + se.getMessage()); - context.setJson("{\"error\":\"Database error\"}"); - context.setSuccess(false); - return context; + return context.writeError("Database error"); } json.append("]"); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMMailingListMembersJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMMailingListMembersJsonService.java index a7bad390..e270c934 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMMailingListMembersJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMMailingListMembersJsonService.java @@ -22,6 +22,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.mailinglists.Email; import com.simisinc.platform.domain.model.mailinglists.MailingList; @@ -29,8 +30,8 @@ import com.simisinc.platform.infrastructure.persistence.mailinglists.EmailRepository; import com.simisinc.platform.infrastructure.persistence.mailinglists.EmailSpecification; import com.simisinc.platform.infrastructure.persistence.mailinglists.MailingListRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to list members of a mailing list @@ -38,31 +39,27 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMMailingListMembersJsonService extends GenericWidget { +public class CRMMailingListMembersJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908901L; private static Log LOG = LogFactory.getLog(CRMMailingListMembersJsonService.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"error\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMMailingListMembersJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } long mailingListId = context.getParameterAsLong("listId"); if (mailingListId == -1) { - context.setJson("{\"error\":\"listId is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("listId is required"); } MailingList mailingList = MailingListRepository.findById(mailingListId); if (mailingList == null) { - context.setJson("{\"error\":\"Mailing list not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Mailing list not found"); } int page = context.getParameterAsInt("page", 1); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMMailingListsJsonService.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMMailingListsJsonService.java index 0535b163..4c061aab 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMMailingListsJsonService.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMMailingListsJsonService.java @@ -21,11 +21,12 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.mailinglists.MailingList; import com.simisinc.platform.infrastructure.persistence.mailinglists.MailingListRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to list all mailing lists with member counts @@ -33,17 +34,17 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMMailingListsJsonService extends GenericWidget { +public class CRMMailingListsJsonService extends GenericJsonService { static final long serialVersionUID = -8484048371911908900L; private static Log LOG = LogFactory.getLog(CRMMailingListsJsonService.class); - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"error\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMMailingListsJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } List mailingLists = MailingListRepository.findAll(); @@ -60,7 +61,8 @@ public WidgetContext execute(WidgetContext context) { sb.append("\"id\":").append(list.getId()).append(","); sb.append("\"name\":\"").append(JsonCommand.toJson(list.getName())).append("\","); sb.append("\"title\":\"").append(JsonCommand.toJson(list.getTitle() != null ? list.getTitle() : "")).append("\","); - sb.append("\"description\":\"").append(JsonCommand.toJson(list.getDescription() != null ? list.getDescription() : "")).append("\","); + sb.append("\"description\":\"").append(JsonCommand.toJson(list.getDescription() != null ? list.getDescription() : "")) + .append("\","); sb.append("\"memberCount\":").append(list.getMemberCount()).append(","); sb.append("\"enabled\":").append(list.getEnabled()).append(","); sb.append("\"showOnline\":").append(list.getShowOnline()); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveCustomerAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveCustomerAjax.java index 8195c500..f475e291 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveCustomerAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveCustomerAjax.java @@ -21,12 +21,13 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.ecommerce.SaveCustomerCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.ecommerce.Customer; import com.simisinc.platform.infrastructure.persistence.ecommerce.CustomerRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to save (create/update) a customer from the CRM editor @@ -34,17 +35,17 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMSaveCustomerAjax extends GenericWidget { +public class CRMSaveCustomerAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908881L; private static Log LOG = LogFactory.getLog(CRMSaveCustomerAjax.class); - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMSaveCustomerAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long id = context.getParameterAsLong("id", -1L); @@ -54,19 +55,13 @@ public WidgetContext post(WidgetContext context) { String organization = StringUtils.trimToNull(context.getParameter("organization")); if (StringUtils.isBlank(firstName)) { - context.setJson("{\"success\":false,\"message\":\"A first name is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("A first name is required"); } if (StringUtils.isBlank(lastName)) { - context.setJson("{\"success\":false,\"message\":\"A last name is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("A last name is required"); } if (StringUtils.isBlank(email)) { - context.setJson("{\"success\":false,\"message\":\"An email address is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("An email address is required"); } try { @@ -120,14 +115,10 @@ public WidgetContext post(WidgetContext context) { } catch (DataException de) { LOG.error("DataException", de); - context.setJson("{\"success\":false,\"message\":\"" + JsonCommand.toJson(de.getMessage()) + "\"}"); - context.setSuccess(false); - return context; + return context.writeError("" + de.getMessage()); } catch (Exception e) { LOG.error("Exception", e); - context.setJson("{\"success\":false,\"message\":\"An error occurred\"}"); - context.setSuccess(false); - return context; + return context.writeError("An error occurred"); } } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveMailingListAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveMailingListAjax.java index 8301323a..75d53fdc 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveMailingListAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveMailingListAjax.java @@ -21,12 +21,13 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.application.mailinglists.SaveMailingListCommand; import com.simisinc.platform.domain.model.mailinglists.MailingList; import com.simisinc.platform.infrastructure.persistence.mailinglists.MailingListRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to save (create/update) a mailing list from the CRM editor @@ -34,17 +35,17 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMSaveMailingListAjax extends GenericWidget { +public class CRMSaveMailingListAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908880L; private static Log LOG = LogFactory.getLog(CRMSaveMailingListAjax.class); - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMSaveMailingListAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long id = context.getParameterAsLong("id", -1L); @@ -54,9 +55,7 @@ public WidgetContext post(WidgetContext context) { boolean showOnline = "true".equalsIgnoreCase(context.getParameter("showOnline")); if (StringUtils.isBlank(name)) { - context.setJson("{\"success\":false,\"message\":\"A name is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("A name is required"); } try { @@ -64,9 +63,7 @@ public WidgetContext post(WidgetContext context) { if (id > -1) { mailingListBean = MailingListRepository.findById(id); if (mailingListBean == null) { - context.setJson("{\"success\":false,\"message\":\"Mailing list not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Mailing list not found"); } } else { mailingListBean = new MailingList(); @@ -97,14 +94,10 @@ public WidgetContext post(WidgetContext context) { } catch (DataException de) { LOG.error("DataException", de); - context.setJson("{\"success\":false,\"message\":\"" + JsonCommand.toJson(de.getMessage()) + "\"}"); - context.setSuccess(false); - return context; + return context.writeError("" + de.getMessage()); } catch (Exception e) { LOG.error("Exception", e); - context.setJson("{\"success\":false,\"message\":\"An error occurred\"}"); - context.setSuccess(false); - return context; + return context.writeError("An error occurred"); } } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSavePricingRuleAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSavePricingRuleAjax.java index b543d564..c5a6e602 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSavePricingRuleAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSavePricingRuleAjax.java @@ -23,12 +23,13 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.ecommerce.SavePricingRuleCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.ecommerce.PricingRule; import com.simisinc.platform.infrastructure.persistence.ecommerce.PricingRuleRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to save (create/update) a pricing rule from the CRM editor @@ -36,17 +37,17 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMSavePricingRuleAjax extends GenericWidget { +public class CRMSavePricingRuleAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908884L; private static Log LOG = LogFactory.getLog(CRMSavePricingRuleAjax.class); - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMSavePricingRuleAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long id = context.getParameterAsLong("id", -1L); @@ -59,9 +60,7 @@ public WidgetContext post(WidgetContext context) { boolean freeShipping = "true".equalsIgnoreCase(context.getParameter("freeShipping")); if (StringUtils.isBlank(name)) { - context.setJson("{\"success\":false,\"message\":\"A name is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("A name is required"); } try { @@ -69,9 +68,7 @@ public WidgetContext post(WidgetContext context) { if (id > -1) { ruleBean = PricingRuleRepository.findById(id); if (ruleBean == null) { - context.setJson("{\"success\":false,\"message\":\"Pricing rule not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Pricing rule not found"); } } else { ruleBean = new PricingRule(); @@ -118,14 +115,10 @@ public WidgetContext post(WidgetContext context) { } catch (DataException de) { LOG.error("DataException", de); - context.setJson("{\"success\":false,\"message\":\"" + JsonCommand.toJson(de.getMessage()) + "\"}"); - context.setSuccess(false); - return context; + return context.writeError("" + de.getMessage()); } catch (Exception e) { LOG.error("Exception", e); - context.setJson("{\"success\":false,\"message\":\"An error occurred\"}"); - context.setSuccess(false); - return context; + return context.writeError("An error occurred"); } } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveProductAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveProductAjax.java index 8d6f5339..f5b1880a 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveProductAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveProductAjax.java @@ -21,12 +21,13 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.ecommerce.SaveProductCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.ecommerce.Product; import com.simisinc.platform.infrastructure.persistence.ecommerce.ProductRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to save (create/update) a product from the CRM editor @@ -34,17 +35,17 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMSaveProductAjax extends GenericWidget { +public class CRMSaveProductAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908883L; private static Log LOG = LogFactory.getLog(CRMSaveProductAjax.class); - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMSaveProductAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long id = context.getParameterAsLong("id", -1L); @@ -100,14 +101,10 @@ public WidgetContext post(WidgetContext context) { } catch (DataException de) { LOG.error("DataException", de); - context.setJson("{\"success\":false,\"message\":\"" + JsonCommand.toJson(de.getMessage()) + "\"}"); - context.setSuccess(false); - return context; + return context.writeError("" + de.getMessage()); } catch (Exception e) { LOG.error("Exception", e); - context.setJson("{\"success\":false,\"message\":\"An error occurred\"}"); - context.setSuccess(false); - return context; + return context.writeError("An error occurred"); } } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveProductCategoryAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveProductCategoryAjax.java index aef462a9..1793e59c 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveProductCategoryAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveProductCategoryAjax.java @@ -21,12 +21,13 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.ecommerce.SaveProductCategoryCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.ecommerce.ProductCategory; import com.simisinc.platform.infrastructure.persistence.ecommerce.ProductCategoryRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to save (create/update) a product category from the CRM editor @@ -34,17 +35,17 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMSaveProductCategoryAjax extends GenericWidget { +public class CRMSaveProductCategoryAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908882L; private static Log LOG = LogFactory.getLog(CRMSaveProductCategoryAjax.class); - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMSaveProductCategoryAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long id = context.getParameterAsLong("id", -1L); @@ -54,9 +55,7 @@ public WidgetContext post(WidgetContext context) { boolean enabled = !"false".equalsIgnoreCase(context.getParameter("enabled")); if (StringUtils.isBlank(name)) { - context.setJson("{\"success\":false,\"message\":\"A name is required\"}"); - context.setSuccess(false); - return context; + return context.writeError("A name is required"); } try { @@ -64,9 +63,7 @@ public WidgetContext post(WidgetContext context) { if (id > -1) { categoryBean = ProductCategoryRepository.findById(id); if (categoryBean == null) { - context.setJson("{\"success\":false,\"message\":\"Category not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Category not found"); } } else { categoryBean = new ProductCategory(); @@ -100,14 +97,10 @@ public WidgetContext post(WidgetContext context) { } catch (DataException de) { LOG.error("DataException", de); - context.setJson("{\"success\":false,\"message\":\"" + JsonCommand.toJson(de.getMessage()) + "\"}"); - context.setSuccess(false); - return context; + return context.writeError("" + de.getMessage()); } catch (Exception e) { LOG.error("Exception", e); - context.setJson("{\"success\":false,\"message\":\"An error occurred\"}"); - context.setSuccess(false); - return context; + return context.writeError("An error occurred"); } } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveSalesTaxNexusAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveSalesTaxNexusAjax.java index fed2fc5e..27908913 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveSalesTaxNexusAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveSalesTaxNexusAjax.java @@ -21,12 +21,13 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.ecommerce.SaveSalesTaxNexusAddressCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.ecommerce.SalesTaxNexusAddress; import com.simisinc.platform.infrastructure.persistence.ecommerce.SalesTaxNexusAddressRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to save (create/update) a sales tax nexus address from the CRM editor @@ -34,17 +35,17 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMSaveSalesTaxNexusAjax extends GenericWidget { +public class CRMSaveSalesTaxNexusAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908885L; private static Log LOG = LogFactory.getLog(CRMSaveSalesTaxNexusAjax.class); - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMSaveSalesTaxNexusAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long id = context.getParameterAsLong("id", -1L); @@ -100,14 +101,10 @@ public WidgetContext post(WidgetContext context) { } catch (DataException de) { LOG.error("DataException", de); - context.setJson("{\"success\":false,\"message\":\"" + JsonCommand.toJson(de.getMessage()) + "\"}"); - context.setSuccess(false); - return context; + return context.writeError("" + de.getMessage()); } catch (Exception e) { LOG.error("Exception", e); - context.setJson("{\"success\":false,\"message\":\"An error occurred\"}"); - context.setSuccess(false); - return context; + return context.writeError("An error occurred"); } } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveShippingRateAjax.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveShippingRateAjax.java index cab03f94..89f292d8 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveShippingRateAjax.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/CRMSaveShippingRateAjax.java @@ -24,14 +24,15 @@ import org.apache.commons.logging.LogFactory; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.ecommerce.SaveShippingRateCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.ecommerce.ShippingMethod; import com.simisinc.platform.domain.model.ecommerce.ShippingRate; import com.simisinc.platform.infrastructure.persistence.ecommerce.ShippingMethodRepository; import com.simisinc.platform.infrastructure.persistence.ecommerce.ShippingRateRepository; -import com.simisinc.platform.presentation.controller.WidgetContext; -import com.simisinc.platform.presentation.widgets.GenericWidget; +import com.simisinc.platform.presentation.controller.JsonServiceContext; +import com.simisinc.platform.presentation.services.GenericJsonService; /** * JSON service to save (create/update) a shipping rate from the CRM editor @@ -39,18 +40,18 @@ * @author matt rajkowski * @created 2026-02-27 */ -public class CRMSaveShippingRateAjax extends GenericWidget { +public class CRMSaveShippingRateAjax extends GenericJsonService { static final long serialVersionUID = -8484048371911908886L; private static Log LOG = LogFactory.getLog(CRMSaveShippingRateAjax.class); // GET: return available shipping methods for the modal - public WidgetContext execute(WidgetContext context) { + public JsonServiceContext get(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"error\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMSaveShippingRateAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } List methods = ShippingMethodRepository.findAll(); @@ -60,7 +61,8 @@ public WidgetContext execute(WidgetContext context) { boolean first = true; if (methods != null) { for (ShippingMethod m : methods) { - if (!first) sb.append(","); + if (!first) + sb.append(","); first = false; sb.append("{\"id\":").append(m.getId()).append(","); sb.append("\"title\":\"").append(JsonCommand.toJson(m.getTitle())).append("\","); @@ -73,12 +75,12 @@ public WidgetContext execute(WidgetContext context) { return context; } - public WidgetContext post(WidgetContext context) { + public JsonServiceContext post(JsonServiceContext context) { - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + CRMSaveShippingRateAjax.class.getSimpleName()); + return context.writeError("Permission Denied"); } long id = context.getParameterAsLong("id", -1L); @@ -96,9 +98,7 @@ public WidgetContext post(WidgetContext context) { if (id > -1) { rateBean = ShippingRateRepository.findById(id); if (rateBean == null) { - context.setJson("{\"success\":false,\"message\":\"Shipping rate not found\"}"); - context.setSuccess(false); - return context; + return context.writeError("Shipping rate not found"); } } else { rateBean = new ShippingRate(); @@ -148,7 +148,8 @@ public WidgetContext post(WidgetContext context) { sb.append("\"message\":\"Shipping rate saved\","); sb.append("\"rate\":{"); sb.append("\"id\":").append(saved.getId()).append(","); - sb.append("\"countryCode\":\"").append(JsonCommand.toJson(saved.getCountryCode() != null ? saved.getCountryCode() : "")).append("\","); + sb.append("\"countryCode\":\"").append(JsonCommand.toJson(saved.getCountryCode() != null ? saved.getCountryCode() : "")) + .append("\","); sb.append("\"region\":\"").append(JsonCommand.toJson(saved.getRegion() != null ? saved.getRegion() : "")).append("\""); sb.append("}}"); @@ -157,14 +158,10 @@ public WidgetContext post(WidgetContext context) { } catch (DataException de) { LOG.error("DataException", de); - context.setJson("{\"success\":false,\"message\":\"" + JsonCommand.toJson(de.getMessage()) + "\"}"); - context.setSuccess(false); - return context; + return context.writeError("" + de.getMessage()); } catch (Exception e) { LOG.error("Exception", e); - context.setJson("{\"success\":false,\"message\":\"An error occurred\"}"); - context.setSuccess(false); - return context; + return context.writeError("An error occurred"); } } } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/StaticSiteEndpoint.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/StaticSiteJsonService.java similarity index 87% rename from src/main/java/com/simisinc/platform/presentation/widgets/editor/StaticSiteEndpoint.java rename to src/main/java/com/simisinc/platform/presentation/widgets/editor/StaticSiteJsonService.java index bb3ad3ee..ef13ccef 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/StaticSiteEndpoint.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/StaticSiteJsonService.java @@ -27,13 +27,14 @@ import org.jobrunr.scheduling.BackgroundJobRequest; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.LoadGitPublishSettingsCommand; import com.simisinc.platform.application.cms.MakeStaticSiteCommand; import com.simisinc.platform.application.cms.SaveGitPublishSettingsCommand; import com.simisinc.platform.application.json.JsonCommand; import com.simisinc.platform.domain.model.cms.GitPublishSettings; import com.simisinc.platform.infrastructure.scheduler.cms.MakeStaticSiteJob; -import com.simisinc.platform.presentation.controller.WidgetContext; +import com.simisinc.platform.presentation.controller.JsonServiceContext; import com.simisinc.platform.presentation.widgets.GenericWidget; /** @@ -42,27 +43,19 @@ * @author matt rajkowski * @created 1/19/26 10:00 AM */ -public class StaticSiteEndpoint extends GenericWidget { +public class StaticSiteJsonService extends GenericWidget { private static final String STATIC_SITE_PATH = "/web/static-sites"; // Path within the container - /** The default GET, not used */ - public WidgetContext execute(WidgetContext context) { - LOG.debug("StaticSiteEndpoint Execute..."); - return context; - } - /** The action handler which takes an 'action' parameter */ - public WidgetContext action(WidgetContext context) { + public JsonServiceContext action(JsonServiceContext context) { - LOG.debug("StaticSiteEndpoint Action..."); + LOG.debug("StaticSiteJsonService Action..."); - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.debug("No permission to: " + StaticSiteEndpoint.class.getSimpleName()); - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + StaticSiteJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Determine the action @@ -82,22 +75,20 @@ public WidgetContext action(WidgetContext context) { LOG.error("Unknown action: " + action); return null; } catch (Exception e) { - LOG.error("Error in StaticSiteEndpoint", e); + LOG.error("Error in StaticSiteJsonService", e); return null; } } /** Handles POST requests for static site generation and deletion */ - public WidgetContext post(WidgetContext context) throws InvocationTargetException, IllegalAccessException { + public JsonServiceContext post(JsonServiceContext context) throws InvocationTargetException, IllegalAccessException { - LOG.debug("StaticSiteEndpoint POST..."); + LOG.debug("StaticSiteJsonService POST..."); - // Check permissions: only allow content editors and admins - if (!context.hasRole("admin") && !context.hasRole("content-manager")) { - LOG.debug("No permission to: " + StaticSiteEndpoint.class.getSimpleName()); - context.setJson("{\"success\":false,\"message\":\"Permission denied\"}"); - context.setSuccess(false); - return context; + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + StaticSiteJsonService.class.getSimpleName()); + return context.writeError("Permission Denied"); } // Determine the action @@ -111,13 +102,13 @@ public WidgetContext post(WidgetContext context) throws InvocationTargetExceptio return saveGitSettings(context); } } catch (IOException e) { - LOG.error("Error in StaticSiteEndpoint", e); + LOG.error("Error in StaticSiteJsonService", e); } return null; } /** List the previous static site files */ - private WidgetContext list(WidgetContext context) throws IOException { + private JsonServiceContext list(JsonServiceContext context) throws IOException { // @todo the generator stores files in the fileLibrary, and records those in a database table // Read from there instead of the static site directory @@ -153,7 +144,7 @@ private WidgetContext list(WidgetContext context) throws IOException { } /** Generate the static site */ - private WidgetContext generate(WidgetContext context) throws IOException { + private JsonServiceContext generate(JsonServiceContext context) throws IOException { if (MakeStaticSiteCommand.isJobRunning()) { LOG.debug("A static site generation is already in progress."); sendErrorResponse(context.getResponse(), "A static site generation is already in progress."); @@ -167,7 +158,7 @@ private WidgetContext generate(WidgetContext context) throws IOException { return context; } - public WidgetContext delete(WidgetContext context) { + public JsonServiceContext delete(JsonServiceContext context) { LOG.debug("Deleting static site file..."); // @todo the generator stores files in the fileLibrary, and records those in a database table @@ -205,7 +196,7 @@ public WidgetContext delete(WidgetContext context) { } /** Download a static site file */ - private WidgetContext download(WidgetContext context) throws IOException { + private JsonServiceContext download(JsonServiceContext context) throws IOException { HttpServletResponse response = context.getResponse(); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Not implemented."); @@ -249,7 +240,7 @@ private void sendErrorResponse(HttpServletResponse response, String message) thr } /** Get Git publish settings */ - private WidgetContext getGitSettings(WidgetContext context) throws IOException { + private JsonServiceContext getGitSettings(JsonServiceContext context) throws IOException { LOG.debug("Getting Git publish settings..."); GitPublishSettings settings = LoadGitPublishSettingsCommand.loadSettings(); @@ -289,7 +280,7 @@ private WidgetContext getGitSettings(WidgetContext context) throws IOException { } /** Save Git publish settings */ - private WidgetContext saveGitSettings(WidgetContext context) throws IOException { + private JsonServiceContext saveGitSettings(JsonServiceContext context) throws IOException { LOG.debug("Saving Git publish settings..."); try { diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualCRMEditorWidget.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualCRMEditorWidget.java index 7e4fd486..fc26dd58 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualCRMEditorWidget.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualCRMEditorWidget.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.UrlCommand; import com.simisinc.platform.presentation.controller.WidgetContext; import com.simisinc.platform.presentation.widgets.GenericWidget; @@ -38,6 +39,11 @@ public class VisualCRMEditorWidget extends GenericWidget { static String EDITOR_JSP = "/cms/visual-crm-editor.jsp"; public WidgetContext execute(WidgetContext context) { + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + VisualCRMEditorWidget.class.getSimpleName()); + return context; + } // Set the JSP context.setJsp(EDITOR_JSP); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualContentEditorWidget.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualContentEditorWidget.java index 77054fa0..20cb3033 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualContentEditorWidget.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualContentEditorWidget.java @@ -20,10 +20,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.simisinc.platform.application.DataException; -import com.simisinc.platform.application.cms.SaveContentCommand; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.UrlCommand; -import com.simisinc.platform.domain.model.cms.Content; import com.simisinc.platform.presentation.controller.WidgetContext; import com.simisinc.platform.presentation.widgets.GenericWidget; @@ -41,6 +39,11 @@ public class VisualContentEditorWidget extends GenericWidget { static String EDITOR_JSP = "/cms/visual-content-editor.jsp"; public WidgetContext execute(WidgetContext context) { + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + VisualContentEditorWidget.class.getSimpleName()); + return context; + } // Set the JSP context.setJsp(EDITOR_JSP); @@ -65,60 +68,60 @@ public WidgetContext execute(WidgetContext context) { return context; } -/* + /* public WidgetContext post(WidgetContext context) { - + // Parse form parameters String contentUniqueId = context.getParameter("contentUniqueId"); String contentHtml = context.getParameter("content"); String isDraftParam = context.getParameter("isDraft"); String returnPage = context.getParameter("returnPage"); - + // Validate required parameters if (StringUtils.isBlank(contentUniqueId)) { context.setErrorMessage("Content unique ID is required"); context.setRequestObject(null); return context; } - + if (StringUtils.isBlank(contentHtml)) { context.setErrorMessage("Content is required"); context.setRequestObject(null); return context; } - + // Determine if this is a draft save or publish boolean isDraft = "true".equalsIgnoreCase(isDraftParam); - + LOG.debug("Saving content: " + contentUniqueId + ", isDraft: " + isDraft); - + try { // Create content object for saving Content content = new Content(); content.setUniqueId(contentUniqueId); content.setCreatedBy(context.getUserId()); content.setModifiedBy(context.getUserId()); - + // Set the content based on whether it's a draft or publish if (isDraft) { content.setDraftContent(contentHtml); } else { content.setContent(contentHtml); } - + // Save the content using SaveContentCommand Content savedContent = SaveContentCommand.saveContent(content, isDraft); if (savedContent == null) { throw new DataException("The content could not be saved"); } - + // Set success message if (isDraft) { context.setSuccessMessage("Content saved as draft"); } else { context.setSuccessMessage("Content published successfully"); } - + // Determine the next page if (StringUtils.isNotBlank(returnPage)) { context.setRedirect(returnPage); @@ -126,9 +129,9 @@ public WidgetContext post(WidgetContext context) { // Stay on the editor page context.setRedirect("/admin/visual-content-editor"); } - + return context; - + } catch (DataException de) { LOG.error("DataException saving content", de); context.setErrorMessage(de.getMessage()); @@ -141,5 +144,5 @@ public WidgetContext post(WidgetContext context) { return context; } } - */ + */ } diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualDataEditorWidget.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualDataEditorWidget.java index 087445c5..bea1a5c3 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualDataEditorWidget.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualDataEditorWidget.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.UrlCommand; import com.simisinc.platform.presentation.controller.WidgetContext; import com.simisinc.platform.presentation.widgets.GenericWidget; @@ -38,6 +39,11 @@ public class VisualDataEditorWidget extends GenericWidget { static String EDITOR_JSP = "/cms/visual-data-editor.jsp"; public WidgetContext execute(WidgetContext context) { + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + VisualDataEditorWidget.class.getSimpleName()); + return context; + } // Set the JSP context.setJsp(EDITOR_JSP); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualDocumentEditorWidget.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualDocumentEditorWidget.java index 9ae99b71..466c489e 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualDocumentEditorWidget.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualDocumentEditorWidget.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.UrlCommand; import com.simisinc.platform.presentation.controller.WidgetContext; import com.simisinc.platform.presentation.widgets.GenericWidget; @@ -38,6 +39,11 @@ public class VisualDocumentEditorWidget extends GenericWidget { static String EDITOR_JSP = "/cms/visual-document-editor.jsp"; public WidgetContext execute(WidgetContext context) { + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + VisualDocumentEditorWidget.class.getSimpleName()); + return context; + } // Set the JSP context.setJsp(EDITOR_JSP); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualImageEditorWidget.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualImageEditorWidget.java index c5bdb9dd..a3238d13 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualImageEditorWidget.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualImageEditorWidget.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.UrlCommand; import com.simisinc.platform.presentation.controller.WidgetContext; import com.simisinc.platform.presentation.widgets.GenericWidget; @@ -38,6 +39,11 @@ public class VisualImageEditorWidget extends GenericWidget { static String EDITOR_JSP = "/cms/visual-image-editor.jsp"; public WidgetContext execute(WidgetContext context) { + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + VisualImageEditorWidget.class.getSimpleName()); + return context; + } // Set the JSP context.setJsp(EDITOR_JSP); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualPageEditorWidget.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualPageEditorWidget.java index 83815017..87674cdb 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualPageEditorWidget.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualPageEditorWidget.java @@ -22,6 +22,7 @@ import org.apache.commons.text.WordUtils; import com.simisinc.platform.application.DataException; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.SaveWebPageCommand; import com.simisinc.platform.application.cms.UrlCommand; import com.simisinc.platform.application.cms.WebPageJsonToXMLCommand; @@ -44,6 +45,11 @@ public class VisualPageEditorWidget extends GenericWidget { static String EDITOR_JSP = "/cms/visual-page-editor.jsp"; public WidgetContext execute(WidgetContext context) { + // Check permissions + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + VisualPageEditorWidget.class.getSimpleName()); + return context; + } // Set the JSP context.setJsp(EDITOR_JSP); diff --git a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualWorkflowEditorWidget.java b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualWorkflowEditorWidget.java index 21dd8b65..9d62f676 100644 --- a/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualWorkflowEditorWidget.java +++ b/src/main/java/com/simisinc/platform/presentation/widgets/editor/VisualWorkflowEditorWidget.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import com.simisinc.platform.application.admin.PermissionEngine; import com.simisinc.platform.application.cms.UrlCommand; import com.simisinc.platform.presentation.controller.WidgetContext; import com.simisinc.platform.presentation.widgets.GenericWidget; @@ -41,8 +42,8 @@ public class VisualWorkflowEditorWidget extends GenericWidget { public WidgetContext execute(WidgetContext context) { // Check permissions - if (!context.hasRole("admin")) { - LOG.debug("No permission to access workflow editor"); + if (!PermissionEngine.checkAccess(getClass().getName(), context.getUserSession())) { + LOG.debug("No permission to: " + VisualWorkflowEditorWidget.class.getSimpleName()); return context; } diff --git a/src/main/webapp/WEB-INF/json-services/json-services.xml b/src/main/webapp/WEB-INF/json-services/json-services.xml index 3980f6d0..12ed4fc1 100644 --- a/src/main/webapp/WEB-INF/json-services/json-services.xml +++ b/src/main/webapp/WEB-INF/json-services/json-services.xml @@ -137,10 +137,13 @@ - - - - + + + + + + + diff --git a/src/main/webapp/WEB-INF/jsp/admin/permission-groups.jsp b/src/main/webapp/WEB-INF/jsp/admin/permission-groups.jsp new file mode 100644 index 00000000..fc280230 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/admin/permission-groups.jsp @@ -0,0 +1,50 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="font" uri="/WEB-INF/tlds/font-functions.tld" %> + + + + +

+
+<%@include file="../page_messages.jspf" %> + + +

No permission groups are currently loaded.

+
+ + +
+
+ + + — + +
+
+

Cedar Policy

+
+

Components

+ + + + + + + + + + + + + + + + + + +
ClassType
No members registered
+
+
+
+
+
diff --git a/src/main/webapp/WEB-INF/permission-groups/component-groups.xml b/src/main/webapp/WEB-INF/permission-groups/component-groups.xml new file mode 100644 index 00000000..3b243165 --- /dev/null +++ b/src/main/webapp/WEB-INF/permission-groups/component-groups.xml @@ -0,0 +1,362 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/WEB-INF/permission-groups/policies/site-blog-editor.cedar b/src/main/webapp/WEB-INF/permission-groups/policies/site-blog-editor.cedar new file mode 100644 index 00000000..cf821843 --- /dev/null +++ b/src/main/webapp/WEB-INF/permission-groups/policies/site-blog-editor.cedar @@ -0,0 +1,14 @@ +// Permission policy for the Site Blog Editor feature group. +// Covers the blog post widget (viewing drafts, deleting posts). +// Grants the "access" action to any principal whose roles contain "admin" +// or "content-manager". + +permit ( + principal, + action == CMS::Action::"access", + resource in CMS::PermissionGroup::"site-blog-editor" +) +when { + "admin" in principal.roles || + "content-manager" in principal.roles +}; diff --git a/src/main/webapp/WEB-INF/permission-groups/policies/site-content-editor.cedar b/src/main/webapp/WEB-INF/permission-groups/policies/site-content-editor.cedar new file mode 100644 index 00000000..770edc14 --- /dev/null +++ b/src/main/webapp/WEB-INF/permission-groups/policies/site-content-editor.cedar @@ -0,0 +1,15 @@ +// Permission policy for the Site Content Editor feature group. +// Covers the content widget (inline HTML/content-block editing), +// the menu widget (TOC editor access), and the sub-folder form widget. +// Grants the "access" action to any principal whose roles contain "admin" +// or "content-manager". + +permit ( + principal, + action == CMS::Action::"access", + resource in CMS::PermissionGroup::"site-content-editor" +) +when { + "admin" in principal.roles || + "content-manager" in principal.roles +}; diff --git a/src/main/webapp/WEB-INF/permission-groups/policies/visual-content-editor.cedar b/src/main/webapp/WEB-INF/permission-groups/policies/visual-content-editor.cedar new file mode 100644 index 00000000..ee485e20 --- /dev/null +++ b/src/main/webapp/WEB-INF/permission-groups/policies/visual-content-editor.cedar @@ -0,0 +1,16 @@ +// Permission policy for the Visual Content Editor feature group. +// Covers content blocks, page editor, sitemap, blogs, and calendars. +// Grants the "access" action to any principal whose roles contain "admin" +// or "content-manager" for any component that is a member of this group. +// The PageContentBlocksJsonService also extends access to "content-editor". + +permit ( + principal, + action == CMS::Action::"access", + resource in CMS::PermissionGroup::"visual-content-editor" +) +when { + "admin" in principal.roles || + "content-manager" in principal.roles || + "content-editor" in principal.roles +}; diff --git a/src/main/webapp/WEB-INF/permission-groups/policies/visual-crm-editor.cedar b/src/main/webapp/WEB-INF/permission-groups/policies/visual-crm-editor.cedar new file mode 100644 index 00000000..093733f9 --- /dev/null +++ b/src/main/webapp/WEB-INF/permission-groups/policies/visual-crm-editor.cedar @@ -0,0 +1,17 @@ +// Permission policy for the Visual CRM Editor feature group. +// Covers forms, mailing lists, customers, orders, product catalog, +// pricing rules, sales tax, shipping rates, users, groups, and roles. +// Grants "access" to admins, content-managers, and ecommerce-managers. +// User/group/role management (CRMUsers, CRMUserGroups, CRMUserRoles) +// requires admin only — enforced within those service implementations. + +permit ( + principal, + action == CMS::Action::"access", + resource in CMS::PermissionGroup::"visual-crm-editor" +) +when { + "admin" in principal.roles || + "content-manager" in principal.roles || + "ecommerce-manager" in principal.roles +}; diff --git a/src/main/webapp/WEB-INF/permission-groups/policies/visual-data-editor.cedar b/src/main/webapp/WEB-INF/permission-groups/policies/visual-data-editor.cedar new file mode 100644 index 00000000..b9357292 --- /dev/null +++ b/src/main/webapp/WEB-INF/permission-groups/policies/visual-data-editor.cedar @@ -0,0 +1,14 @@ +// Permission policy for the Visual Data Editor feature group. +// Covers collections, datasets, and data management operations. +// Grants the "access" action to any principal whose roles contain "admin" +// or "data-manager" for any component that is a member of this group. + +permit ( + principal, + action == CMS::Action::"access", + resource in CMS::PermissionGroup::"visual-data-editor" +) +when { + "admin" in principal.roles || + "data-manager" in principal.roles +}; diff --git a/src/main/webapp/WEB-INF/permission-groups/policies/visual-document-editor.cedar b/src/main/webapp/WEB-INF/permission-groups/policies/visual-document-editor.cedar new file mode 100644 index 00000000..3c0118ab --- /dev/null +++ b/src/main/webapp/WEB-INF/permission-groups/policies/visual-document-editor.cedar @@ -0,0 +1,14 @@ +// Permission policy for the Visual Document Editor feature group. +// Covers document library, folder management, file operations, and analytics. +// Grants the "access" action to any principal whose roles contain "admin" +// or "content-manager" for any component that is a member of this group. + +permit ( + principal, + action == CMS::Action::"access", + resource in CMS::PermissionGroup::"visual-document-editor" +) +when { + "admin" in principal.roles || + "content-manager" in principal.roles +}; diff --git a/src/main/webapp/WEB-INF/permission-groups/policies/visual-image-editor.cedar b/src/main/webapp/WEB-INF/permission-groups/policies/visual-image-editor.cedar new file mode 100644 index 00000000..03a52dde --- /dev/null +++ b/src/main/webapp/WEB-INF/permission-groups/policies/visual-image-editor.cedar @@ -0,0 +1,13 @@ +// Permission policy for the Visual Image Editor feature group. +// Grants the "access" action to any principal whose roles contain "admin" +// or "content-manager" for any component that is a member of this group. + +permit ( + principal, + action == CMS::Action::"access", + resource in CMS::PermissionGroup::"visual-image-editor" +) +when { + "admin" in principal.roles || + "content-manager" in principal.roles +}; diff --git a/src/main/webapp/WEB-INF/permission-groups/policies/visual-web-sync-editor.cedar b/src/main/webapp/WEB-INF/permission-groups/policies/visual-web-sync-editor.cedar new file mode 100644 index 00000000..6a646b09 --- /dev/null +++ b/src/main/webapp/WEB-INF/permission-groups/policies/visual-web-sync-editor.cedar @@ -0,0 +1,13 @@ +// Permission policy for the Visual Web Sync Editor feature group. +// Grants the "access" action to any principal whose roles contain "admin" +// or "content-manager" for any component that is a member of this group. + +permit ( + principal, + action == CMS::Action::"access", + resource in CMS::PermissionGroup::"visual-web-sync-editor" +) +when { + "admin" in principal.roles || + "content-manager" in principal.roles +}; diff --git a/src/main/webapp/WEB-INF/permission-groups/policies/visual-workflow-editor.cedar b/src/main/webapp/WEB-INF/permission-groups/policies/visual-workflow-editor.cedar new file mode 100644 index 00000000..35adc810 --- /dev/null +++ b/src/main/webapp/WEB-INF/permission-groups/policies/visual-workflow-editor.cedar @@ -0,0 +1,12 @@ +// Permission policy for the Visual Workflow Editor feature group. +// Covers workflow task and event management. +// Grants the "access" action only to principals whose roles contain "admin". + +permit ( + principal, + action == CMS::Action::"access", + resource in CMS::PermissionGroup::"visual-workflow-editor" +) +when { + "admin" in principal.roles +}; diff --git a/src/main/webapp/WEB-INF/web-layouts/page/admin-layout.xml b/src/main/webapp/WEB-INF/web-layouts/page/admin-layout.xml index c424b65b..1a798628 100644 --- a/src/main/webapp/WEB-INF/web-layouts/page/admin-layout.xml +++ b/src/main/webapp/WEB-INF/web-layouts/page/admin-layout.xml @@ -664,6 +664,17 @@ + +
+ + + fa-lock + Permission Groups + + +
+
+ diff --git a/src/main/webapp/WEB-INF/widgets/widget-library.xml b/src/main/webapp/WEB-INF/widgets/widget-library.xml index 6cc7da21..9a82e076 100644 --- a/src/main/webapp/WEB-INF/widgets/widget-library.xml +++ b/src/main/webapp/WEB-INF/widgets/widget-library.xml @@ -170,6 +170,7 @@ + From 49bb1745356a421b437530f9c33d1367a5e30075 Mon Sep 17 00:00:00 2001 From: Matt Rajkowski Date: Sun, 22 Mar 2026 15:26:14 -0400 Subject: [PATCH 2/2] Sets policy values --- src/main/webapp/WEB-INF/permission-groups/component-groups.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/WEB-INF/permission-groups/component-groups.xml b/src/main/webapp/WEB-INF/permission-groups/component-groups.xml index 3b243165..4dc30b34 100644 --- a/src/main/webapp/WEB-INF/permission-groups/component-groups.xml +++ b/src/main/webapp/WEB-INF/permission-groups/component-groups.xml @@ -15,7 +15,7 @@ -