diff --git a/ccm-cms/src/main/java/org/librecms/Cms.java b/ccm-cms/src/main/java/org/librecms/Cms.java index ecaab22a7..224deef28 100644 --- a/ccm-cms/src/main/java/org/librecms/Cms.java +++ b/ccm-cms/src/main/java/org/librecms/Cms.java @@ -21,6 +21,23 @@ public class Cms implements CcmModule { @Override public void install(final InstallEvent event) { //ToDo Create initial data for the module if neccessary + + // Create initial content section + // If a list of sections is provided in the integration properties + // use that list, otherwise create a content section named 'info'. + + // Map given domains to content section(s) + + // Also create the following roles for each content section and assign + // the permissions + // + // * Alert Recipient + // * Author : Categorize Items, Create New Items, Edit Items, View Published Items, Preview Items + // * Editor : Categorize Items, Create New Items, Edit Items, Approve Items, Delete Items, View Published Items, Preview Items + // * Manager : Administer Roles, Administer Workflow, Administer Lifecycles, Administer Categories, Administer Content Types, Categorize Items, Create New Items, Edit Items, Approve Items, Publish Items, Delete Items, View Published Items, Preview Items + // * Publisher : Categorize Items, Create New Items, Edit Items, Approve Items, Publish Items, Delete Items, View Published Items, Preview Items + // * [Thrusted User]: Categorize Items, Create New Items, Edit Items, Apply Alternate Workflows, Approve Items, Publish Items, Delete Items, View Published Items, Preview Items + // * Content Reader: View Published Items } @Override diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSection.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSection.java index e42e7189d..858be2036 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentSection.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentSection.java @@ -69,11 +69,11 @@ public class ContentSection extends CcmApplication implements Serializable { @OneToOne @JoinColumn(name = "STAFF_ROLE_ID") - private Role staffRole; + private Role staffRole; //ToDo: Check if this is still necessary @OneToOne @JoinColumn(name = "VIEWERS_ROLE_ID") - private Role viewersRole; + private Role viewersRole; //ToDo: Check if this is still necessary @Column(name = "DEFAULT_LOCALE") private Locale defaultLocale; diff --git a/ccm-core/src/main/java/org/libreccm/categorization/Category.java b/ccm-core/src/main/java/org/libreccm/categorization/Category.java index 6b9ae8c15..4b753835d 100644 --- a/ccm-core/src/main/java/org/libreccm/categorization/Category.java +++ b/ccm-core/src/main/java/org/libreccm/categorization/Category.java @@ -18,6 +18,7 @@ */ package org.libreccm.categorization; +import static org.libreccm.categorization.CategorizationConstants.*; import static org.libreccm.core.CoreConstants.*; import org.hibernate.validator.constraints.NotBlank; @@ -48,6 +49,9 @@ import javax.persistence.NamedSubgraph; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.validation.constraints.Pattern; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; /** * The category entity represents a single category. Each category is part of a @@ -91,6 +95,7 @@ import javax.validation.constraints.Pattern; ) }) @DefaultEntityGraph("Category.withSubCategoriesAndObjects") +@XmlRootElement(name = "category", namespace = CAT_XML_NS) public class Category extends CcmObject implements InheritsPermissions, Serializable { @@ -101,6 +106,7 @@ public class Category extends CcmObject implements InheritsPermissions, * category system/domain is used in different installations. */ @Column(name = "UNIQUE_ID") + @XmlElement(name = "unique-id", namespace = CAT_XML_NS) private String uniqueId; /** @@ -110,6 +116,7 @@ public class Category extends CcmObject implements InheritsPermissions, @Column(name = "NAME", nullable = false) @NotBlank @Pattern(regexp = "[\\w-.]*") + @XmlElement(name ="name", namespace = CAT_XML_NS) private String name; /** @@ -123,6 +130,7 @@ public class Category extends CcmObject implements InheritsPermissions, joinColumns = { @JoinColumn(name = "OBJECT_ID")} )) + @XmlElementWrapper(name = "title", namespace = CAT_XML_NS) private LocalizedString title; /** @@ -136,6 +144,7 @@ public class Category extends CcmObject implements InheritsPermissions, joinColumns = { @JoinColumn(name = "OBJECT_ID")} )) + @XmlElementWrapper(name = "title", namespace = CAT_XML_NS) private LocalizedString description; /** @@ -143,6 +152,7 @@ public class Category extends CcmObject implements InheritsPermissions, * enabled, the category can't be used in any way. */ @Column(name = "ENABLED") + @XmlElement(name = "enabled", namespace = CAT_XML_NS) private boolean enabled; /** @@ -150,6 +160,7 @@ public class Category extends CcmObject implements InheritsPermissions, * visible should be only visible in the backend but not in the frontend. */ @Column(name = "VISIBLE") + @XmlElement(name = "visible", namespace = CAT_XML_NS) private boolean visible; /** @@ -157,18 +168,21 @@ public class Category extends CcmObject implements InheritsPermissions, * an abstract category. */ @Column(name = "ABSTRACT_CATEGORY") + @XmlElement(name = "abstract", namespace = CAT_XML_NS) private boolean abstractCategory; /** * The objects assigned to this category. */ @OneToMany(mappedBy = "category") + @XmlElementWrapper(name = "objects", namespace = CAT_XML_NS) private List objects; /** * The sub categories of this category. */ @OneToMany(mappedBy = "parentCategory") + @XmlElementWrapper(name = "subcategories", namespace = CAT_XML_NS) private List subCategories; /** @@ -183,6 +197,7 @@ public class Category extends CcmObject implements InheritsPermissions, * Numeric value to define the order of the categories. */ @Column(name = "CATEGORY_ORDER") + @XmlElement(name = "order", namespace = CAT_XML_NS) private long categoryOrder; public Category() { diff --git a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java index 1c50513b3..9fab32b1b 100644 --- a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java +++ b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java @@ -74,8 +74,6 @@ public class CcmCore implements CcmModule { @Override public void install(final InstallEvent event) { -// final EntityManager entityManager = event.getEntityManager(); - final SystemUsersSetup systemUsersSetup = new SystemUsersSetup( event); systemUsersSetup.setupSystemUsers(); @@ -87,6 +85,9 @@ public class CcmCore implements CcmModule { final LoginApplicationSetup loginSetup = new LoginApplicationSetup(event); loginSetup.setup(); + + // Load category domains from bundle/classpath + // File format: JAXB (but Jackson for reading the XML) } @Override diff --git a/ccm-core/src/main/java/org/libreccm/core/CoreConstants.java b/ccm-core/src/main/java/org/libreccm/core/CoreConstants.java index dca4277f2..8b16f2328 100644 --- a/ccm-core/src/main/java/org/libreccm/core/CoreConstants.java +++ b/ccm-core/src/main/java/org/libreccm/core/CoreConstants.java @@ -37,6 +37,12 @@ public final class CoreConstants { */ public static final String DB_SCHEMA = "CCM_CORE"; + /** + * Fully qualified name of file containing the integration properties of a + * bundle. + */ + public static final String INTEGRATION_PROPS = "/integration.properties"; + /** * String used as display name for the virtual Access denied objects * in the security API. diff --git a/ccm-core/src/main/java/org/libreccm/modules/ConfigurationLoader.java b/ccm-core/src/main/java/org/libreccm/modules/ConfigurationLoader.java index 37dcab3e9..1331add15 100644 --- a/ccm-core/src/main/java/org/libreccm/modules/ConfigurationLoader.java +++ b/ccm-core/src/main/java/org/libreccm/modules/ConfigurationLoader.java @@ -31,6 +31,7 @@ import org.libreccm.configuration.LongSetting; import org.libreccm.configuration.Setting; import org.libreccm.configuration.StringListSetting; import org.libreccm.configuration.StringSetting; +import org.libreccm.core.CoreConstants; import org.libreccm.l10n.LocalizedString; import java.io.IOException; @@ -43,8 +44,6 @@ import java.util.Properties; import java.util.Set; import javax.persistence.EntityManager; -import javax.persistence.EntityTransaction; -import javax.transaction.Transaction; /** * A helper class used by the {@link ModuleManager} to load the initial @@ -74,7 +73,7 @@ class ConfigurationLoader { integration = new Properties(); try (final InputStream inputStream = getClass().getResourceAsStream( - "/integration.properties")) { + CoreConstants.INTEGRATION_PROPS)) { if (inputStream == null) { LOGGER.warn("No integration properties found. Using empty " diff --git a/ccm-core/src/main/java/org/libreccm/modules/ModuleManager.java b/ccm-core/src/main/java/org/libreccm/modules/ModuleManager.java index 045a54f71..c37679dda 100644 --- a/ccm-core/src/main/java/org/libreccm/modules/ModuleManager.java +++ b/ccm-core/src/main/java/org/libreccm/modules/ModuleManager.java @@ -96,6 +96,10 @@ public class ModuleManager { @Transactional(Transactional.TxType.REQUIRED) public void initModules() { LOGGER.info("Initalising modules..."); + + final ConfigurationLoader confLoader = new ConfigurationLoader( + entityManager); + //Initialise all modules in the correct order for (final TreeNode node : moduleNodes) { @@ -111,6 +115,7 @@ public class ModuleManager { if (installedModule != null && installedModule.getStatus() == ModuleStatus.NEW) { node.getModule().install(installEvent); + confLoader.loadConfigurations(node.getModule()); installedModule.setStatus(ModuleStatus.INSTALLED); entityManager.merge(installedModule); } diff --git a/ccm-core/src/main/java/org/libreccm/security/ApplicationRoleSetup.java b/ccm-core/src/main/java/org/libreccm/security/ApplicationRoleSetup.java new file mode 100644 index 000000000..21ffe5809 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/security/ApplicationRoleSetup.java @@ -0,0 +1,77 @@ +/* + * 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.libreccm.security; + +import org.libreccm.core.CcmObject; +import org.libreccm.web.AbstractCcmApplicationSetup; + +import javax.persistence.EntityManager; + +/** + * A helper class used by the {@link AbstractCcmApplicationSetup} to create + * roles and permissions for the roles. This class is necessary because some + * constructors and methods of the classes {@link Role} and {@link Permission} + * are only accessible from this package. + * + * @author Jens Pelzetter + */ +public class ApplicationRoleSetup { + + private final EntityManager entityManager; + + public ApplicationRoleSetup(final EntityManager entityManager) { + this.entityManager = entityManager; + } + + public Role createRole(final String name) { + final Role role = new Role(); + role.setName(name); + + entityManager.persist(role); + + return role; + } + + private Permission createPermission(final Role role, final String privilege) { + final Permission permission = new Permission(); + permission.setGrantedPrivilege(privilege); + permission.setGrantee(role); + role.addPermission(permission); + + return permission; + } + + public void grantPermission(final Role role, final String privilege) { + final Permission permission = createPermission(role, privilege); + + entityManager.persist(permission); + entityManager.merge(role); + } + + public void grantPermission(final Role role, + final String privilege, + final CcmObject ccmObject) { + final Permission permission = createPermission(role, privilege); + permission.setObject(ccmObject); + + entityManager.persist(privilege); + entityManager.merge(role); + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/security/SystemUsersSetup.java b/ccm-core/src/main/java/org/libreccm/security/SystemUsersSetup.java index 8f59ae5d4..477e893da 100644 --- a/ccm-core/src/main/java/org/libreccm/security/SystemUsersSetup.java +++ b/ccm-core/src/main/java/org/libreccm/security/SystemUsersSetup.java @@ -21,6 +21,7 @@ package org.libreccm.security; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.libreccm.core.CcmCore; +import org.libreccm.core.CoreConstants; import org.libreccm.core.EmailAddress; import org.libreccm.modules.InstallEvent; @@ -41,6 +42,12 @@ public class SystemUsersSetup { private static final Logger LOGGER = LogManager.getLogger( SystemUsersSetup.class); + private static final String ADMIN_NAME = "admin.name"; + private static final String ADMIN_FAMILY_NAME = "admin.family_name"; + private static final String ADMIN_GIVEN_NAME = "admin.given_name"; + private static final String ADMIN_EMAIL_ADDRESS = "admin.email_address"; + private static final String ADMIN_PASSWORD = "admin.password"; + //Default password is "libreccm" private static final String DEFAULT_ADMIN_PW = "$shiro1$SHA-512$500000$MFPkVikNoRrBZ8R8CxQIHA==$ybEECtSPukmXDbV27a3LnWktFsh9lQl2ZYqCUtV0NF9G35Rt0+Tzp1msNLBQUVv15SrsdFgBSfhgWfZFyTva+Q=="; @@ -59,41 +66,26 @@ public class SystemUsersSetup { private void createAdmin() { LOGGER.info("Creating admin user..."); - final User admin = new User(); - admin.setName("admin"); - admin.setFamilyName("LibreCCM"); - admin.setGivenName("System Administrator"); - final EmailAddress adminEmail = new EmailAddress(); - adminEmail.setAddress("admin@libreccm.example"); - admin.setPrimaryEmailAddress(adminEmail); - String adminPassword = DEFAULT_ADMIN_PW; - try (final InputStream inputStream = getClass().getResourceAsStream( - "/integration.properties")) { - if (inputStream == null) { - LOGGER.warn( - "No integration.properties file found. Using default " - + "password (see documentation)"); - } else { - final Properties properties = new Properties(); - try { - properties.load(inputStream); - final String password = properties.getProperty( - "admin.password"); - if (password != null && !password.isEmpty()) { - adminPassword = password; - } - } catch (IOException ex) { - LOGGER.warn("Failed to load integration.properties. " - + "Using default password.", - ex); - } - } - } catch (IOException ex) { - LOGGER.warn("Exception while reading integration.properties file." - + "Using default password for admin account. ", - ex); - } + final Properties integrationProps = getIntegrationProps(); + final String adminName = integrationProps.getProperty(ADMIN_NAME, + "admin"); + final String adminFamilyName = integrationProps.getProperty( + ADMIN_FAMILY_NAME, "LibreCCM"); + final String adminGivenName = integrationProps.getProperty( + ADMIN_GIVEN_NAME, "System Administrator"); + final String adminEmailAddress = integrationProps.getProperty( + ADMIN_EMAIL_ADDRESS, "admin@libreccm.example"); + final String adminPassword = integrationProps.getProperty( + ADMIN_PASSWORD, DEFAULT_ADMIN_PW);; + + final User admin = new User(); + admin.setName(adminName); + admin.setFamilyName(adminFamilyName); + admin.setGivenName(adminGivenName); + final EmailAddress adminEmail = new EmailAddress(); + adminEmail.setAddress(adminEmailAddress); + admin.setPrimaryEmailAddress(adminEmail); admin.setPassword(adminPassword); final Role adminRole = new Role(); @@ -128,4 +120,20 @@ public class SystemUsersSetup { entityManager.persist(user); } + private Properties getIntegrationProps() { + try (final InputStream inputStream = getClass().getResourceAsStream( + CoreConstants.INTEGRATION_PROPS)) { + final Properties properties = new Properties(); + if (inputStream == null) { + LOGGER.warn("No integration properties available."); + properties.load(inputStream); + } + return properties; + } catch (IOException ex) { + LOGGER.warn("Failed to load integration properties from bundle. " + + "Using empty integration properties.", ex); + return new Properties(); + } + } + } diff --git a/ccm-core/src/main/java/org/libreccm/web/AbstractCcmApplicationSetup.java b/ccm-core/src/main/java/org/libreccm/web/AbstractCcmApplicationSetup.java index 94b5404e6..3e855cba8 100644 --- a/ccm-core/src/main/java/org/libreccm/web/AbstractCcmApplicationSetup.java +++ b/ccm-core/src/main/java/org/libreccm/web/AbstractCcmApplicationSetup.java @@ -18,7 +18,18 @@ */ package org.libreccm.web; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.libreccm.core.CcmObject; +import org.libreccm.core.CoreConstants; import org.libreccm.modules.InstallEvent; +import org.libreccm.security.ApplicationRoleSetup; +import org.libreccm.security.Permission; +import org.libreccm.security.Role; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; import javax.persistence.EntityManager; @@ -27,17 +38,50 @@ import javax.persistence.EntityManager; * @author Jens Pelzetter */ public abstract class AbstractCcmApplicationSetup { - + + private static final Logger LOGGER = LogManager.getLogger( + AbstractCcmApplicationSetup.class); + private final EntityManager entityManager; - + private final ApplicationRoleSetup appRoleSetup; + public AbstractCcmApplicationSetup(final InstallEvent event) { this.entityManager = event.getEntityManager(); + appRoleSetup = new ApplicationRoleSetup(entityManager); } - + protected EntityManager getEntityManager() { return entityManager; } - + + protected Properties getIntegrationProps() { + try (InputStream inputStream = getClass().getResourceAsStream( + CoreConstants.INTEGRATION_PROPS)) { + final Properties properties = new Properties(); + properties.load(inputStream); + return properties; + } catch (IOException ex) { + LOGGER.warn( + "Failed to load integration properties. Using empty properties.", + ex); + return new Properties(); + } + } + + public Role createRole(final String name) { + return appRoleSetup.createRole(name); + } + + public void grantPermission(final Role role, final String privilege) { + appRoleSetup.grantPermission(role, privilege); + } + + public void grantPermission(final Role role, + final String privilege, + final CcmObject ccmObject) { + appRoleSetup.grantPermission(role, privilege, ccmObject); + } + public abstract void setup(); - + }