/* * Copyright (C) 2016 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.contentsection; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.libreccm.core.UnexpectedErrorException; import org.libreccm.modules.InstallEvent; import org.libreccm.security.Role; import org.libreccm.web.AbstractCcmApplicationSetup; import org.libreccm.workflow.Workflow; import org.librecms.CmsConstants; import java.util.UUID; import static org.librecms.contentsection.ContentSection.*; import org.librecms.contentsection.privileges.AdminPrivileges; import org.librecms.contentsection.privileges.AssetPrivileges; import org.librecms.contentsection.privileges.ItemPrivileges; import org.librecms.contenttypes.Article; import org.librecms.contenttypes.Event; import org.librecms.contenttypes.MultiPartArticle; import org.librecms.contenttypes.News; import java.util.Arrays; import org.librecms.contentsection.privileges.TypePrivileges; import org.librecms.lifecycle.LifecycleDefinition; import java.util.Locale; /** * * @author Jens Pelzetter */ public class ContentSectionSetup extends AbstractCcmApplicationSetup { private static final Logger LOGGER = LogManager.getLogger( ContentSectionSetup.class); private static final String INITIAL_CONTENT_SECTIONS = "org.librecms.initial_content_sections"; private static final String DEFAULT_ITEM_RESOLVER = "org.librecms.default_item_resolver"; private static final String[] DEFAULT_TYPES = new String[]{ Article.class.getName(), Event.class.getName(), MultiPartArticle.class.getName(), News.class.getName()}; public ContentSectionSetup(final InstallEvent event) { super(event); } @Override public void setup() { final String sectionNames; if (getIntegrationProps().containsKey(INITIAL_CONTENT_SECTIONS)) { sectionNames = getIntegrationProps().getProperty( INITIAL_CONTENT_SECTIONS); LOGGER.info( "Found names for initial content sections in integration " + "properties: {}", sectionNames); } else { sectionNames = "info"; LOGGER.info("No initial content sections definied integration " + "properties, using default: {}", sectionNames); } for (final String contentSectionName : sectionNames.split(",")) { createContentSection(contentSectionName); } } private void createContentSection(final String sectionName) { LOGGER.debug("Creating content section with section name \"{}\"...", sectionName); final ContentSection section = new ContentSection(); section.setUuid(UUID.randomUUID().toString()); section.setApplicationType(CmsConstants.CONTENT_SECTION_APP_TYPE); section.setPrimaryUrl(String.format("/%s/", sectionName)); section.setDisplayName(sectionName); section.setLabel(sectionName); LOGGER.debug("New content section properties: " + "uuid = {}; " + "applicationType = \"{}\"; " + "primaryUrl = \"{}\"; " + "displayName = \"{}\"; " + "label = \"{}\"", section.getUuid(), section.getApplicationType(), section.getPrimaryUrl(), section.getDisplayName(), section.getLabel()); final Folder rootFolder = new Folder(); rootFolder.setUuid(UUID.randomUUID().toString()); rootFolder.setUniqueId(rootFolder.getUuid()); rootFolder.setName(String.format("%s_" + ROOT, sectionName)); rootFolder.getTitle().putValue(new Locale("en"), "/"); rootFolder.setType(FolderType.DOCUMENTS_FOLDER); rootFolder.setSection(section); final Folder rootAssetFolder = new Folder(); rootAssetFolder.setName(String.format("%s_" + ASSETS, sectionName)); rootAssetFolder.getTitle().putValue(new Locale("en"), "/"); rootAssetFolder.setUuid(UUID.randomUUID().toString()); rootAssetFolder.setUniqueId(rootAssetFolder.getUuid()); rootAssetFolder.setType(FolderType.ASSETS_FOLDER); rootAssetFolder.setSection(section); section.setRootDocumentFolder(rootFolder); section.setRootAssetsFolder(rootAssetFolder); getEntityManager().persist(section); getEntityManager().persist(rootFolder); getEntityManager().persist(rootAssetFolder); LOGGER.debug( "Creating default roles and permissions for content section " + "'{}'...", sectionName); final Role alertRecipient = createRole(String.format( "%s_" + ALERT_RECIPIENT, sectionName)); final Role author = createRole(String.format("%s_" + AUTHOR, sectionName)); final Role editor = createRole(String.format("%s_" + EDITOR, sectionName)); final Role manager = createRole(String.format("%s_" + MANAGER, sectionName)); final Role publisher = createRole(String.format("%s_" + PUBLISHER, sectionName)); final Role contentReader = createRole(String.format( "%s_" + CONTENT_READER, sectionName)); grantPermissions(author, rootFolder, ItemPrivileges.CATEGORIZE, ItemPrivileges.CREATE_NEW, ItemPrivileges.EDIT, ItemPrivileges.VIEW_PUBLISHED, ItemPrivileges.PREVIEW); grantPermissions(author, rootAssetFolder, AssetPrivileges.USE, AssetPrivileges.CREATE_NEW, AssetPrivileges.EDIT, AssetPrivileges.VIEW, AssetPrivileges.DELETE); grantPermissions(editor, rootFolder, ItemPrivileges.CATEGORIZE, ItemPrivileges.CREATE_NEW, ItemPrivileges.EDIT, ItemPrivileges.APPROVE, ItemPrivileges.DELETE, ItemPrivileges.VIEW_PUBLISHED, ItemPrivileges.PREVIEW); grantPermissions(editor, rootAssetFolder, AssetPrivileges.USE, AssetPrivileges.CREATE_NEW, AssetPrivileges.EDIT, AssetPrivileges.VIEW, AssetPrivileges.DELETE); grantPermissions(manager, section, AdminPrivileges.ADMINISTER_ROLES, AdminPrivileges.ADMINISTER_WORKFLOWS, AdminPrivileges.ADMINISTER_LIFECYLES, AdminPrivileges.ADMINISTER_CATEGORIES, AdminPrivileges.ADMINISTER_CONTENT_TYPES); grantPermissions(manager, rootFolder, ItemPrivileges.ADMINISTER, ItemPrivileges.CATEGORIZE, ItemPrivileges.CREATE_NEW, ItemPrivileges.EDIT, ItemPrivileges.APPROVE, ItemPrivileges.PUBLISH, ItemPrivileges.DELETE, ItemPrivileges.VIEW_PUBLISHED, ItemPrivileges.PREVIEW); grantPermissions(manager, rootAssetFolder, AssetPrivileges.USE, AssetPrivileges.CREATE_NEW, AssetPrivileges.EDIT, AssetPrivileges.VIEW, AssetPrivileges.DELETE); grantPermissions(publisher, rootFolder, ItemPrivileges.CATEGORIZE, ItemPrivileges.CREATE_NEW, ItemPrivileges.EDIT, ItemPrivileges.APPROVE, ItemPrivileges.PUBLISH, ItemPrivileges.DELETE, ItemPrivileges.VIEW_PUBLISHED, ItemPrivileges.PREVIEW); grantPermissions(publisher, rootAssetFolder, AssetPrivileges.USE, AssetPrivileges.CREATE_NEW, AssetPrivileges.EDIT, AssetPrivileges.VIEW, AssetPrivileges.DELETE); grantPermissions(contentReader, rootFolder, ItemPrivileges.VIEW_PUBLISHED); grantPermissions(contentReader, rootAssetFolder, AssetPrivileges.VIEW); getEntityManager().persist(alertRecipient); getEntityManager().persist(author); getEntityManager().persist(editor); getEntityManager().persist(manager); getEntityManager().persist(publisher); getEntityManager().persist(contentReader); section.addRole(alertRecipient); section.addRole(author); section.addRole(editor); section.addRole(manager); section.addRole(publisher); section.addRole(contentReader); final LifecycleDefinition lifecycleDefinition = new LifecycleDefinition(); lifecycleDefinition.setUuid(UUID.randomUUID().toString()); lifecycleDefinition.getLabel().putValue(Locale.ENGLISH, "Standard"); final Workflow workflow = new Workflow(); workflow.setUuid(UUID.randomUUID().toString()); workflow.setAbstractWorkflow(true); workflow.getName().putValue(Locale.ENGLISH, "Standard"); section.addLifecycleDefinition(lifecycleDefinition); section.addWorkflowTemplate(workflow); getEntityManager().persist(lifecycleDefinition); getEntityManager().persist(workflow); LOGGER.debug("Adding default content types to content section '{}'...", sectionName); final String[] types; if (getIntegrationProps().containsKey(String.format("%s.content_types", sectionName))) { final String typesStr = getIntegrationProps().getProperty(String .format("%s.content_types", sectionName)); LOGGER.debug("integration.properties contains setting for content " + "types of section '{}': {}", sectionName, typesStr); types = typesStr.split(","); } else if (getIntegrationProps().containsKey("default_content_types")) { final String typesStr = getIntegrationProps().getProperty( "default_content_types"); LOGGER.debug("integration.properties contains setting for default " + "content types for all sections: {}", typesStr); types = typesStr.split(","); } else { LOGGER.debug("integration.properties contains not settings for " + "default content types. Using internal default: {}", String.join(", ", DEFAULT_TYPES)); types = DEFAULT_TYPES; } Arrays.stream(types).forEach(type -> addContentTypeToSection(section, type, author, editor, manager)); getEntityManager().merge(section); } private void addContentTypeToSection(final ContentSection section, final String contentType, final Role... roles) { final String typeClassName = contentType.trim(); LOGGER.debug("Adding content type '{}' to content section '{}'...", contentType, section.getPrimaryUrl()); final Class clazz; try { clazz = Class.forName(typeClassName); } catch (ClassNotFoundException ex) { throw new UnexpectedErrorException(String.format( "No class for content type '%s'.", typeClassName)); } if (ContentItem.class.isAssignableFrom(clazz)) { LOGGER.warn("'{}' is assignable from '{}'!", ContentItem.class.getName(), clazz.getName()); final ContentType type = new ContentType(); type.setContentSection(section); type.setUuid(UUID.randomUUID().toString()); type.setDisplayName(clazz.getSimpleName()); type.setContentItemClass(clazz.getName()); getEntityManager().persist(type); section.addContentType(type); Arrays.stream(roles) .forEach(role -> grantPermission(role, TypePrivileges.USE_TYPE, type)); } else { throw new UnexpectedErrorException(String.format( "The class '%s' is not a sub class of '%s'.", clazz.getName(), ContentItem.class.getName())); } } }