- Removed EntityGraphs. They did not work as intended.
- Moved operations on entities in CcmShiroRealm to separate class. The CcmShiroRealmController wraps these operations into a transaction to avoid LazyInititalizationExceptions.


git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4548 8810af33-2d31-482b-a856-94f89814c4df

Former-commit-id: e1b612a2fb
pull/2/head
jensp 2017-02-01 20:34:43 +00:00
parent f006894cbb
commit 75e8b10e6c
18 changed files with 209 additions and 276 deletions

View File

@ -54,11 +54,11 @@ public class ItemSelectionModel extends CcmObjectSelectionModel<ContentItem> {
private Long typeId; private Long typeId;
public ItemSelectionModel(final LongParameter parameter) { public ItemSelectionModel(final LongParameter parameter) {
super(parameter); super(ContentItem.class.getName(), parameter);
} }
public ItemSelectionModel(final String parameterName) { public ItemSelectionModel(final String parameterName) {
super(parameterName); super(ContentItem.class.getName(), parameterName);
} }
/** /**

View File

@ -24,6 +24,7 @@ import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.page.PageTransformer; import com.arsdigita.bebop.page.PageTransformer;
import com.arsdigita.cms.CMS;
import com.arsdigita.dispatcher.RequestContext; import com.arsdigita.dispatcher.RequestContext;
import com.arsdigita.templating.PresentationManager; import com.arsdigita.templating.PresentationManager;
import com.arsdigita.web.Web; import com.arsdigita.web.Web;
@ -281,6 +282,10 @@ public class CMSPage extends Page implements ResourceHandler {
section = (ContentSection) app; section = (ContentSection) app;
} }
if (section != null) {
CMS.getContext().setContentSection(section);
}
final String itemId = request.getParameter("item_id"); final String itemId = request.getParameter("item_id");
if (itemId != null) { if (itemId != null) {

View File

@ -243,6 +243,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
} }
return m_browsePane; return m_browsePane;
} }
/** /**
* Creates, and then caches, the search pane. Overriding this method to * Creates, and then caches, the search pane. Overriding this method to
* return null will prevent this tab from appearing. * return null will prevent this tab from appearing.
@ -386,16 +387,16 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
final TabbedPane pane = new TabbedPane(); final TabbedPane pane = new TabbedPane();
//tab(pane, "cms.ui.folders", getFolderAdminPane()); //tab(pane, "cms.ui.folders", getFolderAdminPane());
// ToDo NG tab(pane, "cms.ui.browse", getBrowsePane()); tab(pane, "cms.ui.browse", getBrowsePane());
// ToDo NG tab(pane, "cms.ui.search", getSearchPane()); tab(pane, "cms.ui.search", getSearchPane());
// ToDo NG tab(pane, "cms.ui.images", getImagesPane()); // ToDo NG replace with media tab tab(pane, "cms.ui.images", getImagesPane());
// ToDo NG tab(pane, "cms.ui.roles", getRoleAdminPane()); tab(pane, "cms.ui.roles", getRoleAdminPane());
tab(pane, "cms.ui.workflows", getWorkflowAdminPane()); tab(pane, "cms.ui.workflows", getWorkflowAdminPane());
tab(pane, "cms.ui.lifecycles", getLifecycleAdminPane()); tab(pane, "cms.ui.lifecycles", getLifecycleAdminPane());
// ToDo NG tab(pane, "cms.ui.categories", getCategoryAdminPane()); // ToDo NG tab(pane, "cms.ui.categories", getCategoryAdminPane());
tab(pane, "cms.ui.content_types", getContentTypeAdminPane()); tab(pane, "cms.ui.content_types", getContentTypeAdminPane());
tab(pane, "cms.ui.cse", getCSEPane()); tab(pane, "cms.ui.cse", getCSEPane());
// ToDo NG tab(pane, "cms.ui.reports", getReportPane()); tab(pane, "cms.ui.reports", getReportPane());
return pane; return pane;
} }

View File

@ -118,9 +118,9 @@ public class ItemQueryComponent extends BaseQueryComponent {
// CreationUserFilterType.KEY)); // CreationUserFilterType.KEY));
// add(new PartyFilterWidget(new LastModifiedUserFilterType(), // add(new PartyFilterWidget(new LastModifiedUserFilterType(),
// LastModifiedUserFilterType.KEY)); // LastModifiedUserFilterType.KEY));
Submit submit = new Submit(context + "_search", // Submit submit = new Submit(context + "_search",
ContentSectionPage.globalize("cms.ui.search")); // ContentSectionPage.globalize("cms.ui.search"));
add(submit); // add(submit);
} }
// private class LaunchDateFilterWidget extends DateRangeFilterWidget { // private class LaunchDateFilterWidget extends DateRangeFilterWidget {

View File

@ -42,11 +42,11 @@ public class CcmObjectSelectionModel<T extends CcmObject>
private final SingleSelectionModel<Long> model; private final SingleSelectionModel<Long> model;
public CcmObjectSelectionModel(final LongParameter parameter) { public CcmObjectSelectionModel(final LongParameter parameter) {
this("", parameter); this(CcmObject.class.getName(), parameter);
} }
public CcmObjectSelectionModel(final String parameterName) { public CcmObjectSelectionModel(final String parameterName) {
this("", new LongParameter(parameterName)); this(CcmObject.class.getName(), new LongParameter(parameterName));
} }
// public CcmObjectSelectionModel(final SingleSelectionModel<T> model ) { // public CcmObjectSelectionModel(final SingleSelectionModel<T> model ) {
@ -65,7 +65,7 @@ public class CcmObjectSelectionModel<T extends CcmObject>
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
model = new ParameterSingleSelectionModel(new LongParameter( model = new ParameterSingleSelectionModel<Long>(new LongParameter(
parameterName)); parameterName));
} }

View File

@ -25,7 +25,6 @@ import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotBlank;
import org.libreccm.core.CcmObject; import org.libreccm.core.CcmObject;
import org.libreccm.core.DefaultEntityGraph;
import org.libreccm.l10n.LocalizedString; import org.libreccm.l10n.LocalizedString;
import org.libreccm.portation.Portable; import org.libreccm.portation.Portable;
import org.libreccm.security.RecursivePermissions; import org.libreccm.security.RecursivePermissions;
@ -35,7 +34,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import javax.persistence.AssociationOverride; import javax.persistence.AssociationOverride;
import javax.persistence.Column; import javax.persistence.Column;
@ -101,7 +99,6 @@ import javax.xml.bind.annotation.XmlRootElement;
// } // }
) )
}) })
@DefaultEntityGraph("Category.withSubCategoriesAndObjects")
@XmlRootElement(name = "category", namespace = CAT_XML_NS) @XmlRootElement(name = "category", namespace = CAT_XML_NS)
public class Category extends CcmObject implements Serializable, Portable { public class Category extends CcmObject implements Serializable, Portable {

View File

@ -24,7 +24,6 @@ import static org.libreccm.core.CoreConstants.*;
import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.URL; import org.hibernate.validator.constraints.URL;
import org.libreccm.core.CcmObject; import org.libreccm.core.CcmObject;
import org.libreccm.core.DefaultEntityGraph;
import org.libreccm.l10n.LocalizedString; import org.libreccm.l10n.LocalizedString;
import org.libreccm.security.RecursivePermissions; import org.libreccm.security.RecursivePermissions;
import org.libreccm.web.CcmApplication; import org.libreccm.web.CcmApplication;
@ -110,7 +109,6 @@ import javax.xml.bind.annotation.XmlRootElement;
} }
) )
}) })
@DefaultEntityGraph("Domain.allCategories")
@XmlRootElement(name = "domain", namespace = CAT_XML_NS) @XmlRootElement(name = "domain", namespace = CAT_XML_NS)
public class Domain extends CcmObject implements Serializable { public class Domain extends CcmObject implements Serializable {

View File

@ -19,7 +19,6 @@
package org.libreccm.categorization; package org.libreccm.categorization;
import org.libreccm.core.AbstractEntityRepository; import org.libreccm.core.AbstractEntityRepository;
import org.libreccm.core.DefaultEntityGraph;
import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege; import org.libreccm.security.RequiresPrivilege;
@ -64,31 +63,8 @@ public class DomainRepository extends AbstractEntityRepository<Long, Domain> {
@Override @Override
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public List<Domain> findAll() { public List<Domain> findAll() {
if (getEntityClass().isAnnotationPresent(DefaultEntityGraph.class)) {
return findAll(getEntityClass().getAnnotation(
DefaultEntityGraph.class).value());
} else {
final TypedQuery<Domain> query = getEntityManager()
.createNamedQuery("Domain.findAll", Domain.class);
return query.getResultList();
}
}
@Override
@Transactional(Transactional.TxType.REQUIRED)
public List<Domain> findAll(final String entityGraphName) {
@SuppressWarnings("unchecked")
final EntityGraph<Domain> entityGraph = (EntityGraph<Domain>) entityManager.
getEntityGraph(entityGraphName);
return findAll(entityGraph);
}
@Override
@Transactional(Transactional.TxType.REQUIRED)
public List<Domain> findAll(final EntityGraph<Domain> entityGraph) {
final TypedQuery<Domain> query = getEntityManager() final TypedQuery<Domain> query = getEntityManager()
.createNamedQuery("Domain.findAll", Domain.class); .createNamedQuery("Domain.findAll", Domain.class);
query.setHint(FETCH_GRAPH_HINT_KEY, entityGraph);
return query.getResultList(); return query.getResultList();
} }
@ -150,7 +126,7 @@ public class DomainRepository extends AbstractEntityRepository<Long, Domain> {
public void save(final Domain domain) { public void save(final Domain domain) {
super.save(domain); super.save(domain);
} }
@AuthorizationRequired @AuthorizationRequired
@RequiresPrivilege(CategorizationConstants.PRIVILEGE_MANAGE_DOMAINS) @RequiresPrivilege(CategorizationConstants.PRIVILEGE_MANAGE_DOMAINS)
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
@ -158,4 +134,5 @@ public class DomainRepository extends AbstractEntityRepository<Long, Domain> {
public void delete(final Domain domain) { public void delete(final Domain domain) {
super.delete(domain); super.delete(domain);
} }
} }

View File

@ -79,25 +79,6 @@ public abstract class AbstractEntityRepository<K, E> {
return entityManager.createEntityGraph(getEntityClass()); return entityManager.createEntityGraph(getEntityClass());
} }
protected void applyDefaultEntityGraph(final TypedQuery<E> query) {
if (getEntityClass().isAnnotationPresent(DefaultEntityGraph.class)) {
LOGGER.debug("The following EntityGraphs are available for the "
+ "entity class {}:",
getEntityClass().getName());
getEntityManager().getEntityGraphs(getEntityClass()).stream()
.forEach(g -> LOGGER.debug("\t{}", g.getName()));
LOGGER.debug("Entity class {} has default entity graphs:",
getEntityClass().getName());
LOGGER.debug("Applying entity graph {}",
getEntityClass().getAnnotation(
DefaultEntityGraph.class).value());
query.setHint(FETCH_GRAPH_HINT_KEY,
entityManager.getEntityGraph(
getEntityClass().getAnnotation(
DefaultEntityGraph.class).value()));
}
}
/** /**
* Helper method for retrieving a single result from a query. * Helper method for retrieving a single result from a query.
* *
@ -172,12 +153,7 @@ public abstract class AbstractEntityRepository<K, E> {
*/ */
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
public E findById(final K entityId) { public E findById(final K entityId) {
if (getEntityClass().isAnnotationPresent(DefaultEntityGraph.class)) { return entityManager.find(getEntityClass(), entityId);
return findById(entityId, getEntityClass().getAnnotation(
DefaultEntityGraph.class).value());
} else {
return entityManager.find(getEntityClass(), entityId);
}
} }
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
@ -239,12 +215,8 @@ public abstract class AbstractEntityRepository<K, E> {
} }
public List<E> executeCriteriaQuery(final CriteriaQuery<E> criteriaQuery) { public List<E> executeCriteriaQuery(final CriteriaQuery<E> criteriaQuery) {
if (hasDefaultEntityGraph()) { final TypedQuery<E> query = entityManager.createQuery(criteriaQuery);
return executeCriteriaQuery(criteriaQuery, getDefaultEntityGraph()); return query.getResultList();
} else {
final TypedQuery<E> query = entityManager.createQuery(criteriaQuery);
return query.getResultList();
}
} }
public List<E> executeCriteriaQuery(final CriteriaQuery<E> criteriaQuery, public List<E> executeCriteriaQuery(final CriteriaQuery<E> criteriaQuery,
@ -316,19 +288,4 @@ public abstract class AbstractEntityRepository<K, E> {
entityManager.remove(entityManager.merge(entity)); entityManager.remove(entityManager.merge(entity));
} }
protected boolean hasDefaultEntityGraph() {
return getEntityClass().isAnnotationPresent(DefaultEntityGraph.class);
}
protected String getDefaultEntityGraph() {
if (hasDefaultEntityGraph()) {
return getEntityClass().getAnnotation(DefaultEntityGraph.class)
.value();
} else {
throw new IllegalArgumentException(String.format(
"Entity class \"%s\" has no DefaultEntityGraph!",
getEntityClass().getName()));
}
}
} }

View File

@ -1,39 +0,0 @@
/*
* 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.core;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Target({TYPE})
public @interface DefaultEntityGraph {
String value();
}

View File

@ -18,7 +18,6 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import com.arsdigita.kernel.KernelConfig;
import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationInfo;
@ -47,6 +46,15 @@ public class CcmShiroRealm extends AuthorizingRealm {
protected AuthorizationInfo doGetAuthorizationInfo( protected AuthorizationInfo doGetAuthorizationInfo(
final PrincipalCollection principals) { final PrincipalCollection principals) {
final CcmShiroRealmController controller;
try {
controller = CdiUtil.createCdiUtil()
.findBean(CcmShiroRealmController.class);
} catch (IllegalStateException ex) {
throw new AuthenticationException(
"Failed to retrieve CcmShiroRealmController", ex);
}
// Get the pricipal (object identifing the user). // Get the pricipal (object identifing the user).
final Object principal = principals.getPrimaryPrincipal(); final Object principal = principals.getPrimaryPrincipal();
@ -64,35 +72,8 @@ public class CcmShiroRealm extends AuthorizingRealm {
if ("system-user".equals(userIdentifier)) { if ("system-user".equals(userIdentifier)) {
// The system user is a virtual user which has all roles and all // The system user is a virtual user which has all roles and all
// privileges // privileges
// final RoleRepository roleRepository;
// final BeanManager beanManager = CDI.current().getBeanManager();
// final Set<Bean<?>> beans = beanManager.
// getBeans(RoleRepository.class);
// final Iterator<Bean<?>> iterator = beans.iterator();
// if (iterator.hasNext()) {
// @SuppressWarnings("unchecked")
// final Bean<RoleRepository> bean
// = (Bean<RoleRepository>) iterator
// .next();
// final CreationalContext<RoleRepository> ctx = beanManager.
// createCreationalContext(bean);
//
// roleRepository = (RoleRepository) beanManager.getReference(
// bean, RoleRepository.class, ctx);
// } else {
// throw new AuthenticationException(
// "Failed to retrieve RoleRepository");
// }
final RoleRepository roleRepository; final List<Role> roles = controller.retrieveAllRoles();
try {
roleRepository = CdiUtil.createCdiUtil()
.findBean(RoleRepository.class);
} catch (IllegalStateException ex) {
throw new AuthenticationException(
"Failed to retrieve RoleRepository", ex);
}
final List<Role> roles = roleRepository.findAll();
final SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); final SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
for (final Role role : roles) { for (final Role role : roles) {
@ -103,41 +84,7 @@ public class CcmShiroRealm extends AuthorizingRealm {
return info; return info;
} }
//Find the user identified by the provided pricipal. return controller.createAuthorizationInfo(userIdentifier);
final User user = findUser(userIdentifier);
// Create a SimpleAuthorizationInfo instance. Contains the information
// from the database in the format expected by Shiro.
final SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// Get the Roles directly assigned to the user.
for (final RoleMembership roleMembership : user.getRoleMemberships()) {
// Add the role to the AuthorizationInfo object.
info.addRole(roleMembership.getRole().getName());
// Add the permissions assigned to the role to the AuthorizatonInfo.
for (final Permission permission : roleMembership.getRole()
.getPermissions()) {
info.addStringPermission(permissionToString(permission));
}
}
//Get the Roles assigned to the groups of which the user is member of.
for (final GroupMembership membership : user.getGroupMemberships()) {
// Get the roles assigned to the group
for (final RoleMembership roleMembership : membership.getGroup()
.getRoleMemberships()) {
// Add the role to the AuthorizationInfo
info.addRole(roleMembership.getRole().getName());
// Add the permissions assigned to the role to the
// AuthorizationInfo
for (final Permission permission : roleMembership.getRole()
.getPermissions()) {
info.addStringPermission(permissionToString(permission));
}
}
}
return info;
} }
@Override @Override
@ -156,10 +103,19 @@ public class CcmShiroRealm extends AuthorizingRealm {
principal.getClass().getName())); principal.getClass().getName()));
} }
final CcmShiroRealmController controller;
try {
controller = CdiUtil.createCdiUtil()
.findBean(CcmShiroRealmController.class);
} catch (IllegalStateException ex) {
throw new AuthenticationException(
"Failed to retrieve CcmShiroRealmController", ex);
}
// Convert the pricipal to a string. // Convert the pricipal to a string.
final String userIdentifier = (String) principal; final String userIdentifier = (String) principal;
// Find the user identified by the pricipal. // Find the user identified by the pricipal.
final User user = findUser(userIdentifier); final User user = controller.findUser(userIdentifier);
// Return a SimpleAuthenticationInfo with the information relevant // Return a SimpleAuthenticationInfo with the information relevant
// for Shiro // for Shiro
@ -168,71 +124,6 @@ public class CcmShiroRealm extends AuthorizingRealm {
"CcmShiroRealm"); "CcmShiroRealm");
} }
/**
* Helper method for finding a user by its identifier. Depending on the
* configuration of CCM this is either the name of the user or the email
* address of the user.
*
* @param userIdentifier The identifier of the user.
*
* @return The User identified by the provided {@code userIdentifier}.
*
* @throws AuthenticationException if no user for the provided identifier
* could be retrieved.
*/
private User findUser(final String userIdentifier) {
// For some reason we can't use the the CdiUtil class here, therefore
// we have to do the lookup for the UserRepository be ourself.
final UserRepository userRepository;
// final BeanManager beanManager = CDI.current().getBeanManager();
// final Set<Bean<?>> beans = beanManager.getBeans(
// UserRepository.class);
// final Iterator<Bean<?>> iterator = beans.iterator();
// if (iterator.hasNext()) {
// @SuppressWarnings("unchecked")
// final Bean<UserRepository> bean = (Bean<UserRepository>) iterator
// .next();
// final CreationalContext<UserRepository> ctx = beanManager
// .createCreationalContext(bean);
//
// userRepository = (UserRepository) beanManager.getReference(
// bean, UserRepository.class, ctx);
try {
userRepository = CdiUtil.createCdiUtil().findBean(
UserRepository.class);
} catch (IllegalStateException ex) {
throw new AuthenticationException(
"Failed to retrieve UserRepository.", ex);
}
// } else {
// throw new AuthenticationException(
// "Failed to retrieve UserRepository.");
// }
// Depending of the configuration of CCM use the appropriate method
// for finding the user in the database.
final KernelConfig config = KernelConfig.getConfig();
final User user;
if ("email".equals(config.getPrimaryUserIdentifier())) {
user = userRepository.findByEmailAddress(userIdentifier);
} else {
user = userRepository.findByName(userIdentifier);
}
// If no matching user is found throw an AuthenticationException
if (user
== null) {
throw new AuthenticationException(String.format(
"No user identified by principal \"%s\" was found. Primary user "
+ "identifier is \"%s\".",
userIdentifier, config.getPrimaryUserIdentifier()));
}
return user;
}
/** /**
* Helper method for converting a {@link Permission} to the string format * Helper method for converting a {@link Permission} to the string format
* used by Shiro. * used by Shiro.

View File

@ -0,0 +1,155 @@
/*
* Copyright (C) 2017 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 com.arsdigita.kernel.KernelConfig;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.libreccm.configuration.ConfigurationManager;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
/**
* This bean provides several services for the {@link CcmShiroRealm}. It wraps
* several calls into a transaction to avoid
* {@code LazyInitializationException}.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
class CcmShiroRealmController {
@Inject
private UserRepository userRepo;
@Inject
private GroupRepository groupRepo;
@Inject
private RoleRepository roleRepo;
@Inject
private ConfigurationManager confManager;
@Transactional(Transactional.TxType.REQUIRED)
protected List<Role> retrieveAllRoles() {
return roleRepo.findAll();
}
/**
* Helper method for finding a user by its identifier. Depending on the
* configuration of CCM this is either the name of the user or the email
* address of the user.
*
* @param userIdentifier The identifier of the user.
*
* @return The User identified by the provided {@code userIdentifier}.
*
* @throws AuthenticationException if no user for the provided identifier
* could be retrieved.
*/
@Transactional(Transactional.TxType.REQUIRED)
protected User findUser(final String userIdentifier) {
final KernelConfig kernelConfig = confManager.findConfiguration(
KernelConfig.class);
final User user;
if ("email".equals(kernelConfig.getPrimaryUserIdentifier())) {
user = userRepo.findByEmailAddress(userIdentifier);
} else {
user = userRepo.findByName(userIdentifier);
}
// If no matching user is found throw an AuthenticationException
if (user
== null) {
throw new AuthenticationException(String.format(
"No user identified by principal \"%s\" was found. Primary user "
+ "identifier is \"%s\".",
userIdentifier, kernelConfig.getPrimaryUserIdentifier()));
}
return user;
}
@Transactional(Transactional.TxType.REQUIRED)
protected AuthorizationInfo createAuthorizationInfo(
final String userIdentifier) {
final User user = findUser(userIdentifier);
// Create a SimpleAuthorizationInfo instance. Contains the information
// from the database in the format expected by Shiro.
final SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// Get the Roles directly assigned to the user.
for (final RoleMembership roleMembership : user.getRoleMemberships()) {
// Add the role to the AuthorizationInfo object.
info.addRole(roleMembership.getRole().getName());
// Add the permissions assigned to the role to the AuthorizatonInfo.
for (final Permission permission : roleMembership.getRole()
.getPermissions()) {
info.addStringPermission(permissionToString(permission));
}
}
//Get the Roles assigned to the groups of which the user is member of.
for (final GroupMembership membership : user.getGroupMemberships()) {
// Get the roles assigned to the group
for (final RoleMembership roleMembership : membership.getGroup()
.getRoleMemberships()) {
// Add the role to the AuthorizationInfo
info.addRole(roleMembership.getRole().getName());
// Add the permissions assigned to the role to the
// AuthorizationInfo
for (final Permission permission : roleMembership.getRole()
.getPermissions()) {
info.addStringPermission(permissionToString(permission));
}
}
}
return info;
}
/**
* Helper method for converting a {@link Permission} to the string format
* used by Shiro.
*
* @param permission The permission to convert.
*
* @return A Shiro permission string.
*/
private String permissionToString(final Permission permission) {
if (permission.getObject() == null) {
return permission.getGrantedPrivilege();
} else {
return String.format("%s:%d",
permission.getGrantedPrivilege(),
permission.getObject().getObjectId());
}
}
}

View File

@ -18,9 +18,7 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
import org.libreccm.core.DefaultEntityGraph;
import org.libreccm.portation.Portable; import org.libreccm.portation.Portable;
import javax.persistence.Entity; import javax.persistence.Entity;
@ -35,6 +33,7 @@ import javax.persistence.Table;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -89,7 +88,6 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA;
@NamedAttributeNode(value = "permissions")}) @NamedAttributeNode(value = "permissions")})
}) })
}) })
@DefaultEntityGraph("Group.withMembersAndRoleMemberships")
@XmlRootElement(name = "user-group", namespace = CORE_XML_NS) @XmlRootElement(name = "user-group", namespace = CORE_XML_NS)
public class Group extends Party implements Serializable, Portable { public class Group extends Party implements Serializable, Portable {

View File

@ -18,9 +18,7 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
import org.libreccm.core.DefaultEntityGraph;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
@ -40,6 +38,7 @@ import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern; import javax.validation.constraints.Pattern;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlElementWrapper;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -74,7 +73,6 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA;
attributeNodes = @NamedAttributeNode( attributeNodes = @NamedAttributeNode(
value = "roleMemberships")) value = "roleMemberships"))
}) })
@DefaultEntityGraph("Party.withRoleMemberships")
public class Party implements Serializable { public class Party implements Serializable {
private static final long serialVersionUID = 3319997992281332204L; private static final long serialVersionUID = 3319997992281332204L;

View File

@ -18,10 +18,8 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.NotBlank;
import org.libreccm.core.DefaultEntityGraph;
import org.libreccm.l10n.LocalizedString; import org.libreccm.l10n.LocalizedString;
import org.libreccm.portation.Portable; import org.libreccm.portation.Portable;
import org.libreccm.workflow.TaskAssignment; import org.libreccm.workflow.TaskAssignment;
@ -48,6 +46,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -55,6 +54,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Field;
import static org.libreccm.core.CoreConstants.CORE_XML_NS; import static org.libreccm.core.CoreConstants.CORE_XML_NS;
@ -117,7 +117,6 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA;
@NamedAttributeNode(value = "permissions") @NamedAttributeNode(value = "permissions")
}) })
}) })
@DefaultEntityGraph(Role.ENTITY_GRPAH_WITH_MEMBERS)
@XmlRootElement(name = "role", namespace = CORE_XML_NS) @XmlRootElement(name = "role", namespace = CORE_XML_NS)
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
@SuppressWarnings({"PMD.ShortClassName", "PMD.TooManyMethods"}) @SuppressWarnings({"PMD.ShortClassName", "PMD.TooManyMethods"})

View File

@ -18,9 +18,7 @@
*/ */
package org.libreccm.security; package org.libreccm.security;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
import org.libreccm.core.DefaultEntityGraph;
import org.libreccm.core.EmailAddress; import org.libreccm.core.EmailAddress;
import org.libreccm.portation.Portable; import org.libreccm.portation.Portable;
@ -48,6 +46,7 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlTransient;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -122,7 +121,6 @@ import static org.libreccm.core.CoreConstants.DB_SCHEMA;
) )
}) })
}) })
@DefaultEntityGraph("User.withGroupAndRoleMemberships")
@XmlRootElement(name = "user", namespace = CORE_XML_NS) @XmlRootElement(name = "user", namespace = CORE_XML_NS)
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
//Supressing a few warnings from PMD because they misleading here. //Supressing a few warnings from PMD because they misleading here.

View File

@ -61,7 +61,6 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
public User findByName(final String name) { public User findByName(final String name) {
final TypedQuery<User> query = getEntityManager().createNamedQuery( final TypedQuery<User> query = getEntityManager().createNamedQuery(
"User.findByName", User.class); "User.findByName", User.class);
applyDefaultEntityGraph(query);
query.setParameter("name", name); query.setParameter("name", name);
return getSingleResultOrNull(query); return getSingleResultOrNull(query);
@ -123,7 +122,6 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
final TypedQuery<User> query = getEntityManager().createNamedQuery( final TypedQuery<User> query = getEntityManager().createNamedQuery(
"User.findByEmailAddress", User.class); "User.findByEmailAddress", User.class);
query.setParameter("emailAddress", emailAddress); query.setParameter("emailAddress", emailAddress);
applyDefaultEntityGraph(query);
return getSingleResultOrNull(query); return getSingleResultOrNull(query);
} }

View File

@ -19,6 +19,7 @@
package org.libreccm.portation; package org.libreccm.portation;
import javax.inject.Inject; import javax.inject.Inject;
import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence; import org.jboss.arquillian.junit.InSequence;
@ -35,7 +36,6 @@ 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.tests.categories.IntegrationTest;
import static org.libreccm.testutils.DependenciesHelpers.getModuleDependencies; import static org.libreccm.testutils.DependenciesHelpers.getModuleDependencies;
@ -49,7 +49,7 @@ import org.jboss.arquillian.persistence.CleanupUsingScript;
* @author <a href="mailto:tosmers@uni-bremen.de">Tobias Osmers</a> * @author <a href="mailto:tosmers@uni-bremen.de">Tobias Osmers</a>
* @version created on 12/1/16 * @version created on 12/1/16
*/ */
@org.junit.experimental.categories.Category(IntegrationTest.class) //@org.junit.experimental.categories.Category(IntegrationTest.class)
@RunWith(Arquillian.class) @RunWith(Arquillian.class)
@PersistenceTest @PersistenceTest
@Transactional(TransactionMode.COMMIT) @Transactional(TransactionMode.COMMIT)