diff --git a/ccm-cms/src/main/java/org/librecms/ui/CmsApplication.java b/ccm-cms/src/main/java/org/librecms/ui/CmsApplication.java index 8bc4c238b..74aead65b 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/CmsApplication.java +++ b/ccm-cms/src/main/java/org/librecms/ui/CmsApplication.java @@ -20,7 +20,6 @@ package org.librecms.ui; import org.libreccm.ui.IsAuthenticatedFilter; -import java.util.HashSet; import java.util.Set; import javax.ws.rs.ApplicationPath; @@ -28,7 +27,7 @@ import javax.ws.rs.core.Application; /** * The CMS application acts as entry point for all CMS related user interfaces. - * + * * @author Jens Pelzetter */ @ApplicationPath("/@cms") @@ -36,12 +35,13 @@ public class CmsApplication extends Application { @Override public Set> getClasses() { - final Set> classes = new HashSet<>(); - - classes.add(IsAuthenticatedFilter.class); - classes.add(CmsController.class); - - return classes; + return Set.of( + IsAuthenticatedFilter.class, + CmsController.class, + ContentSectionsController.class, + PagesController.class, + SearchController.class + ); } } diff --git a/ccm-cms/src/main/java/org/librecms/ui/CmsController.java b/ccm-cms/src/main/java/org/librecms/ui/CmsController.java index 708157619..eb1d85281 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/CmsController.java +++ b/ccm-cms/src/main/java/org/librecms/ui/CmsController.java @@ -18,31 +18,17 @@ */ package org.librecms.ui; -import org.libreccm.api.Identifier; -import org.libreccm.api.IdentifierParser; -import org.libreccm.core.CoreConstants; import org.libreccm.security.AuthorizationRequired; -import org.libreccm.security.PermissionChecker; -import org.libreccm.security.RequiresPrivilege; -import org.librecms.contentsection.ContentSection; -import org.librecms.contentsection.ContentSectionManager; -import org.librecms.contentsection.ContentSectionRepository; -import org.librecms.contentsection.Folder; import java.net.URI; import java.net.URISyntaxException; -import java.util.Objects; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.mvc.Controller; import javax.servlet.http.HttpServletRequest; -import javax.transaction.Transactional; -import javax.ws.rs.FormParam; import javax.ws.rs.GET; -import javax.ws.rs.POST; import javax.ws.rs.Path; -import javax.ws.rs.PathParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; @@ -57,21 +43,9 @@ import javax.ws.rs.core.Response; @Path("/") public class CmsController { - @Inject - private ContentSectionRepository sectionRepo; - - @Inject - private ContentSectionManager sectionManager; - @Inject private HttpServletRequest request; - @Inject - private IdentifierParser identifierParser; - - @Inject - private PermissionChecker permissionChecker; - /** * Redirects requests to the root path ({@code /@cms} or {@code /@cms/}) to * the {@code /@cms/contentsections}. @@ -103,217 +77,4 @@ public class CmsController { } } - /** - * Shows all available content sections. - * - * @return The template to use. - */ - @GET - @Path("/contentsections/") - @AuthorizationRequired - public String getContentSections() { - return "org/librecms/ui/cms/contentsections-list.xhtml"; - } - - /** - * Creates a new content section. - * - * @param sectionName The name of the new section. - * - * @return Redirect to the content sections list. - */ - @POST - @Path("/contentsections/new") - @AuthorizationRequired - @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) - @Transactional(Transactional.TxType.REQUIRED) - public String createContentSection( - @FormParam("sectionName") final String sectionName - ) { - sectionManager.createContentSection(sectionName); - - return "redirect:/contentsections/"; - } - - /** - * Renames a content section. - * - * @param identifierParam The identifier (see {@link Identifier} and - * {@link IdentifierParser}) of the content section - * to rename. - * @param sectionName The new name of the content section. - * - * @return Redirect to the list of content sections. - */ - @POST - @Path("/contentsections/{sectionIdentifier}/rename") - @AuthorizationRequired - @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) - @Transactional(Transactional.TxType.REQUIRED) - public String renameContentSection( - @PathParam("sectionIdentifier") final String identifierParam, - @FormParam("sectionName") final String sectionName - ) { - final ContentSection section = findContentSection(identifierParam); - - sectionManager.renameContentSection(section, sectionName); - - return "redirect:/contentsections/"; - } - - /** - * Deletes a content section. The content section must be empty (no items, - * assets or folders in it). - * - * @param identifierParam The identifier (see {@link Identifier} and - * {@link IdentifierParser}) of the content section - * to delete. - * @param confirmed A string which must contain the value {@code true} - * to be sure that the user confirmed the deletion of - * the content section. - * - * @return Redirect to the list of content sections. - */ - @POST - @Path("/contentsections/{sectionIdentifier}/delete") - @AuthorizationRequired - @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) - @Transactional(Transactional.TxType.REQUIRED) - public String deleteContentSection( - @PathParam("sectionIdentifier") final String identifierParam, - @FormParam("confirmed") final String confirmed - ) { - if (Objects.equals(confirmed, "true")) { - final ContentSection section = findContentSection(identifierParam); - - if (!canDelete(section)) { - throw new WebApplicationException( - String.format( - "ContentSection %s is not empty and can't be deleted.", - section.getLabel() - ), - Response.Status.BAD_REQUEST - ); - } - - sectionManager.deleteContentSection(section); - } - - return "redirect:/contentsections/"; - } - - /** - * ToDo: Show UI for managing pages. - * - * @return Placeholder - */ - @GET - @Path("/pages") - @AuthorizationRequired - public String getPages() { - return "org/librecms/ui/cms/pages.xhtml"; - } - - /** - * ToDo: Search for content items (and assets?) in all content sections. - * - * @return Placeholder - */ - @GET - @Path("/search") - @AuthorizationRequired - public String getSearch() { - return "org/librecms/ui/cms/search.xhtml"; - } - - /** - * Helper function for retrieving a content section by an identifier. - * - * @param identifierParam The identifier paramter. - * - * @return The content section if a section identified by the provided - * identifier exists. - * - * @throws WebApplicationException A {@link WebApplicationException} with - * {@link Response.Status#NOT_FOUND} status - * code if there is not content section - * identified by the provided identifier. - * - * @see IdentifierParser - * @see Identifier - */ - private ContentSection findContentSection(final String identifierParam) { - final Identifier identifier = identifierParser.parseIdentifier( - identifierParam - ); - - final ContentSection section; - switch (identifier.getType()) { - case ID: - section = sectionRepo.findById( - Long.parseLong(identifier.getIdentifier()) - ).orElseThrow( - () -> new WebApplicationException( - String.format( - "No ContentSection identified by ID %s " - + "available.", - identifierParam - ), - Response.Status.NOT_FOUND - ) - ); - break; - case UUID: - section = sectionRepo - .findByUuid(identifier.getIdentifier()) - .orElseThrow( - () -> new WebApplicationException( - String.format( - "No ContentSection identifed UUID %s " - + "available.", - identifierParam - ), - Response.Status.NOT_FOUND - ) - ); - break; - default: - section = sectionRepo - .findByLabel(identifier.getIdentifier()) - .orElseThrow( - () -> new WebApplicationException( - String.format( - "No ContentSection with name %s " - + "available.", - identifierParam - ), - Response.Status.NOT_FOUND - ) - ); - break; - } - - return section; - } - - /** - * Helper function to determine of a content section can be deleted. Checks - * if the {@link ContentSection#rootAssetsFolder} and the - * {@link ContentSection#rootDocumentsFolder} are empty. - * - * @param section The section - * - * @return {@code true} if the content section is empty can be deleted, - * {@code false} is not. - */ - protected boolean canDelete(final ContentSection section) { - final Folder rootAssetsFolder = section.getRootAssetsFolder(); - final Folder rootDocumentsFolder = section.getRootDocumentsFolder(); - - return rootAssetsFolder.getSubFolders().isEmpty() - && rootAssetsFolder.getObjects().isEmpty() - && rootDocumentsFolder.getSubFolders().isEmpty() - && rootDocumentsFolder.getObjects().isEmpty(); - } - } diff --git a/ccm-cms/src/main/java/org/librecms/ui/ContentSectionsController.java b/ccm-cms/src/main/java/org/librecms/ui/ContentSectionsController.java new file mode 100644 index 000000000..f320a8521 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/ContentSectionsController.java @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2021 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import org.libreccm.api.Identifier; +import org.libreccm.api.IdentifierParser; +import org.libreccm.core.CoreConstants; +import org.libreccm.security.AuthorizationRequired; +import org.libreccm.security.PermissionChecker; +import org.libreccm.security.RequiresPrivilege; +import org.librecms.contentsection.ContentSection; +import org.librecms.contentsection.ContentSectionManager; +import org.librecms.contentsection.ContentSectionRepository; +import org.librecms.contentsection.Folder; + +import java.util.Objects; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.mvc.Controller; +import javax.transaction.Transactional; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Controller +@Path("/") +public class ContentSectionsController { + + @Inject + private ContentSectionRepository sectionRepo; + + @Inject + private ContentSectionManager sectionManager; + + @Inject + private IdentifierParser identifierParser; + + @Inject + private PermissionChecker permissionChecker; + + /** + * Shows all available content sections. + * + * @return The template to use. + */ + @GET + @Path("/") + @AuthorizationRequired + public String getContentSections() { + return "org/librecms/ui/cms/contentsections-list.xhtml"; + } + + /** + * Creates a new content section. + * + * @param sectionName The name of the new section. + * + * @return Redirect to the content sections list. + */ + @POST + @Path("/new") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public String createContentSection( + @FormParam("sectionName") final String sectionName + ) { + sectionManager.createContentSection(sectionName); + + return "redirect:/contentsections/"; + } + + /** + * Renames a content section. + * + * @param identifierParam The identifier (see {@link Identifier} and + * {@link IdentifierParser}) of the content section + * to rename. + * @param sectionName The new name of the content section. + * + * @return Redirect to the list of content sections. + */ + @POST + @Path("/{sectionIdentifier}/rename") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public String renameContentSection( + @PathParam("sectionIdentifier") final String identifierParam, + @FormParam("sectionName") final String sectionName + ) { + final ContentSection section = findContentSection(identifierParam); + + sectionManager.renameContentSection(section, sectionName); + + return "redirect:/contentsections/"; + } + + /** + * Deletes a content section. The content section must be empty (no items, + * assets or folders in it). + * + * @param identifierParam The identifier (see {@link Identifier} and + * {@link IdentifierParser}) of the content section + * to delete. + * @param confirmed A string which must contain the value {@code true} + * to be sure that the user confirmed the deletion of + * the content section. + * + * @return Redirect to the list of content sections. + */ + @POST + @Path("/{sectionIdentifier}/delete") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + @Transactional(Transactional.TxType.REQUIRED) + public String deleteContentSection( + @PathParam("sectionIdentifier") final String identifierParam, + @FormParam("confirmed") final String confirmed + ) { + if (Objects.equals(confirmed, "true")) { + final ContentSection section = findContentSection(identifierParam); + + if (!canDelete(section)) { + throw new WebApplicationException( + String.format( + "ContentSection %s is not empty and can't be deleted.", + section.getLabel() + ), + Response.Status.BAD_REQUEST + ); + } + + sectionManager.deleteContentSection(section); + } + + return "redirect:/contentsections/"; + } + + /** + * Helper function for retrieving a content section by an identifier. + * + * @param identifierParam The identifier paramter. + * + * @return The content section if a section identified by the provided + * identifier exists. + * + * @throws WebApplicationException A {@link WebApplicationException} with + * {@link Response.Status#NOT_FOUND} status + * code if there is not content section + * identified by the provided identifier. + * + * @see IdentifierParser + * @see Identifier + */ + private ContentSection findContentSection(final String identifierParam) { + final Identifier identifier = identifierParser.parseIdentifier( + identifierParam + ); + + final ContentSection section; + switch (identifier.getType()) { + case ID: + section = sectionRepo.findById( + Long.parseLong(identifier.getIdentifier()) + ).orElseThrow( + () -> new WebApplicationException( + String.format( + "No ContentSection identified by ID %s " + + "available.", + identifierParam + ), + Response.Status.NOT_FOUND + ) + ); + break; + case UUID: + section = sectionRepo + .findByUuid(identifier.getIdentifier()) + .orElseThrow( + () -> new WebApplicationException( + String.format( + "No ContentSection identifed UUID %s " + + "available.", + identifierParam + ), + Response.Status.NOT_FOUND + ) + ); + break; + default: + section = sectionRepo + .findByLabel(identifier.getIdentifier()) + .orElseThrow( + () -> new WebApplicationException( + String.format( + "No ContentSection with name %s " + + "available.", + identifierParam + ), + Response.Status.NOT_FOUND + ) + ); + break; + } + + return section; + } + + /** + * Helper function to determine of a content section can be deleted. Checks + * if the {@link ContentSection#rootAssetsFolder} and the + * {@link ContentSection#rootDocumentsFolder} are empty. + * + * @param section The section + * + * @return {@code true} if the content section is empty can be deleted, + * {@code false} is not. + */ + protected boolean canDelete(final ContentSection section) { + final Folder rootAssetsFolder = section.getRootAssetsFolder(); + final Folder rootDocumentsFolder = section.getRootDocumentsFolder(); + + return rootAssetsFolder.getSubFolders().isEmpty() + && rootAssetsFolder.getObjects().isEmpty() + && rootDocumentsFolder.getSubFolders().isEmpty() + && rootDocumentsFolder.getObjects().isEmpty(); + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/ui/ContentSectionsTableModel.java b/ccm-cms/src/main/java/org/librecms/ui/ContentSectionsTableModel.java index 02a7fc65f..cfff37306 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/ContentSectionsTableModel.java +++ b/ccm-cms/src/main/java/org/librecms/ui/ContentSectionsTableModel.java @@ -46,7 +46,7 @@ public class ContentSectionsTableModel { * The controller. */ @Inject - private CmsController controller; + private ContentSectionsController controller; /** * Repository for content sections. diff --git a/ccm-cms/src/main/java/org/librecms/ui/PagesController.java b/ccm-cms/src/main/java/org/librecms/ui/PagesController.java new file mode 100644 index 000000000..0566dd5e5 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/PagesController.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2021 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import org.libreccm.security.AuthorizationRequired; + +import javax.enterprise.context.RequestScoped; +import javax.mvc.Controller; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Controller +@Path("/pages") +public class PagesController { + + /** + * ToDo: Show UI for managing pages. + * + * @return Placeholder + */ + @GET + @Path("/") + @AuthorizationRequired + public String getPages() { + return "org/librecms/ui/cms/pages.xhtml"; + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/ui/SearchController.java b/ccm-cms/src/main/java/org/librecms/ui/SearchController.java new file mode 100644 index 000000000..27c124f9a --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/SearchController.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2021 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.ui; + +import org.libreccm.security.AuthorizationRequired; + +import javax.enterprise.context.RequestScoped; +import javax.mvc.Controller; +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +@Controller +@Path("/search") +public class SearchController { + + /** + * ToDo: Search for content items (and assets?) in all content sections. + * + * @return Placeholder + */ + @GET + @Path("/") + @AuthorizationRequired + public String getSearch() { + return "org/librecms/ui/cms/search.xhtml"; + } + +}