CCM NG: ContentSectionManager

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4195 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-07-13 16:38:26 +00:00
parent 0e291a87b9
commit 2948e65c3a
7 changed files with 454 additions and 58 deletions

View File

@ -131,10 +131,10 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<source>1.8</source>
<target>1.8</target>
<optimize>true</optimize>
<debug>true</debug>
<encoding>${project.build.sourceEncoding}</encoding>

View File

@ -23,12 +23,16 @@ import org.libreccm.security.Role;
import org.libreccm.web.CcmApplication;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@ -44,6 +48,16 @@ public class ContentSection extends CcmApplication implements Serializable {
private static final long serialVersionUID = -671718122153931727L;
protected static final String ROOT = "root";
protected static final String ASSETS = "assets";
protected static final String ALERT_RECIPIENT = "alert_recipient";
protected static final String AUTHOR = "author";
protected static final String EDITOR = "editor";
protected static final String MANAGER = "manager";
protected static final String PUBLISHER = "publisher";
protected static final String CONTENT_READER = "content_reader";
@Column(name = "LABEL", length = 512)
private String label;
@ -67,13 +81,16 @@ public class ContentSection extends CcmApplication implements Serializable {
@Column(name = "XML_GENERATOR_CLASS", length = 1024)
private String xmlGeneratorClass;
@OneToOne
@JoinColumn(name = "STAFF_ROLE_ID")
private Role staffRole; //ToDo: Check if this is still necessary
@OneToOne
@JoinColumn(name = "VIEWERS_ROLE_ID")
private Role viewersRole; //ToDo: Check if this is still necessary
@ManyToMany
@JoinTable(name = "CONTENT_SECTION_ROLES",
schema = DB_SCHEMA,
joinColumns = {
@JoinColumn(name = "SECTION_ID")
},
inverseJoinColumns = {
@JoinColumn(name = "ROLE_ID")
})
private List<Role> roles;
@Column(name = "DEFAULT_LOCALE")
private Locale defaultLocale;
@ -134,20 +151,20 @@ public class ContentSection extends CcmApplication implements Serializable {
this.xmlGeneratorClass = xmlGeneratorClass;
}
public Role getStaffRole() {
return staffRole;
public List<Role> getRoles() {
return Collections.unmodifiableList(roles);
}
public void setStaffRole(final Role staffRole) {
this.staffRole = staffRole;
protected void setRoles(final List<Role> roles) {
this.roles = roles;
}
public Role getViewersRole() {
return viewersRole;
protected void addRole(final Role role) {
roles.add(role);
}
public void setViewersRole(final Role viewersRole) {
this.viewersRole = viewersRole;
protected void removeRole(final Role role) {
roles.remove(role);
}
public Locale getDefaultLocale() {

View File

@ -0,0 +1,216 @@
/*
* 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.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryRepository;
import org.libreccm.core.CoreConstants;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.PermissionManager;
import org.libreccm.security.RequiresPrivilege;
import org.libreccm.security.Role;
import org.libreccm.security.RoleManager;
import org.libreccm.security.RoleRepository;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
import static org.librecms.CmsConstants.*;
import static org.librecms.contentsection.ContentSection.*;
/**
* Provides several functions for managing content sections.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
public class ContentSectionManager {
@Inject
private ContentSectionRepository sectionRepo;
@Inject
private CategoryRepository categoryRepo;
@Inject
private RoleRepository roleRepo;
@Inject
private RoleManager roleManager;
@Inject
private PermissionManager permissionManager;
/**
* Creates a new content section including the default roles.
*
* @param name The name of the new content section.
*
* @return The new content section.
*/
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.ADMIN_PRIVILEGE)
@Transactional(Transactional.TxType.REQUIRED)
public ContentSection createContentSection(final String name) {
final ContentSection section = new ContentSection();
section.setLabel(name);
final Category rootFolder = new Category();
rootFolder.setName(String.format("%s_root", name));
final Category rootAssetFolder = new Category();
rootFolder.setName(String.format("%s_assets", name));
section.setRootDocumentFolder(rootFolder);
section.setRootAssetsFolder(rootAssetFolder);
sectionRepo.save(section);
categoryRepo.save(rootFolder);
categoryRepo.save(rootAssetFolder);
addRoleToContentSection(section,
String.format("%s_" + ALERT_RECIPIENT, name));
addRoleToContentSection(section,
String.format("%s_" + AUTHOR, name),
PRIVILEGE_ITEMS_CATEGORIZE,
PRIVILEGE_ITEMS_CREATE_NEW,
PRIVILEGE_ITEMS_EDIT,
PRIVILEGE_ITEMS_VIEW_PUBLISHED,
PRIVILEGE_ITEMS_PREVIEW);
addRoleToContentSection(section,
String.format("%s_" + EDITOR, name),
PRIVILEGE_ITEMS_CATEGORIZE,
PRIVILEGE_ITEMS_CREATE_NEW,
PRIVILEGE_ITEMS_EDIT,
PRIVILEGE_ITEMS_APPROVE,
PRIVILEGE_ITEMS_DELETE,
PRIVILEGE_ITEMS_VIEW_PUBLISHED,
PRIVILEGE_ITEMS_PREVIEW);
addRoleToContentSection(section,
String.format("%s_" + MANAGER, name),
PRIVILEGE_ADMINISTER_ROLES,
PRIVILEGE_ADMINISTER_WORKFLOW,
PRIVILEGE_ADMINISTER_LIFECYLES,
PRIVILEGE_ADMINISTER_CATEGORIES,
PRIVILEGE_ADMINISTER_CONTENT_TYPES,
PRIVILEGE_ITEMS_CATEGORIZE,
PRIVILEGE_ITEMS_CREATE_NEW,
PRIVILEGE_ITEMS_EDIT,
PRIVILEGE_ITEMS_APPROVE,
PRIVILEGE_ITEMS_PUBLISH,
PRIVILEGE_ITEMS_DELETE,
PRIVILEGE_ITEMS_VIEW_PUBLISHED,
PRIVILEGE_ITEMS_PREVIEW);
addRoleToContentSection(section,
String.format("%s_" + PUBLISHER, name),
PRIVILEGE_ITEMS_CATEGORIZE,
PRIVILEGE_ITEMS_CREATE_NEW,
PRIVILEGE_ITEMS_EDIT,
PRIVILEGE_ITEMS_APPROVE,
PRIVILEGE_ITEMS_PUBLISH,
PRIVILEGE_ITEMS_DELETE,
PRIVILEGE_ITEMS_VIEW_PUBLISHED,
PRIVILEGE_ITEMS_PREVIEW);
addRoleToContentSection(section,
String.format("%s_" + CONTENT_READER, name),
PRIVILEGE_ITEMS_VIEW_PUBLISHED);
return section;
}
/**
* Renames a content section and all roles associated with it (roles
* starting with the name of the content section).
*
* @param section The section to rename.
*
* @@param name The new name of the content section.
*/
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.ADMIN_PRIVILEGE)
@Transactional(Transactional.TxType.REQUIRED)
public void renameContentSection(final ContentSection section,
final String name) {
final String oldName = section.getLabel();
section.setLabel(name);
section.getRoles().forEach(r -> renameSectionRole(r, oldName, name));
}
private void renameSectionRole(final Role role,
final String oldName,
final String newName) {
if (role.getName().startsWith(oldName, 0)) {
final String suffix = role.getName().substring(oldName.length());
role.setName(String.join("", newName, suffix));
roleRepo.save(role);
}
}
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.ADMIN_PRIVILEGE)
@Transactional(Transactional.TxType.REQUIRED)
public void addRoleToContentSection(final ContentSection section,
final String roleName,
final String... privileges) {
final Role role = new Role();
role.setName(String.join("_", section.getLabel(), roleName));
roleRepo.save(role);
final Category rootFolder = section.getRootDocumentsFolder();
for (String privilege : privileges) {
permissionManager.grantPrivilege(privilege, role, rootFolder);
}
section.addRole(role);
sectionRepo.save(section);
}
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.ADMIN_PRIVILEGE)
@Transactional(Transactional.TxType.REQUIRED)
public void removeRoleFromContentSection(
final ContentSection contentSection,
final Role role) {
contentSection.removeRole(role);
sectionRepo.save(contentSection);
roleRepo.delete(role);
}
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.ADMIN_PRIVILEGE)
@Transactional(Transactional.TxType.REQUIRED)
public void addTypeToSection(final ContentType type,
final ContentSection section) {
throw new UnsupportedOperationException();
}
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.ADMIN_PRIVILEGE)
@Transactional(Transactional.TxType.REQUIRED)
public void removeTypeToSection(final ContentType type,
final ContentSection section) {
throw new UnsupportedOperationException();
}
}

View File

@ -19,8 +19,12 @@
package org.librecms.contentsection;
import org.libreccm.core.AbstractEntityRepository;
import org.libreccm.core.CoreConstants;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege;
import javax.enterprise.context.RequestScoped;
import javax.transaction.Transactional;
/**
*
@ -40,4 +44,20 @@ public class ContentSectionRepository
return section.getObjectId() == 0;
}
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.ADMIN_PRIVILEGE)
@Transactional(Transactional.TxType.REQUIRED)
@Override
public void save(final ContentSection section) {
super.save(section);
}
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.ADMIN_PRIVILEGE)
@Transactional(Transactional.TxType.REQUIRED)
@Override
public void delete(final ContentSection section) {
super.delete(section);
}
}

View File

@ -26,6 +26,7 @@ import org.libreccm.security.Role;
import org.libreccm.web.AbstractCcmApplicationSetup;
import static org.librecms.CmsConstants.*;
import static org.librecms.contentsection.ContentSection.*;
/**
*
@ -45,28 +46,28 @@ public class ContentSectionSetup extends AbstractCcmApplicationSetup {
@Override
public void setup() {
final String contentSectionNames;
final String sectionNames;
if (getIntegrationProps().containsKey(INITIAL_CONTENT_SECTIONS)) {
contentSectionNames = getIntegrationProps().getProperty(
sectionNames = getIntegrationProps().getProperty(
INITIAL_CONTENT_SECTIONS);
} else {
contentSectionNames = "info";
sectionNames = "info";
}
for (final String contentSectionName : contentSectionNames.split(",")) {
for (final String contentSectionName : sectionNames.split(",")) {
createContentSection(contentSectionName);
}
}
private void createContentSection(final String contentSectionName) {
private void createContentSection(final String sectionName) {
final ContentSection section = new ContentSection();
section.setLabel(contentSectionName);
section.setLabel(sectionName);
final Category rootFolder = new Category();
rootFolder.setName(String.format("%s_root", contentSectionName));
rootFolder.setName(String.format("%s_" + ROOT, sectionName));
final Category rootAssetFolder = new Category();
rootFolder.setName(String.format("%s_assets", contentSectionName));
rootFolder.setName(String.format("%s_" + ASSETS, sectionName));
section.setRootDocumentFolder(rootFolder);
section.setRootAssetsFolder(rootAssetFolder);
@ -76,17 +77,17 @@ public class ContentSectionSetup extends AbstractCcmApplicationSetup {
getEntityManager().persist(rootAssetFolder);
final Role alertRecipient = createRole(String.format(
"%s_alert_recipient", contentSectionName));
final Role author = createRole(String.format("%s_author",
contentSectionName));
final Role editor = createRole(String.format("%s_editor",
contentSectionName));
final Role manager = createRole(String.format("%s_manager",
contentSectionName));
final Role publisher = createRole(String.format("%s_publisher",
contentSectionName));
final Role contentReader = createRole(String.format("%s_content_reader",
contentSectionName));
"%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,
@ -122,7 +123,7 @@ public class ContentSectionSetup extends AbstractCcmApplicationSetup {
PRIVILEGE_ITEMS_VIEW_PUBLISHED,
PRIVILEGE_ITEMS_PREVIEW);
grantPermissions(editor,
grantPermissions(publisher,
rootFolder,
PRIVILEGE_ITEMS_CATEGORIZE,
PRIVILEGE_ITEMS_CREATE_NEW,
@ -137,7 +138,6 @@ public class ContentSectionSetup extends AbstractCcmApplicationSetup {
rootFolder,
PRIVILEGE_ITEMS_VIEW_PUBLISHED);
getEntityManager().persist(alertRecipient);
getEntityManager().persist(author);
getEntityManager().persist(editor);

View File

@ -3,18 +3,12 @@
*/
package org.librecms;
import org.librecms.Cms;
import static org.hamcrest.CoreMatchers.*;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.ShouldThrowException;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence;
import org.jboss.arquillian.persistence.CreateSchema;
import org.jboss.arquillian.persistence.PersistenceTest;
import org.jboss.arquillian.persistence.ShouldMatchDataSet;
import org.jboss.arquillian.persistence.UsingDataSet;
import org.jboss.arquillian.transaction.api.annotation.TransactionMode;
import org.jboss.arquillian.transaction.api.annotation.Transactional;
import org.jboss.shrinkwrap.api.ShrinkWrap;
@ -32,13 +26,10 @@ import org.junit.runner.RunWith;
import org.libreccm.tests.categories.IntegrationTest;
import java.io.File;
import java.util.List;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import static org.junit.Assert.*;
@Category(IntegrationTest.class)
@RunWith(Arquillian.class)

View File

@ -0,0 +1,152 @@
/*
* 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.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence;
import org.jboss.arquillian.persistence.CreateSchema;
import org.jboss.arquillian.persistence.PersistenceTest;
import org.jboss.arquillian.persistence.ShouldMatchDataSet;
import org.jboss.arquillian.persistence.UsingDataSet;
import org.jboss.arquillian.transaction.api.annotation.TransactionMode;
import org.jboss.arquillian.transaction.api.annotation.Transactional;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.libreccm.tests.categories.IntegrationTest;
import org.librecms.Cms;
import java.io.File;
import static org.junit.Assert.*;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Category(IntegrationTest.class)
@RunWith(Arquillian.class)
@PersistenceTest
@Transactional(TransactionMode.COMMIT)
@CreateSchema({"create_ccm_cms_schema.sql"})
public class ContentSectionManagerTest {
public ContentSectionManagerTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
@Deployment
public static WebArchive createDeployment() {
final PomEquippedResolveStage pom = Maven
.resolver()
.loadPomFromFile("pom.xml");
final PomEquippedResolveStage dependencies = pom
.importCompileAndRuntimeDependencies();
final File[] libs = dependencies.resolve().withTransitivity().asFile();
for (File lib : libs) {
System.err.printf("Adding file '%s' to test archive...%n",
lib.getName());
}
return ShrinkWrap
.create(WebArchive.class,
"LibreCCM-org.libreccm.cms.CmsTest.war")
.addPackage(Cms.class.getPackage())
.addAsLibraries(libs)
.addAsResource("test-persistence.xml",
"META-INF/persistence.xml")
.addAsWebInfResource("test-web.xml", "WEB-INF/web.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "WEB-INF/beans.xml");
}
@Test
@UsingDataSet("datasets/org/librecms/contentsection/"
+ "ContentSectionManagerTest/data.xml")
@ShouldMatchDataSet(
value = "datasets/org/librecms/contentsection/"
+ "ContentSectionManagerTest/after-create.xml",
excludeColumns = {"section_id"})
@InSequence(100)
public void createSection() {
}
@Test
@UsingDataSet("datasets/org/librecms/contentsection/"
+ "ContentSectionManagerTest/data.xml")
@ShouldMatchDataSet(
value = "datasets/org/librecms/contentsection/"
+ "ContentSectionManagerTest/after-rename.xml",
excludeColumns = {"section_id"})
@InSequence(200)
public void renameSection() {
}
@Test
@UsingDataSet("datasets/org/librecms/contentsection/"
+ "ContentSectionManagerTest/data.xml")
@ShouldMatchDataSet(
value = "datasets/org/librecms/contentsection/"
+ "ContentSectionManagerTest/after-add-role.xml",
excludeColumns = {"section_id"})
@InSequence(300)
public void addRole() {
}
@Test
@UsingDataSet("datasets/org/librecms/contentsection/"
+ "ContentSectionManagerTest/data.xml")
@ShouldMatchDataSet(
value = "datasets/org/librecms/contentsection/"
+ "ContentSectionManagerTest/after-remove-role.xml",
excludeColumns = {"section_id"})
@InSequence(300)
public void removeRole() {
}
}