- Some code cleanup
- PrivilegeRepository for creating and deleting permissions


git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3540 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2015-08-01 19:34:43 +00:00
parent 010a0c5c13
commit 6a334f9277
19 changed files with 515 additions and 116 deletions

View File

@ -379,11 +379,12 @@
<excludes>
<exclude>**/AbstractConfig.java</exclude>
<exclude>**/AbstractParameter.java</exclude>
<exclude>**/AbstractParameterContext</exclude>
<exclude>**/AbstractParameterContext.java</exclude>
<exclude>**/Assert.java</exclude>
<exclude>**/Classes.java</exclude>
<exclude>**/CCMApplicationContextListener.java</exclude>
<exclude>**/CCMResourceManager.java</exclude>
<exclude>**/Classes.java</exclude>
<exclude>**/ClassParameter.java</exclude>
<exclude>**/ClassParameterReader.java</exclude>
<exclude>**/CompoundParameterReader.java</exclude>
<exclude>**/ConfigError.java</exclude>
@ -391,8 +392,8 @@
<exclude>**/Converters.java</exclude>
<exclude>**/CSVParameterReader.java</exclude>
<exclude>**/DateFormatter.java</exclude>
<exclude>**/DataFormatterConfig.java</exclude>
<exclude>**/DateTimeFormatter</exclude>
<exclude>**/DateFormatterConfig.java</exclude>
<exclude>**/DateTimeFormatter.java</exclude>
<exclude>**/Document.java</exclude>
<exclude>**/Element.java</exclude>
<exclude>**/EmailParameter.java</exclude>
@ -416,9 +417,10 @@
<exclude>**/SecurityConfig.java</exclude>
<exclude>**/SecurityHelper.java</exclude>
<exclude>**/SingletonParameter.java</exclude>
<exclude>**/SpecificClassParameter.java</exclude>
<exclude>**/StringParameter.java</exclude>
<exclude>**/TimeFormatter.java</exclude>
<exclude>**/UncheckedWrapperException</exclude>
<exclude>**/UncheckedWrapperException.java</exclude>
<exclude>**/XML.java</exclude>
</excludes>
</configuration>

View File

@ -95,19 +95,19 @@ public class GroupManager {
"Can't remove a user from group null");
}
GroupMembership membershipToDelete = null;
GroupMembership delete = null;
for(final GroupMembership membership : group.getMembers()) {
if (membership.getUser().equals(user)) {
membershipToDelete = membership;
delete = membership;
break;
}
}
if (membershipToDelete != null) {
group.removeMember(membershipToDelete);
user.removeGroupMembership(membershipToDelete);
if (delete != null) {
group.removeMember(delete);
user.removeGroupMembership(delete);
entityManager.remove(membershipToDelete);
entityManager.remove(delete);
}
}

View File

@ -63,12 +63,18 @@ public class PermissionManager {
* Checks if the the provided {@code subject} has a permission granting the
* provided {@code privilege} on the provided {@code object}.
*
* If the provided subject is {@code null} the method will try to retrieve
* the public user from the database. If there is no public user the method
* will return {@code false}.
*
* @param privilege The privilege to check.
* @param object The object on which the privilege is granted.
* @param subject The subject to which the privilege is granted.
*
* @return {@code true} of the subject has a permission granting
* {@code privilege} on {@code object}, either explicit or implicit.
*
* @see UserRepository#retrievePublicUser()
*/
public boolean isPermitted(final Privilege privilege,
final CcmObject object,
@ -80,6 +86,10 @@ public class PermissionManager {
* Checks if the the provided {@code subject} has a permission granting the
* provided {@code privilege} on the provided {@code object}.
*
* If the provided subject is {@code null} the method will try to retrieve
* the public user from the database. If there is no public user the method
* will return {@code false}.
*
* @param privilege The privilege to check.
* @param object The object on which the privilege is granted.
* @param subject The subject to which the privilege is granted.
@ -88,6 +98,8 @@ public class PermissionManager {
* {@code privilege} on {@code object}
* to {@code subject}
*
* @see #isPermitted(org.libreccm.core.Privilege,
* org.libreccm.core.CcmObject, org.libreccm.core.Subject)
*/
public void checkPermission(final Privilege privilege,
final CcmObject object,

View File

@ -54,8 +54,9 @@ import javax.xml.bind.annotation.XmlRootElement;
query = "SELECT p FROM Privilege p "
+ "WHERE p.privilege = :name"),
@NamedQuery(name = "isPrivilegeInUse",
query = "SELECT COUNT(p) FROM Permission p JOIN Privilege r "
+ "WHERE r.privilege = :name")
query = "SELECT COUNT(p) FROM Permission p "
+ " JOIN p.grantedPrivilege g "
+ " WHERE g.privilege = :name")
})
@XmlRootElement(name = "privilege", namespace = CORE_XML_NS)
public class Privilege implements Serializable {

View File

@ -21,6 +21,7 @@ package org.libreccm.core;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
/**
@ -40,16 +41,24 @@ public class PrivilegeRepository {
/**
* Finds the {@link Privilege} identified by {@code name}.
*
* @param privilege The name of the privilege to return.
* @param name The name of the privilege to return.
*
* @return
* @return The requested privilege.
*
* @throws UnknownPrivilegeException if there is no privilege identified by
* the provided {@code name}.
*/
public Privilege retrievePrivilege(final String privilege) {
public Privilege retrievePrivilege(final String name) {
final TypedQuery<Privilege> query = entityManager.createNamedQuery(
"findPrivilegeByName", Privilege.class);
query.setParameter("name", privilege);
query.setParameter("name", name);
try {
return query.getSingleResult();
} catch (NoResultException ex) {
throw new UnknownPrivilegeException(String.format(
"There is no privilege \"%s\".", name), ex);
}
}
/**
@ -78,26 +87,34 @@ public class PrivilegeRepository {
* ToDo: Check if current user is system user.
*
* @param privilegeName The privilege to delete.
*
* @throws UnknownPrivilegeException if there is no privilege identified by
* the provided {@code name}.
*/
public void deletePrivilege(final String privilegeName) {
final Privilege privilege = retrievePrivilege(privilegeName);
if (isPrivilegeInUse(privilegeName)) {
throw new IllegalArgumentException(
"Provided privilage can't be removed because its still in use");
}
if (privilege != null) {
final Privilege privilege = retrievePrivilege(privilegeName);
entityManager.remove(privilege);
}
}
/**
* Checks a {@link Privilege} is in use.
*
* @param privilegeName The name of the privilege to check.
*
* @return {@code true} if the privilege is in use (there is a least one
* permission using it), {@code false} otherwise.
*/
public boolean isPrivilegeInUse(final String privilegeName) {
final TypedQuery<Integer> query = entityManager.createNamedQuery(
"isPrivilegeInUse", Integer.class);
final TypedQuery<Long> query = entityManager.createNamedQuery(
"isPrivilegeInUse", Long.class);
query.setParameter("name", privilegeName);
final Integer result = query.getSingleResult();
final Long result = query.getSingleResult();
return result > 0;
}

View File

@ -39,6 +39,11 @@ import org.libreccm.l10n.LocalizedString;
@Entity
@Table(name = "resource_types")
@Inheritance(strategy = InheritanceType.JOINED)
@SuppressWarnings({"PMD.CyclomaticComplexity",
"PMD.StdCyclomaticComplexity",
"PMD.ModifiedCyclomaticComplexity",
"PMD.NPathComplexity",
"PMD.LongVariable"})
public class ResourceType implements Serializable {
private static final long serialVersionUID = 4563584142251370627L;
@ -157,25 +162,25 @@ public class ResourceType implements Serializable {
return false;
}
if (this.resourceTypeId != other.resourceTypeId) {
if (this.resourceTypeId != other.getResourceTypeId()) {
return false;
}
if (!Objects.equals(this.title, other.title)) {
if (!Objects.equals(this.title, other.getTitle())) {
return false;
}
if (!Objects.equals(this.description, other.description)) {
if (!Objects.equals(this.description, other.getDescription())) {
return false;
}
if (this.workspaceApplication != other.workspaceApplication) {
if (this.workspaceApplication != other.isWorkspaceApplication()) {
return false;
}
if (this.viewableAsFullPage != other.viewableAsFullPage) {
if (this.viewableAsFullPage != other.isViewableAsFullPage()) {
return false;
}
if (this.viewableAsEmbedded != other.viewableAsEmbedded) {
if (this.viewableAsEmbedded != other.isViewableAsEmbedded()) {
return false;
}
return this.singleton == other.singleton;
return this.singleton == other.isSingleton();
}
public boolean canEqual(final Object obj) {
@ -207,4 +212,5 @@ public class ResourceType implements Serializable {
singleton,
data);
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2015 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.core;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class UnknownPrivilegeException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* Creates a new instance of <code>UnknownPrivilegeException</code> without
* detail message.
*/
public UnknownPrivilegeException() {
super();
}
/**
* Constructs an instance of <code>UnknownPrivilegeException</code> with the
* specified detail message.
*
* @param msg The detail message.
*/
public UnknownPrivilegeException(final String msg) {
super(msg);
}
/**
* Constructs an instance of <code>UnknownPrivilegeException</code> which
* wraps the specified exception.
*
* @param exception The exception to wrap.
*/
public UnknownPrivilegeException(final Exception exception) {
super(exception);
}
/**
* Constructs an instance of <code>UnknownPrivilegeException</code> with the
* specified message which also wraps the specified exception.
*
* @param msg The detail message.
* @param exception The exception to wrap.
*/
public UnknownPrivilegeException(final String msg, final Exception exception) {
super(msg, exception);
}
}

View File

@ -43,6 +43,29 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
return entity.getSubjectId() == 0;
}
/**
* Retrieves the internal system user which is permitted to execute almost
* every operation.
*
* @return The internal system user.
*/
public User retrieveSystemUser() {
throw new UnsupportedOperationException();
}
/**
* Retrieves the public user. The public user is used to represent the
* privileges of a user which is not logged in. The public user is a
* ordinary user account in the database with the screen name
* {@code public-user}.
*
* @return The public user or {@code null} if there is no account for the
* public user.
*/
public User retrievePublicUser() {
throw new UnsupportedOperationException();
}
public User findByScreenName(final String screenname) {
final TypedQuery<User> query = getEntityManager().createNamedQuery(
"findUserByScreenName", User.class);
@ -69,7 +92,7 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
if (result.isEmpty()) {
return null;
} else if(result.size() == 1) {
} else if (result.size() == 1) {
return result.get(0);
} else {
throw new MultipleMatchingUserException(String.format(
@ -79,5 +102,4 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
}
}
}

View File

@ -40,6 +40,7 @@ import org.libreccm.core.ResourceType;
*/
@Entity
@Table(name = "application_types")
@SuppressWarnings("PMD.LongVariable")
public class ApplicationType extends ResourceType implements Serializable {
private static final long serialVersionUID = -1175728067001112457L;

View File

@ -58,6 +58,9 @@ public class DatasetsTest extends DatasetsVerifier {
"/datasets/org/libreccm/core/PermissionRepositoryTest/after-save-new.json",
"/datasets/org/libreccm/core/PermissionRepositoryTest/after-delete.json",
"/datasets/org/libreccm/core/PermissionRepositoryTest/data.json",
"/datasets/org/libreccm/core/PrivilegeRepositoryTest/after-create.json",
"/datasets/org/libreccm/core/PrivilegeRepositoryTest/after-delete.json",
"/datasets/org/libreccm/core/PrivilegeRepositoryTest/data.json",
"/datasets/org/libreccm/core/RoleRepositoryTest/data.json",
"/datasets/org/libreccm/core/RoleRepositoryTest/after-delete.json",
"/datasets/org/libreccm/core/RoleRepositoryTest/after-save-changed.json",

View File

@ -141,8 +141,8 @@ public class PermissionRepositoryTest {
}
@Test
@UsingDataSet(
"datasets/org/libreccm/core/PermissionRepositoryTest/data.json")
@UsingDataSet("datasets/org/libreccm/core/PermissionRepositoryTest/"
+ "data.json")
@InSequence(10)
public void findPermissionsForSubject() {
final User jdoe = userRepository.findByScreenName("jdoe");
@ -441,4 +441,5 @@ public class PermissionRepositoryTest {
public void deleteNullPermission() {
permissionRepository.delete(null);
}
}

View File

@ -0,0 +1,199 @@
/*
* Copyright (C) 2015 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.core;
import static org.hamcrest.Matchers.*;
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.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 java.io.File;
import javax.inject.Inject;
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)
public class PrivilegeRepositoryTest {
@Inject
private transient PrivilegeRepository privilegeRepository;
public PrivilegeRepositoryTest() {
}
@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.core.UserRepositoryTest.war")
.addPackage(User.class.getPackage())
.addPackage(org.libreccm.web.Application.class.getPackage())
.addPackage(org.libreccm.categorization.Category.class.
getPackage())
.addPackage(org.libreccm.l10n.LocalizedString.class.getPackage()).
addPackage(org.libreccm.jpa.EntityManagerProducer.class
.getPackage())
.addPackage(org.libreccm.jpa.utils.MimeTypeConverter.class
.getPackage())
.addPackage(org.libreccm.testutils.EqualsVerifier.class.
getPackage())
.addPackage(org.libreccm.tests.categories.IntegrationTest.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/libreccm/core/PrivilegeRepositoryTest/"
+ "data.json")
@InSequence(10)
public void retrievePrivilege() {
final Privilege admin = privilegeRepository.retrievePrivilege("admin");
final Privilege read = privilegeRepository.retrievePrivilege("read");
final Privilege write = privilegeRepository.retrievePrivilege("write");
assertThat(admin, is(not(nullValue())));
assertThat(read, is(not(nullValue())));
assertThat(write, is(not(nullValue())));
assertThat(admin.getPrivilege(), is(equalTo("admin")));
assertThat(read.getPrivilege(), is(equalTo("read")));
assertThat(write.getPrivilege(), is(equalTo("write")));
}
@Test(expected = UnknownPrivilegeException.class)
@UsingDataSet("datasets/org/libreccm/core/PrivilegeRepositoryTest/"
+ "data.json")
@ShouldThrowException(UnknownPrivilegeException.class)
@InSequence(20)
public void retrieveNotExitingPrivilege() {
privilegeRepository.retrievePrivilege("publish");
}
@Test
@UsingDataSet("datasets/org/libreccm/core/PrivilegeRepositoryTest/"
+ "data.json")
@ShouldMatchDataSet(value = "datasets/org/libreccm/core/"
+ "PrivilegeRepositoryTest/after-create.json",
excludeColumns = {"privilege_id"})
@InSequence(30)
public void createNewPrivilege() {
privilegeRepository.createPrivilege("publish");
}
@Test
@UsingDataSet("datasets/org/libreccm/core/PrivilegeRepositoryTest/"
+ "data.json")
@ShouldMatchDataSet(value = "datasets/org/libreccm/core/"
+ "PrivilegeRepositoryTest/after-delete.json",
excludeColumns = {"privilege_id"})
@InSequence(40)
public void deletePrivilege() {
privilegeRepository.deletePrivilege("write");
}
@Test(expected = UnknownPrivilegeException.class)
@UsingDataSet("datasets/org/libreccm/core/PrivilegeRepositoryTest/"
+ "data.json")
@ShouldThrowException(UnknownPrivilegeException.class)
@InSequence(41)
public void deleteNullPrivilege() {
privilegeRepository.deletePrivilege(null);
}
@Test
@UsingDataSet("datasets/org/libreccm/core/PermissionRepositoryTest/"
+ "data.json")
@InSequence(50)
public void checkIsPermissionInUse() {
assertThat(privilegeRepository.isPrivilegeInUse("admin"), is(true));
assertThat(privilegeRepository.isPrivilegeInUse("write"), is(true));
assertThat(privilegeRepository.isPrivilegeInUse("read"), is(true));
assertThat(privilegeRepository.isPrivilegeInUse("used"), is(false));
}
@Test(expected = IllegalArgumentException.class)
@UsingDataSet("datasets/org/libreccm/core/PermissionRepositoryTest/"
+ "data.json")
@ShouldThrowException(IllegalArgumentException.class)
@InSequence(60)
public void deleteInUsePrivilege() {
privilegeRepository.deletePrivilege("admin");
}
}

View File

@ -103,6 +103,10 @@
{
"privilege_id": -30,
"privilege": "write"
},
{
"privilege_id": -40,
"privilege": "unused"
}
],
"ccm_objects":

View File

@ -103,6 +103,10 @@
{
"privilege_id": -30,
"privilege": "write"
},
{
"privilege_id": -40,
"privilege": "unused"
}
],
"ccm_objects":

View File

@ -103,6 +103,10 @@
{
"privilege_id": -30,
"privilege": "write"
},
{
"privilege_id": -40,
"privilege": "unused"
}
],
"ccm_objects":
@ -167,7 +171,7 @@
"object_id": -40
},
{
"permission_id": -50,
"permission_id": -60,
"granted_privilege_id": -30,
"grantee_id": -50,
"object_id": -40

View File

@ -103,6 +103,10 @@
{
"privilege_id": -30,
"privilege": "write"
},
{
"privilege_id": -40,
"privilege": "unused"
}
],
"ccm_objects":

View File

@ -0,0 +1,21 @@
{
"ccm_privileges":
[
{
"privilege_id": -10,
"privilege": "admin"
},
{
"privilege_id": -20,
"privilege": "read"
},
{
"privilege_id": -30,
"privilege": "write"
},
{
"privilege_id": -40,
"privilege": "publish"
}
]
}

View File

@ -0,0 +1,13 @@
{
"ccm_privileges":
[
{
"privilege_id": -10,
"privilege": "admin"
},
{
"privilege_id": -20,
"privilege": "read"
}
]
}

View File

@ -0,0 +1,17 @@
{
"ccm_privileges":
[
{
"privilege_id": -10,
"privilege": "admin"
},
{
"privilege_id": -20,
"privilege": "read"
},
{
"privilege_id": -30,
"privilege": "write"
}
]
}