Refactored CmsController because the class was becoming too large.

pull/10/head
Jens Pelzetter 2021-11-18 19:53:05 +01:00
parent f8ef994da0
commit e842cbc9ff
6 changed files with 363 additions and 248 deletions

View File

@ -20,7 +20,6 @@ package org.librecms.ui;
import org.libreccm.ui.IsAuthenticatedFilter; import org.libreccm.ui.IsAuthenticatedFilter;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
import javax.ws.rs.ApplicationPath; import javax.ws.rs.ApplicationPath;
@ -36,12 +35,13 @@ public class CmsApplication extends Application {
@Override @Override
public Set<Class<?>> getClasses() { public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<>(); return Set.of(
IsAuthenticatedFilter.class,
classes.add(IsAuthenticatedFilter.class); CmsController.class,
classes.add(CmsController.class); ContentSectionsController.class,
PagesController.class,
return classes; SearchController.class
);
} }
} }

View File

@ -18,31 +18,17 @@
*/ */
package org.librecms.ui; 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.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.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Objects;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.mvc.Controller; import javax.mvc.Controller;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
@ -57,21 +43,9 @@ import javax.ws.rs.core.Response;
@Path("/") @Path("/")
public class CmsController { public class CmsController {
@Inject
private ContentSectionRepository sectionRepo;
@Inject
private ContentSectionManager sectionManager;
@Inject @Inject
private HttpServletRequest request; private HttpServletRequest request;
@Inject
private IdentifierParser identifierParser;
@Inject
private PermissionChecker permissionChecker;
/** /**
* Redirects requests to the root path ({@code /@cms} or {@code /@cms/}) to * Redirects requests to the root path ({@code /@cms} or {@code /@cms/}) to
* the {@code /@cms/contentsections}. * 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();
}
} }

View File

@ -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 <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@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();
}
}

View File

@ -46,7 +46,7 @@ public class ContentSectionsTableModel {
* The controller. * The controller.
*/ */
@Inject @Inject
private CmsController controller; private ContentSectionsController controller;
/** /**
* Repository for content sections. * Repository for content sections.

View File

@ -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 <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@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";
}
}

View File

@ -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 <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@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";
}
}