CCM NG: Authorisation checks for several repository classes

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4158 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-06-15 18:36:55 +00:00
parent bce1dac628
commit 9f66872c80
10 changed files with 234 additions and 47 deletions

View File

@ -22,7 +22,9 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.Subject;
import org.libreccm.core.AbstractEntityRepository; import org.libreccm.core.AbstractEntityRepository;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.PermissionChecker; import org.libreccm.security.PermissionChecker;
import org.libreccm.security.RequiresPrivilege;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -161,15 +163,21 @@ public class CategoryRepository extends AbstractEntityRepository<Long, Category>
return current; return current;
} }
@Override @AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public void save(final Category category) { @Override
public void save(
@RequiresPrivilege("manage_categories") final Category category) {
super.save(category); super.save(category);
} }
@Override @AuthorizationRequired
@RequiresPrivilege("manage_categories")
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
@Override
public void delete(final Category category) { public void delete(final Category category) {
super.save(category); super.save(category);
} }
} }

View File

@ -85,16 +85,24 @@ public class GroupRepository extends AbstractEntityRepository<Long, Group> {
return query.getResultList(); return query.getResultList();
} }
public List<Group> findAllOrderedByGroupName() { public List<Group> findAllOrderedByGroupName() {
final TypedQuery<Group> query = getEntityManager().createNamedQuery( final TypedQuery<Group> query = getEntityManager().createNamedQuery(
"Group.findAllOrderedByGroupName", Group.class); "Group.findAllOrderedByGroupName", Group.class);
return query.getResultList(); return query.getResultList();
} }
@Override @AuthorizationRequired
@RequiresPrivilege("admin")
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
@Override
public void save(final Group group) {
super.save(group);
}
@AuthorizationRequired
@RequiresPrivilege("admin")
@Transactional(Transactional.TxType.REQUIRED)
@Override
public void delete(final Group entity) { public void delete(final Group entity) {
if (entity == null) { if (entity == null) {
throw new IllegalArgumentException("Can't delete null"); throw new IllegalArgumentException("Can't delete null");
@ -109,4 +117,5 @@ public class GroupRepository extends AbstractEntityRepository<Long, Group> {
getEntityManager().remove(delete); getEntityManager().remove(delete);
} }
} }

View File

@ -81,6 +81,16 @@ public class RoleRepository extends AbstractEntityRepository<Long, Role> {
return query.getResultList(); return query.getResultList();
} }
@AuthorizationRequired
@RequiresPrivilege("admin")
@Transactional(Transactional.TxType.REQUIRED)
@Override
public void save(final Role role) {
super.save(role);
}
@AuthorizationRequired
@RequiresPrivilege("admin")
@Override @Override
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public void delete(final Role role) { public void delete(final Role role) {

View File

@ -18,13 +18,17 @@
*/ */
package org.libreccm.web; package org.libreccm.web;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.libreccm.core.AbstractEntityRepository; import org.libreccm.core.AbstractEntityRepository;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege;
import java.util.List; import java.util.List;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.transaction.Transactional;
/** /**
* *
@ -81,4 +85,20 @@ public class ApplicationRepository
return query.getResultList(); return query.getResultList();
} }
@AuthorizationRequired
@RequiresPrivilege("admin")
@Transactional(Transactional.TxType.REQUIRED)
@Override
public void save(final CcmApplication application) {
super.save(application);
}
@AuthorizationRequired
@RequiresPrivilege("admin")
@Transactional(Transactional.TxType.REQUIRED)
@Override
public void delete(final CcmApplication application) {
super.delete(application);
}
} }

View File

@ -18,6 +18,10 @@
*/ */
package org.libreccm.categorization; package org.libreccm.categorization;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import java.io.File; import java.io.File;
import javax.inject.Inject; import javax.inject.Inject;
@ -34,8 +38,8 @@ import org.jboss.arquillian.persistence.ShouldMatchDataSet;
import org.jboss.arquillian.persistence.UsingDataSet; import org.jboss.arquillian.persistence.UsingDataSet;
import org.jboss.arquillian.transaction.api.annotation.TransactionMode; import org.jboss.arquillian.transaction.api.annotation.TransactionMode;
import org.jboss.arquillian.transaction.api.annotation.Transactional; import org.jboss.arquillian.transaction.api.annotation.Transactional;
import org.jboss.sasl.util.UsernamePasswordHashUtil;
import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive; import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.Maven; import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage; import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage;
@ -45,8 +49,11 @@ import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.libreccm.security.Shiro;
import org.libreccm.tests.categories.IntegrationTest; import org.libreccm.tests.categories.IntegrationTest;
import javax.ws.rs.NotAuthorizedException;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -67,6 +74,12 @@ public class CategoryRepositoryTest {
@Inject @Inject
private DomainRepository domainRepo; private DomainRepository domainRepo;
@Inject
private Shiro shiro;
@Inject
private Subject subject;
@PersistenceContext(name = "LibreCCM") @PersistenceContext(name = "LibreCCM")
private EntityManager entityManager; private EntityManager entityManager;
@ -117,16 +130,21 @@ public class CategoryRepositoryTest {
.getPackage()) .getPackage())
.addPackage(org.libreccm.l10n.LocalizedString.class.getPackage()) .addPackage(org.libreccm.l10n.LocalizedString.class.getPackage())
.addPackage(org.libreccm.security.Permission.class.getPackage()) .addPackage(org.libreccm.security.Permission.class.getPackage())
.addPackage(org.libreccm.testutils.EqualsVerifier.class.getPackage()) .addPackage(org.libreccm.testutils.EqualsVerifier.class
.getPackage())
.addPackage(org.libreccm.tests.categories.IntegrationTest.class .addPackage(org.libreccm.tests.categories.IntegrationTest.class
.getPackage()) .getPackage())
.addPackage(org.libreccm.web.CcmApplication.class.getPackage()) .addPackage(org.libreccm.web.CcmApplication.class.getPackage())
.addPackage(org.libreccm.workflow.Workflow.class.getPackage()) .addPackage(org.libreccm.workflow.Workflow.class.getPackage())
.addPackage(org.libreccm.cdi.utils.CdiUtil.class.getPackage())
.addClass(com.arsdigita.kernel.KernelConfig.class)
.addClass(com.arsdigita.kernel.security.SecurityConfig.class)
.addAsLibraries(libs) .addAsLibraries(libs)
.addAsResource("configs/shiro.ini", "shiro.ini")
.addAsResource("test-persistence.xml", .addAsResource("test-persistence.xml",
"META-INF/persistence.xml") "META-INF/persistence.xml")
.addAsWebInfResource("test-web.xml", "WEB-INF/web.xml") .addAsWebInfResource("test-web.xml", "web.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "WEB-INF/beans.xml"); .addAsWebInfResource("META-INF/beans.xml", "beans.xml");
} }
@Test @Test
@ -250,6 +268,44 @@ public class CategoryRepositoryTest {
category.setName("new-category"); category.setName("new-category");
category.setUniqueId("new0001"); category.setUniqueId("new0001");
shiro.getSystemUser().execute(() -> categoryRepo.save(category));
}
@Test
@UsingDataSet(
"datasets/org/libreccm/categorization/CategoryRepositoryTest/data.yml")
@ShouldMatchDataSet(
value = "datasets/org/libreccm/categorization/CategoryRepositoryTest/"
+ "after-save-new-category.yml",
excludeColumns = {"object_id", "uuid"})
@InSequence(3200)
public void saveNewCategoryGlobalAuth() {
final UsernamePasswordToken token = new UsernamePasswordToken(
"john.doe@example.org", "foo123");
token.setRememberMe(true);
subject.login(token);
final Category category = new Category();
category.setDisplayName("new-category");
category.setName("new-category");
category.setUniqueId("new0001");
categoryRepo.save(category);
subject.logout();
}
@Test(expected = UnauthorizedException.class)
@UsingDataSet(
"datasets/org/libreccm/categorization/CategoryRepositoryTest/data.yml")
@ShouldThrowException(UnauthorizedException.class)
@InSequence(3400)
public void saveNewCategoryNotAuthorized() {
final Category category = new Category();
category.setDisplayName("new-category");
category.setName("new-category");
category.setUniqueId("new0001");
categoryRepo.save(category); categoryRepo.save(category);
} }

View File

@ -126,14 +126,16 @@ public class GroupRepositoryTest {
.getPackage()) .getPackage())
.addPackage(org.libreccm.jpa.utils.MimeTypeConverter.class .addPackage(org.libreccm.jpa.utils.MimeTypeConverter.class
.getPackage()) .getPackage())
.addPackage(org.libreccm.testutils.EqualsVerifier.class.getPackage()) .addPackage(org.libreccm.testutils.EqualsVerifier.class
.getPackage())
.addPackage(org.libreccm.tests.categories.IntegrationTest.class .addPackage(org.libreccm.tests.categories.IntegrationTest.class
.getPackage()) .getPackage())
.addAsLibraries(libs) .addAsLibraries(libs)
.addAsResource("configs/shiro.ini", "shiro.ini")
.addAsResource("test-persistence.xml", .addAsResource("test-persistence.xml",
"META-INF/persistence.xml") "META-INF/persistence.xml")
.addAsWebInfResource("test-web.xml", "WEB-INF/web.xml") .addAsWebInfResource("test-web.xml", "web.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "WEB-INF/beans.xml"); .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
} }
@Test @Test

View File

@ -18,6 +18,7 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import org.apache.shiro.subject.Subject;
import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.ShouldThrowException; import org.jboss.arquillian.container.test.api.ShouldThrowException;
import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.junit.Arquillian;
@ -29,7 +30,6 @@ import org.jboss.arquillian.persistence.UsingDataSet;
import org.jboss.arquillian.transaction.api.annotation.TransactionMode; import org.jboss.arquillian.transaction.api.annotation.TransactionMode;
import org.jboss.arquillian.transaction.api.annotation.Transactional; import org.jboss.arquillian.transaction.api.annotation.Transactional;
import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive; import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.Maven; import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage; import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage;
@ -72,6 +72,9 @@ public class PartyRepositoryTest {
@Inject @Inject
private PartyRepository partyRepository; private PartyRepository partyRepository;
@Inject
private Shiro shiro;
@PersistenceContext @PersistenceContext
private EntityManager entityManager; private EntityManager entityManager;
@ -115,23 +118,30 @@ public class PartyRepositoryTest {
.addPackage(org.libreccm.core.CcmObject.class.getPackage()) .addPackage(org.libreccm.core.CcmObject.class.getPackage())
.addPackage(org.libreccm.categorization.Categorization.class .addPackage(org.libreccm.categorization.Categorization.class
.getPackage()) .getPackage())
.addPackage(org.libreccm.configuration.ConfigurationManager.class .addPackage(
org.libreccm.configuration.ConfigurationManager.class
.getPackage())
.addPackage(org.libreccm.l10n.LocalizedString.class
.getPackage()) .getPackage())
.addPackage(org.libreccm.l10n.LocalizedString.class.getPackage())
.addPackage(org.libreccm.web.CcmApplication.class.getPackage()) .addPackage(org.libreccm.web.CcmApplication.class.getPackage())
.addPackage(org.libreccm.workflow.Workflow.class.getPackage()) .addPackage(org.libreccm.workflow.Workflow.class.getPackage())
.addPackage(org.libreccm.jpa.EntityManagerProducer.class .addPackage(org.libreccm.jpa.EntityManagerProducer.class
.getPackage()) .getPackage())
.addPackage(org.libreccm.jpa.utils.MimeTypeConverter.class .addPackage(org.libreccm.jpa.utils.MimeTypeConverter.class
.getPackage()) .getPackage())
.addPackage(org.libreccm.testutils.EqualsVerifier.class.getPackage()) .addPackage(org.libreccm.testutils.EqualsVerifier.class.
getPackage())
.addPackage(org.libreccm.tests.categories.IntegrationTest.class .addPackage(org.libreccm.tests.categories.IntegrationTest.class
.getPackage()) .getPackage())
.addClass(com.arsdigita.kernel.security.SecurityConfig.class)
.addClass(com.arsdigita.kernel.KernelConfig.class)
.addPackage(org.libreccm.cdi.utils.CdiUtil.class.getPackage())
.addAsLibraries(libs) .addAsLibraries(libs)
.addAsResource("configs/shiro.ini", "shiro.ini")
.addAsResource("test-persistence.xml", .addAsResource("test-persistence.xml",
"META-INF/persistence.xml") "META-INF/persistence.xml")
.addAsWebInfResource("test-web.xml", "WEB-INF/web.xml") .addAsWebInfResource("test-web.xml", "web.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "WEB-INF/beans.xml"); .addAsWebInfResource("META-INF/beans.xml", "beans.xml");
} }
@Test @Test
@ -218,12 +228,13 @@ public class PartyRepositoryTest {
"$shiro1$SHA-512$500000$Y7CnccN1h25sR7KCElMOXg==$CVLWBhetodaEzzhDfGjRcCFZtSW02xOnjH7xhBx0lbxO66grKIt6LWmXoUhLEydce1JZ7cbzNLYOxIwwTeqi5Q=="); "$shiro1$SHA-512$500000$Y7CnccN1h25sR7KCElMOXg==$CVLWBhetodaEzzhDfGjRcCFZtSW02xOnjH7xhBx0lbxO66grKIt6LWmXoUhLEydce1JZ7cbzNLYOxIwwTeqi5Q==");
mmuster.setPasswordResetRequired(false); mmuster.setPasswordResetRequired(false);
partyRepository.save(mmuster); final Subject system = shiro.getSystemUser();
system.execute(() -> partyRepository.save(mmuster));
final Group users = new Group(); final Group users = new Group();
users.setName("users"); users.setName("users");
partyRepository.save(users); system.execute(() -> partyRepository.save(users));
} }
@Test @Test
@ -240,15 +251,17 @@ public class PartyRepositoryTest {
user.setName("johndoe"); user.setName("johndoe");
group.setName("managers"); group.setName("managers");
shiro.getSystemUser().execute(() -> {
partyRepository.save(user); partyRepository.save(user);
partyRepository.save(group); partyRepository.save(group);
});
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
@ShouldThrowException(IllegalArgumentException.class) @ShouldThrowException(IllegalArgumentException.class)
@InSequence(500) @InSequence(500)
public void saveNullValue() { public void saveNullValue() {
partyRepository.save(null); shiro.getSystemUser().execute(() -> partyRepository.save(null));
} }
@Test @Test
@ -260,14 +273,14 @@ public class PartyRepositoryTest {
public void deleteParty() { public void deleteParty() {
final Party user = partyRepository.findById(-10L); final Party user = partyRepository.findById(-10L);
partyRepository.delete(user); shiro.getSystemUser().execute(() -> partyRepository.delete(user));
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
@ShouldThrowException(IllegalArgumentException.class) @ShouldThrowException(IllegalArgumentException.class)
@InSequence(700) @InSequence(700)
public void deleteNullValue() { public void deleteNullValue() {
partyRepository.delete(null); shiro.getSystemUser().execute(() -> partyRepository.delete(null));
} }
} }

View File

@ -53,6 +53,8 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
* Tests for the {@link RoleRepository}. Note. We are not enabling the
* {@link AuthorizationInterceptor} for this test.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@ -126,10 +128,11 @@ public class RoleRepositoryTest {
.addPackage(org.libreccm.tests.categories.IntegrationTest.class .addPackage(org.libreccm.tests.categories.IntegrationTest.class
.getPackage()) .getPackage())
.addAsLibraries(libs) .addAsLibraries(libs)
.addAsResource("configs/shiro.ini", "shiro.ini")
.addAsResource("test-persistence.xml", .addAsResource("test-persistence.xml",
"META-INF/persistence.xml") "META-INF/persistence.xml")
.addAsWebInfResource("test-web.xml", "WEB-INF/web.xml") .addAsWebInfResource("test-web.xml", "web.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "WEB-INF/beans.xml"); .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
} }
@Test @Test

View File

@ -75,6 +75,9 @@ public class UserRepositoryTest {
@Inject @Inject
private UserRepository userRepository; private UserRepository userRepository;
@Inject
private Shiro shiro;
@PersistenceContext @PersistenceContext
private EntityManager entityManager; private EntityManager entityManager;
@ -127,14 +130,19 @@ public class UserRepositoryTest {
.getPackage()) .getPackage())
.addPackage(org.libreccm.jpa.utils.MimeTypeConverter.class .addPackage(org.libreccm.jpa.utils.MimeTypeConverter.class
.getPackage()) .getPackage())
.addPackage(org.libreccm.testutils.EqualsVerifier.class.getPackage()) .addPackage(org.libreccm.testutils.EqualsVerifier.class
.getPackage())
.addPackage(org.libreccm.tests.categories.IntegrationTest.class .addPackage(org.libreccm.tests.categories.IntegrationTest.class
.getPackage()) .getPackage())
.addClass(com.arsdigita.kernel.security.SecurityConfig.class)
.addClass(com.arsdigita.kernel.KernelConfig.class)
.addPackage(org.libreccm.cdi.utils.CdiUtil.class.getPackage())
.addAsLibraries(libs) .addAsLibraries(libs)
.addAsResource("configs/shiro.ini", "shiro.ini")
.addAsResource("test-persistence.xml", .addAsResource("test-persistence.xml",
"META-INF/persistence.xml") "META-INF/persistence.xml")
.addAsWebInfResource("test-web.xml", "WEB-INF/web.xml") .addAsWebInfResource("test-web.xml", "web.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "WEB-INF/beans.xml"); .addAsWebInfResource("META-INF/beans.xml", "beans.xml");
} }
@Test @Test
@ -264,7 +272,7 @@ public class UserRepositoryTest {
"$shiro1$SHA-512$500000$24lA090z7GKYr4VFlZ6t4A==$/heoTHPA5huT1UfJ8Q+waXEG6AjUKhFYLFrj7KW/l0/z9O+QkiZTtfPfbcPblgjcEvrROMEIoQY4Z65S7rFLQg=="); "$shiro1$SHA-512$500000$24lA090z7GKYr4VFlZ6t4A==$/heoTHPA5huT1UfJ8Q+waXEG6AjUKhFYLFrj7KW/l0/z9O+QkiZTtfPfbcPblgjcEvrROMEIoQY4Z65S7rFLQg==");
user.setPasswordResetRequired(false); user.setPasswordResetRequired(false);
userRepository.save(user); shiro.getSystemUser().execute(() -> userRepository.save(user));
} }
@Test @Test
@ -286,14 +294,14 @@ public class UserRepositoryTest {
emailAddress.setVerified(true); emailAddress.setVerified(true);
user.setPrimaryEmailAddress(emailAddress); user.setPrimaryEmailAddress(emailAddress);
userRepository.save(user); shiro.getSystemUser().execute(() -> userRepository.save(user));
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
@ShouldThrowException(IllegalArgumentException.class) @ShouldThrowException(IllegalArgumentException.class)
@InSequence(700) @InSequence(700)
public void saveNullValue() { public void saveNullValue() {
userRepository.save(null); shiro.getSystemUser().execute(() -> userRepository.save(null));
} }
@Test @Test
@ -305,14 +313,14 @@ public class UserRepositoryTest {
public void deleteUser() { public void deleteUser() {
final User user = userRepository.findByName("mmuster"); final User user = userRepository.findByName("mmuster");
userRepository.delete(user); shiro.getSystemUser().execute(() -> userRepository.delete(user));
} }
@Test(expected = IllegalArgumentException.class) @Test(expected = IllegalArgumentException.class)
@ShouldThrowException(IllegalArgumentException.class) @ShouldThrowException(IllegalArgumentException.class)
@InSequence(900) @InSequence(900)
public void deleteNullValue() { public void deleteNullValue() {
userRepository.delete(null); shiro.getSystemUser().execute(() -> userRepository.delete(null));
} }
} }

View File

@ -44,3 +44,61 @@ ccm_core.category_domains:
uri: http://libreccm.org/test uri: http://libreccm.org/test
version: 1.0 version: 1.0
ccm_core.parties:
- party_id: -100
name: public-user
- party_id: -200
name: jdoe
- party_id: -300
name: mmuster
ccm_core.users:
- party_id: -100
given_name: public
family_name: user
email_address: public-user@localhost
banned: false
bouncing: false
verified: true
password_reset_required: false
- party_id: -200
given_name: John
family_name: Doe
email_address: john.doe@example.org
password: $shiro1$SHA-512$500000$Y7CnccN1h25sR7KCElMOXg==$CVLWBhetodaEzzhDfGjRcCFZtSW02xOnjH7xhBx0lbxO66grKIt6LWmXoUhLEydce1JZ7cbzNLYOxIwwTeqi5Q==
banned: false
bouncing: false
verified: true
password_reset_required: false
- party_id: -300
given_name: Max
family_name: Mustermann
email_address: max.mustermann@example.org
password: $shiro1$SHA-512$500000$Y7CnccN1h25sR7KCElMOXg==$CVLWBhetodaEzzhDfGjRcCFZtSW02xOnjH7xhBx0lbxO66grKIt6LWmXoUhLEydce1JZ7cbzNLYOxIwwTeqi5Q==
banned: false
bouncing: false
verified: true
password_reset_required: false
ccm_core.ccm_roles:
- role_id: -500
name: category_manager
- role_id: -510
name: category_manager_domain_test
ccm_core.role_memberships:
- membership_id: -600
role_id: -500
member_id: -200
- membership_id: -610
role_id: -510
member_id: -300
ccm_core.permissions:
- permission_id: -700
granted_privilege: manage_categories
grantee_id: -500
- permission_id: -710
granted_privilege: manage_categories
grantee_id: -510
object_id: -1000