From 76a1e0f10bbd326d6114c1ebe9bd8bd766c3887e Mon Sep 17 00:00:00 2001 From: jensp Date: Tue, 2 May 2017 09:02:36 +0000 Subject: [PATCH] CCM NG/ccm-cms: Extended test for developing query which takes permissions into acccount when retrieving ContentItems from the database. git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4699 8810af33-2d31-482b-a856-94f89814c4df --- .../ContentItemPermissionTest.java | 75 ++++++++++++++++--- .../java/org/libreccm/security/Shiro.java | 44 ++++++++--- 2 files changed, 101 insertions(+), 18 deletions(-) diff --git a/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemPermissionTest.java b/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemPermissionTest.java index 0055ea8f2..99986f3f3 100644 --- a/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemPermissionTest.java +++ b/ccm-cms/src/test/java/org/librecms/contentsection/ContentItemPermissionTest.java @@ -47,8 +47,10 @@ import org.libreccm.security.User; import org.libreccm.tests.categories.IntegrationTest; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.concurrent.Callable; import java.util.stream.Collectors; import javax.inject.Inject; @@ -71,11 +73,12 @@ import static org.junit.Assert.*; phase = TestExecutionPhase.BEFORE) public class ContentItemPermissionTest { - private static final String QUERY = "SELECT i FROM ContentItem i " + private static final String QUERY = "SELECT DISTINCT i FROM ContentItem i " + "JOIN i.permissions p " - + "WHERE p.grantee IN :roles " - + "AND p.grantedPrivilege = 'view_draft_items' " - + "ORDER BY i.displayName"; + + "WHERE (p.grantee IN :roles " + + "AND p.grantedPrivilege = 'view_draft_items')" + + "OR true = :isSystemUser " + + "ORDER BY i.displayName"; @Inject private EntityManager entityManager; @@ -106,9 +109,9 @@ public class ContentItemPermissionTest { public static WebArchive createDeployment() { return ShrinkWrap .create(WebArchive.class, - "LibreCCM-org.librecms.contentsection.ContentItemPermissionTest.war") - //Classes imported by this class - .addClass(Role.class) + "LibreCCM-org.librecms.contentsection.ContentItemPermissionTest.war") //Classes imported by this class + . + addClass(Role.class) .addClass(Shiro.class) .addClass(User.class) .addClass(ContentItem.class) @@ -232,7 +235,7 @@ public class ContentItemPermissionTest { .addClass(org.libreccm.core.CcmObjectRepository.class) //Required by org.libreccm.core.CcmObjectRepository .addClass(org.libreccm.core.CoreConstants.class) - //Dependencies from other modules and resources + //Dependencies from other modules and resources .addAsLibraries(getCcmCoreDependencies()) .addAsResource("test-persistence.xml", "META-INF/persistence.xml") @@ -270,12 +273,13 @@ public class ContentItemPermissionTest { .map(membership -> membership.getRole()) .collect(Collectors.toList()); } else { - roles = new ArrayList<>(); + roles = Collections.emptyList(); } final TypedQuery query = entityManager.createQuery( QUERY, ContentItem.class); query.setParameter("roles", roles); + query.setParameter("isSystemUser", shiro.isSystemUser()); final List result = query.getResultList(); assertThat(result.isEmpty(), is(true)); @@ -286,6 +290,7 @@ public class ContentItemPermissionTest { @UsingDataSet("datasets/org/librecms/contentsection/" + "ContentItemPermissionTest/data.xml") public void accessByUser1() { + final UsernamePasswordToken token = new UsernamePasswordToken( "user1@example.org", "foo123"); token.setRememberMe(true); @@ -299,6 +304,7 @@ public class ContentItemPermissionTest { final TypedQuery query = entityManager.createQuery( QUERY, ContentItem.class); query.setParameter("roles", roles); + query.setParameter("isSystemUser", shiro.isSystemUser()); final List result = query.getResultList(); assertThat(result.size(), is(2)); @@ -311,6 +317,7 @@ public class ContentItemPermissionTest { @UsingDataSet("datasets/org/librecms/contentsection/" + "ContentItemPermissionTest/data.xml") public void accessByUser2() { + final UsernamePasswordToken token = new UsernamePasswordToken( "user2@example.org", "foo123"); token.setRememberMe(true); @@ -324,6 +331,7 @@ public class ContentItemPermissionTest { final TypedQuery query = entityManager.createQuery( QUERY, ContentItem.class); query.setParameter("roles", roles); + query.setParameter("isSystemUser", shiro.isSystemUser()); final List result = query.getResultList(); assertThat(result.size(), is(1)); @@ -335,6 +343,7 @@ public class ContentItemPermissionTest { @UsingDataSet("datasets/org/librecms/contentsection/" + "ContentItemPermissionTest/data.xml") public void accessByUser3() { + final UsernamePasswordToken token = new UsernamePasswordToken( "user3@example.org", "foo123"); token.setRememberMe(true); @@ -348,6 +357,7 @@ public class ContentItemPermissionTest { final TypedQuery query = entityManager.createQuery( QUERY, ContentItem.class); query.setParameter("roles", roles); + query.setParameter("isSystemUser", shiro.isSystemUser()); final List result = query.getResultList(); assertThat(result.size(), is(3)); @@ -356,4 +366,51 @@ public class ContentItemPermissionTest { assertThat(result.get(2).getDisplayName(), is(equalTo("article3"))); } + @Test + @InSequence(500) + @UsingDataSet("datasets/org/librecms/contentsection/" + + "ContentItemPermissionTest/data.xml") + public void accessBySystemUser() { + + final UsernamePasswordToken token = new UsernamePasswordToken( + "user3@example.org", "foo123"); + token.setRememberMe(true); + subject.login(token); + + final List result = shiro + .getSystemUser() + .execute(new ItemRetriever()); + + assertThat(result.size(), is(4)); + assertThat(result.get(0).getDisplayName(), is(equalTo("article1"))); + assertThat(result.get(1).getDisplayName(), is(equalTo("article2"))); + assertThat(result.get(2).getDisplayName(), is(equalTo("article3"))); + assertThat(result.get(3).getDisplayName(), is(equalTo("news1"))); + } + + private class ItemRetriever implements Callable> { + + @Override + public List call() throws Exception { + + final Optional user = shiro.getUser(); + final List roles; + if (user.isPresent()) { + roles = shiro.getUser().get().getRoleMemberships() + .stream() + .map(membership -> membership.getRole()) + .collect(Collectors.toList()); + } else { + roles = Collections.emptyList(); + } + + final TypedQuery query = entityManager.createQuery( + QUERY, ContentItem.class); + query.setParameter("roles", roles); + query.setParameter("isSystemUser", shiro.isSystemUser()); + return query.getResultList(); + } + + } + } diff --git a/ccm-core/src/main/java/org/libreccm/security/Shiro.java b/ccm-core/src/main/java/org/libreccm/security/Shiro.java index a751ecf4a..ba30d5451 100644 --- a/ccm-core/src/main/java/org/libreccm/security/Shiro.java +++ b/ccm-core/src/main/java/org/libreccm/security/Shiro.java @@ -134,13 +134,39 @@ public class Shiro { } } + public boolean isPublicUser() { + final Subject subject = getSubject(); + final Object principal = subject.getPrincipal(); + + if (KernelConfig.getConfig().emailIsPrimaryIdentifier()) { + return PUBLIC_USER_PRINCIPAL_EMAIL.equals(principal); + } else { + return PUBLIC_USER_PRINCIPAL_SCREEN_NAME.equals(principal); + } + } + /** * A virtual user for internal processes which has all permissions. * * @return */ public Subject getSystemUser() { - return buildInternalSubject(SYSTEM_USER_PRINCIPAL_SCREEN_NAME); + if (KernelConfig.getConfig().emailIsPrimaryIdentifier()) { + return buildInternalSubject(SYSTEM_USER_PRINCIPAL_EMAIL); + } else { + return buildInternalSubject(SYSTEM_USER_PRINCIPAL_SCREEN_NAME); + } + } + + public boolean isSystemUser() { + final Subject subject = getSubject(); + final Object principal = subject.getPrincipal(); + + if (KernelConfig.getConfig().emailIsPrimaryIdentifier()) { + return SYSTEM_USER_PRINCIPAL_EMAIL.equals(principal); + } else { + return SYSTEM_USER_PRINCIPAL_SCREEN_NAME.equals(principal); + } } /** @@ -152,27 +178,27 @@ public class Shiro { * representation in the database the returned {@link Optional} is empty. * * @see #getSubject() - * @see #getSystemUser() - * @see #getPublicUser() + * @see #getSystemUser() + * @see #getPublicUser() */ public Optional getUser() { final KernelConfig kernelConfig = KernelConfig.getConfig(); if (kernelConfig.emailIsPrimaryIdentifier()) { return userRepository.findByEmailAddress((String) getSubject(). - getPrincipal()); + getPrincipal()); } else { return userRepository.findByName((String) getSubject(). - getPrincipal()); + getPrincipal()); } } private Subject buildInternalSubject(final String userName) { final PrincipalCollection principals = new SimplePrincipalCollection( - userName, "CcmShiroRealm"); + userName, "CcmShiroRealm"); final Subject internalUser = new Subject.Builder() - .principals(principals) - .authenticated(true) - .buildSubject(); + .principals(principals) + .authenticated(true) + .buildSubject(); return internalUser; }