CCM NG/ccm-cms: Support for the TYPE_USE privilege.

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4455 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2016-11-24 17:59:40 +00:00
parent 582bcab967
commit b39aa8152f
7 changed files with 452 additions and 157 deletions

View File

@ -23,11 +23,9 @@ import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label; 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.GridPanel;
import com.arsdigita.bebop.event.FormSectionEvent; import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.ActionEvent; import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener; import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSubmissionListener; import com.arsdigita.bebop.event.FormSubmissionListener;
import com.arsdigita.cms.CMS; import com.arsdigita.cms.CMS;
@ -40,11 +38,9 @@ import com.arsdigita.cms.ui.BaseDeleteForm;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
//ToDo insert later import com.arsdigita.cms.ui.ContentSectionPage; //ToDo insert later import com.arsdigita.cms.ui.ContentSectionPage;
import org.libreccm.core.CcmObject;
import com.arsdigita.kernel.ui.ACSObjectSelectionModel; import com.arsdigita.kernel.ui.ACSObjectSelectionModel;
import com.arsdigita.toolbox.ui.ActionGroup; import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.toolbox.ui.Section;
import com.arsdigita.toolbox.ui.Cancellable; import com.arsdigita.toolbox.ui.Cancellable;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -53,7 +49,6 @@ import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentSectionManager; import org.librecms.contentsection.ContentSectionManager;
import org.librecms.contentsection.ContentTypeManager; import org.librecms.contentsection.ContentTypeManager;
import java.math.BigDecimal;
/** /**
* This class contains the split pane for the ContentType administration * This class contains the split pane for the ContentType administration

View File

@ -5,30 +5,43 @@ import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Table; import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.event.TableActionEvent; import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.event.TableActionListener; import com.arsdigita.bebop.event.TableActionListener;
import com.arsdigita.bebop.table.RowData;
import com.arsdigita.bebop.table.TableCellRenderer; import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn; import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableColumnModel; import com.arsdigita.bebop.table.TableColumnModel;
import com.arsdigita.bebop.table.TableModel; import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.bebop.table.TableModelBuilder; import com.arsdigita.bebop.table.TableModelBuilder;
import com.arsdigita.cms.CMS; import com.arsdigita.cms.CMS;
import org.librecms.contentsection.ContentType; import org.librecms.contentsection.ContentType;
import com.arsdigita.cms.dispatcher.Utilities; import com.arsdigita.cms.dispatcher.Utilities;
import com.arsdigita.cms.ui.ContentSectionRequestLocal; import com.arsdigita.cms.ui.ContentSectionRequestLocal;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.ui.admin.GlobalizationUtil; import com.arsdigita.ui.admin.GlobalizationUtil;
import org.libreccm.security.Party; import org.libreccm.security.Party;
import org.libreccm.security.Role; import org.libreccm.security.Role;
import com.arsdigita.util.LockableImpl; import com.arsdigita.util.LockableImpl;
import java.awt.image.Kernel; import java.awt.image.Kernel;
import java.util.List; import java.util.List;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.Permission; import org.libreccm.security.Permission;
import org.libreccm.security.PermissionChecker;
import org.libreccm.security.RoleRepository; import org.libreccm.security.RoleRepository;
import org.librecms.CmsConstants; import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.privileges.AdminPrivileges;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
import java.util.Iterator;
/** /**
* *
* ToDo, maybe not needed anymore... * ToDo, maybe not needed anymore...
@ -49,28 +62,28 @@ public class TypePermissionsTable extends Table implements TableActionListener {
this.type = type; this.type = type;
setEmptyView(new Label(new GlobalizedMessage( setEmptyView(new Label(new GlobalizedMessage(
"cms.ui.type.permissions.none", "cms.ui.type.permissions.none",
CmsConstants.CMS_BUNDLE))); CmsConstants.CMS_BUNDLE)));
TableColumnModel columnModel = getColumnModel(); TableColumnModel columnModel = getColumnModel();
columnModel.add(new TableColumn( columnModel.add(new TableColumn(
0, 0,
new GlobalizedMessage("cms.ui.type.permissions.role", new GlobalizedMessage("cms.ui.type.permissions.role",
CmsConstants.CMS_BUNDLE).localize(), CmsConstants.CMS_BUNDLE).localize(),
TABLE_COL_ROLE)); TABLE_COL_ROLE));
columnModel.add(new TableColumn( columnModel.add(new TableColumn(
1, 1,
new GlobalizedMessage("cms.ui.type.permissions_can_use", new GlobalizedMessage("cms.ui.type.permissions_can_use",
CmsConstants.CMS_BUNDLE).localize(), CmsConstants.CMS_BUNDLE).localize(),
TABLE_COL_CAN_USE)); TABLE_COL_CAN_USE));
columnModel.add(new TableColumn( columnModel.add(new TableColumn(
2, 2,
new GlobalizedMessage("cms.ui.type.permission.action", new GlobalizedMessage("cms.ui.type.permission.action",
CmsConstants.CMS_BUNDLE).localize(), CmsConstants.CMS_BUNDLE).localize(),
TABLE_COL_ACTION)); TABLE_COL_ACTION));
setModelBuilder(new TypePermissionsTableModelBuilder()); setModelBuilder(new TypePermissionsTableModelBuilder());
@ -83,36 +96,21 @@ public class TypePermissionsTable extends Table implements TableActionListener {
@Override @Override
public void cellSelected(final TableActionEvent event) { public void cellSelected(final TableActionEvent event) {
PageState state = event.getPageState(); final PageState state = event.getPageState();
final TableColumn column = getColumnModel().get(event.getColumn()); final TableColumn column = getColumnModel().get(event.getColumn());
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final RoleRepository roleRepo = cdiUtil.findBean(RoleRepository.class); final RoleRepository roleRepo = cdiUtil.findBean(RoleRepository.class);
final TypePermissionsTableController controller = cdiUtil.findBean(
TypePermissionsTableController.class);
if (TABLE_COL_ACTION.equals(column.getHeaderKey().toString())) { if (TABLE_COL_ACTION.equals(column.getHeaderKey().toString())) {
final Role role = roleRepo.findById(Long.parseLong( final Role role = roleRepo.findById(Long.parseLong(
event.getRowKey().toString())); event.getRowKey().toString()));
ContentType contentType = getType().getContentType(state); ContentType contentType = getType().getContentType(state);
// ToDo
// ObjectPermissionCollection permissions controller.toggleTypeUsePermission(contentType, role);
// = PermissionService.
// getDirectGrantedPermissions(contentType.getOID());
//
// if ((permissions.size() == 0)) {
// role.grantPermission(contentType,
// PrivilegeDescriptor.get(
// com.arsdigita.cms.SecurityManager.CMS_NEW_ITEM));
// } else if (!role.checkPermission(contentType, PrivilegeDescriptor.
// get(com.arsdigita.cms.SecurityManager.CMS_NEW_ITEM))) {
// role.grantPermission(contentType,
// PrivilegeDescriptor.get(
// com.arsdigita.cms.SecurityManager.CMS_NEW_ITEM));
// } else {
// role.revokePermission(contentType,
// PrivilegeDescriptor.get(
// com.arsdigita.cms.SecurityManager.CMS_NEW_ITEM));
// }
} }
} }
@ -122,8 +120,8 @@ public class TypePermissionsTable extends Table implements TableActionListener {
} }
private class TypePermissionsTableModelBuilder private class TypePermissionsTableModelBuilder
extends LockableImpl extends LockableImpl
implements TableModelBuilder { implements TableModelBuilder {
public TypePermissionsTableModelBuilder() { public TypePermissionsTableModelBuilder() {
} }
@ -133,95 +131,73 @@ public class TypePermissionsTable extends Table implements TableActionListener {
table.getRowSelectionModel().clearSelection(state); table.getRowSelectionModel().clearSelection(state);
return new TypePermissionsTableModel(table, state); return new TypePermissionsTableModel(table, state);
} }
} }
private class TypePermissionsTableModel implements TableModel { private class TypePermissionsTableModel implements TableModel {
private Table table; private final Iterator<RowData<Long>> iterator;
private List<Role> roles; private RowData<Long> currentRow;
private ContentType contentType;
private List<Permission> permissions;
public TypePermissionsTableModel(final Table table, public TypePermissionsTableModel(final Table table,
final PageState state) { final PageState state) {
this.table = table; final ContentType contentType = ((TypePermissionsTable) table)
contentType .getType()
= ((TypePermissionsTable) table).getType().getContentType( .getContentType(state);
state);
roles = CMS.getContext().getContentSection().getRoles(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final TypePermissionsTableController controller = cdiUtil.findBean(
// permissions TypePermissionsTableController.class);
// = PermissionService. final ContentSection section = CMS.getContext().getContentSection();
// getDirectGrantedPermissions(contentType.getOID()); final List<RowData<Long>> rows = controller.retrieveTypePermissions(
contentType, section);
iterator = rows.iterator();
} }
@Override @Override
public int getColumnCount() { public int getColumnCount() {
if (roles == null) { return 3;
return 0;
} else {
return (int) roles.size();
}
} }
@Override @Override
public boolean nextRow() { public boolean nextRow() {
return false; if (iterator.hasNext()) {
// if (roles == null) { currentRow = iterator.next();
// return false; return true;
// } else { } else {
// return roles.next(); return false;
// } }
} }
@Override @Override
public Object getElementAt(int columnIndex) { public Object getElementAt(final int columnIndex) {
// switch (columnIndex) { switch (columnIndex) {
// case 0: case 0:
// return roles.getRole().getName(); return currentRow.getColData(0);
// case 1: case 1:
// if (permissions.isEmpty()) { return currentRow.getColData(1);
// return "cms.ui.type.permissions.can_use.yes"; case 2:
// } else { if ("cms.ui.type.permissions.can_use.yes".equals(currentRow
// if (roles.getRole().checkPermission(contentType, .getColData(1))) {
// PrivilegeDescriptor. return "cms.ui.type.permissions.actions.revoke";
// get( } else {
// com.arsdigita.cms.SecurityManager.CMS_NEW_ITEM))) { return "cms.ui.type.permissions.can_use.grant";
// return "cms.ui.type.permissions.can_use.yes"; }
// } else { default:
// return "cms.ui.type.permissions.can_use.no"; throw new IllegalArgumentException("Invalid column index.");
// } }
// }
// case 2:
// if (permissions.size() == 0) {
// return "cms.ui.type.permissions.actions.restrict_to_this_role";
// } else {
// if (roles.getRole().checkPermission(contentType,
// PrivilegeDescriptor.
// get(
// com.arsdigita.cms.SecurityManager.CMS_NEW_ITEM))) {
// return "cms.ui.type.permissions.actions.revoke";
// } else {
// return "cms.ui.type.permissions.can_use.grant";
// }
// }
// default:
// return null;
// }
return null;
} }
@Override @Override
public Object getKeyAt(int columnIndex) { public Object getKeyAt(final int columnIndex) {
// return roles.getRole().getID(); return currentRow.getRowKey();
return null;
} }
} }
private class RoleCellRenderer private class RoleCellRenderer
extends LockableImpl extends LockableImpl
implements TableCellRenderer { implements TableCellRenderer {
@Override @Override
public Component getComponent(Table table, public Component getComponent(Table table,
@ -231,58 +207,62 @@ public class TypePermissionsTable extends Table implements TableActionListener {
Object key, Object key,
int row, int row,
int column) { int column) {
return new Label(value.toString()); return new Text(value.toString());
} }
} }
private class CanUseCellRenderer private class CanUseCellRenderer
extends LockableImpl extends LockableImpl
implements TableCellRenderer { implements TableCellRenderer {
@Override @Override
public Component getComponent(Table table, public Component getComponent(final Table table,
PageState state, final PageState state,
Object value, final Object value,
boolean isSelected, final boolean isSelected,
Object key, final Object key,
int row, final int row,
int column) { final int column) {
return new Label(GlobalizationUtil.globalize(value.toString())); return new Label(new GlobalizedMessage(value.toString(),
CmsConstants.CMS_BUNDLE));
} }
} }
private class ActionCellRenderer private class ActionCellRenderer
extends LockableImpl extends LockableImpl
implements TableCellRenderer { implements TableCellRenderer {
public Component getComponent(Table table, @Override
PageState state, public Component getComponent(final Table table,
Object value, final PageState state,
final Object value,
boolean isSelected, boolean isSelected,
Object key, final Object key,
int row, final int row,
int column) { final int column) {
// com.arsdigita.cms.SecurityManager securityManager = Utilities. final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
// getSecurityManager(state); final PermissionChecker permissionChecker = cdiUtil.findBean(
// Party party = Kernel.getContext().getParty(); PermissionChecker.class);
// if (party == null) {
// party = Kernel.getPublicUser(); final ContentSection section = CMS.getContext().getContentSection();
// }
// if (securityManager.canAccess(party, if (permissionChecker.isPermitted(
// SecurityConstants.CONTENT_TYPE_ADMIN)) { AdminPrivileges.ADMINISTER_CONTENT_TYPES, section)) {
// ControlLink link = new ControlLink((String) GlobalizationUtil.
// globalize( return new ControlLink(new Label(new GlobalizedMessage(
// value.toString()).localize()); (String) value), CmsConstants.CMS_BUNDLE));
// } else {
// return link; return new Text("");
// } else { }
return new Label(value.toString());
// }
} }
} }
private ContentTypeRequestLocal getType() { private ContentTypeRequestLocal getType() {
return type; return type;
} }
} }

View File

@ -0,0 +1,103 @@
/*
* 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 com.arsdigita.cms.ui.type;
import org.librecms.contentsection.privileges.TypePrivileges;
import com.arsdigita.bebop.table.RowData;
import org.libreccm.security.PermissionChecker;
import org.libreccm.security.PermissionManager;
import org.libreccm.security.Role;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType;
import org.librecms.contentsection.ContentTypeRepository;
import java.util.List;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
public class TypePermissionsTableController {
@Inject
private PermissionChecker permissionChecker;
@Inject
private PermissionManager permissionManager;
@Inject
private ContentTypeRepository typeRepo;
@Transactional(Transactional.TxType.REQUIRED)
public List<RowData<Long>> retrieveTypePermissions(
final ContentType type, final ContentSection section) {
//Ensure that we use a sane object for the type
return retrieveTypePermissions(type.getObjectId(), section);
}
@Transactional(Transactional.TxType.REQUIRED)
public List<RowData<Long>> retrieveTypePermissions(
final long typeId, final ContentSection section) {
final ContentType type = typeRepo.findById(typeId);
final List<Role> roles = section.getRoles();
return roles.stream()
.map(role -> retrievePermissionsForRole(type, role))
.collect(Collectors.toList());
}
private RowData<Long> retrievePermissionsForRole(final ContentType type,
final Role role) {
final RowData<Long> rowData = new RowData<>(2);
rowData.setRowKey(role.getRoleId());
rowData.setColData(0, role.getName());
if (permissionChecker.isPermitted(TypePrivileges.USE_TYPE, type)) {
rowData.setColData(1, "cms.ui.type.permissions.can_use.yes");
} else {
rowData.setColData(1, "cms.ui.type.permissions.can_use.no");
}
return rowData;
}
public void toggleTypeUsePermission(final ContentType type,
final Role role) {
if (permissionChecker.isPermitted(TypePrivileges.USE_TYPE, type, role)) {
permissionManager.revokePrivilege(TypePrivileges.USE_TYPE,
role,
type);
} else {
permissionManager.grantPrivilege(TypePrivileges.USE_TYPE,
role,
type);
}
}
}

View File

@ -0,0 +1,58 @@
/*
* 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 com.arsdigita.cms.ui.workflow;
import org.libreccm.security.Role;
import org.libreccm.security.Shiro;
import org.libreccm.security.User;
import org.libreccm.workflow.AssignableTask;
import org.libreccm.workflow.AssignableTaskManager;
import org.libreccm.workflow.Workflow;
import java.util.List;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
public class TaskFinishFormController {
@Inject
private AssignableTaskManager taskManager;
@Inject
private Shiro shiro;
@Transactional(Transactional.TxType.REQUIRED)
public List<AssignableTask> findEnabledTasks(final Workflow workflow) {
final User user = shiro.getUser();
final List<Role> roles = user.getRoleMemberships().stream()
.map(membership -> membership.getRole())
.collect(Collectors.toList());
return taskManager.findAssignedTasks(workflow, roles);
}
}

View File

@ -18,15 +18,16 @@
*/ */
package org.librecms.contentsection; package org.librecms.contentsection;
import org.librecms.contentsection.privileges.TypePrivileges;
import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.PermissionManager;
import org.libreccm.security.RequiresPrivilege; import org.libreccm.security.RequiresPrivilege;
import org.libreccm.security.Role;
import org.libreccm.workflow.WorkflowTemplate; import org.libreccm.workflow.WorkflowTemplate;
import org.librecms.contentsection.privileges.AdminPrivileges; import org.librecms.contentsection.privileges.AdminPrivileges;
import org.librecms.lifecycle.LifecycleDefinition; import org.librecms.lifecycle.LifecycleDefinition;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.transaction.Transactional; import javax.transaction.Transactional;
@ -42,6 +43,9 @@ public class ContentTypeManager {
@Inject @Inject
private ContentTypeRepository typeRepo; private ContentTypeRepository typeRepo;
@Inject
private PermissionManager permissionManager;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Class<? extends ContentItem> classNameToClass(final String className) { public Class<? extends ContentItem> classNameToClass(final String className) {
final Class<?> clazz; final Class<?> clazz;
@ -50,7 +54,7 @@ public class ContentTypeManager {
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
"No class with the name \"%s\" exists.", className), "No class with the name \"%s\" exists.", className),
ex); ex);
} }
if (clazz.isAssignableFrom(ContentItem.class)) { if (clazz.isAssignableFrom(ContentItem.class)) {
@ -85,4 +89,24 @@ public class ContentTypeManager {
typeRepo.save(type); typeRepo.save(type);
} }
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
public void grantUsageOfType(
@RequiresPrivilege(AdminPrivileges.ADMINISTER_CONTENT_TYPES)
final ContentType type,
final Role role) {
permissionManager.grantPrivilege(TypePrivileges.USE_TYPE, role, type);
}
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
public void denyUsageOnType(
@RequiresPrivilege(AdminPrivileges.ADMINISTER_CONTENT_TYPES)
final ContentType type,
final Role role) {
permissionManager.revokePrivilege(TypePrivileges.USE_TYPE, role, type);
}
} }

View File

@ -0,0 +1,33 @@
/*
* 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.privileges;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public final class TypePrivileges {
public static final String USE_TYPE = "use_type";
private TypePrivileges() {
//Nothing
}
}

View File

@ -24,12 +24,15 @@ import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.Subject;
import org.libreccm.core.CcmObject; import org.libreccm.core.CcmObject;
import java.util.Optional;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.transaction.Transactional;
/** /**
* An utility class for checking permissions. Uses the current {@link Subject} * An utility class for checking permissions. Uses the current {@link Subject}
* as provided by the {@link Shiro} bean. * as provided by the {@link Shiro} bean useless otherwise indicated.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@ -45,14 +48,17 @@ public class PermissionChecker {
@Inject @Inject
private Shiro shiro; private Shiro shiro;
@Inject
private RoleRepository roleRepo;
/** /**
* Checks if the current subject has a permission granting the provided * Checks if the current subject has a permission granting the provided
* privilege. * {@code privilege}.
* *
* @param privilege The privilege granted by the permission. * @param privilege The privilege granted by the permission.
* *
* @return {@code true} if the current subject has as permission granting * @return {@code true} if the current subject has a permission granting the
* the provided {@code privilege}, {@code false} otherwise. * provided {@code privilege}, {@code false} otherwise.
*/ */
public boolean isPermitted(final String privilege) { public boolean isPermitted(final String privilege) {
if (subject.isAuthenticated()) { if (subject.isAuthenticated()) {
@ -63,16 +69,51 @@ public class PermissionChecker {
} }
} }
/**
* Check if the provided {@code role} has a permissions granting the
* provided {@code privilege}.
*
* @param privilege The privilege granted by the permission.
* @param role The role to check for a permission granting the
* {@code privilege}.
*
* @return {@code true} if the role has a permission granting the provided
* {@code privilege}, {@code false} otherwise.
*/
@Transactional(Transactional.TxType.REQUIRED)
public boolean isPermitted(final String privilege, final Role role) {
if (privilege == null || privilege.trim().isEmpty()) {
throw new IllegalArgumentException(
"Can't check permission null (or empty)");
}
if (role == null) {
throw new IllegalArgumentException(
"Can't check permission for role null.");
}
//Ensure that we have a none detached entity
final Role theRole = roleRepo.findById(role.getRoleId());
final Optional<Permission> permission = theRole.getPermissions()
.stream()
.filter(granted -> privilege.equals(granted.getGrantedPrivilege()))
.findFirst();
return permission.isPresent();
}
/** /**
* Checks if the current subject has a permission granting the provided * Checks if the current subject has a permission granting the provided
* privilege on the provided object or its parent object(s) if the object * {@code privilege} on the provided {@code object} or its parent object(s)
* implements the {@link InheritsPermissions} interface. * if the object implements the {@link InheritsPermissions} interface.
* *
* @param privilege The granted privilege. * @param privilege The granted privilege.
* @param object The object on which the privilege is granted. * @param object The object on which the privilege is granted.
* *
* @return {@code true} if the there is a permission granting the provided * @return {@code true} if the there is a permission granting the provided
* {@code privilege} on the provided {@code subject}. * {@code privilege} on the provided {@code object} to the current
* subject.
*/ */
public boolean isPermitted(final String privilege, final CcmObject object) { public boolean isPermitted(final String privilege, final CcmObject object) {
final boolean result; final boolean result;
@ -98,6 +139,67 @@ public class PermissionChecker {
} }
} }
/**
* Checks if the provided {@code role} has a permission granting the
* provided {@code privilege} on the provided object or its parent object(s)
* if the object implements the {@link InheritsPermissions} interface.
*
* @param privilege The granted privilege.
* @param object The object on which the {@code privilege} is granted.
* @param role The role to check for a permission granting the
* {@code privilege}.
*
* @return {@code true} if the there is a permission granting the provided
* {@code privilege} on the provided {@code object} to the provided
* {@code role}.
*/
public boolean isPermitted(final String privilege,
final CcmObject object,
final Role role) {
if (privilege == null || privilege.trim().isEmpty()) {
throw new IllegalArgumentException(
"Can't check permission null (or empty)");
}
if (role == null) {
throw new IllegalArgumentException(
"Can't check permission for role null.");
}
if (object == null) {
throw new IllegalArgumentException(
"Can verify permissions for object null.");
}
final boolean result;
//Ensure that we have a none detached entity
final Role theRole = roleRepo.findById(role.getRoleId());
final Optional<Permission> permission = theRole.getPermissions()
.stream()
.filter(granted -> granted.getObject() != null)
.filter(granted -> object.equals(granted.getObject()))
.findFirst();
result = permission.isPresent();
if (result) {
return result;
} else if (object instanceof InheritsPermissions) {
if (((InheritsPermissions) object).getParent().isPresent()) {
return isPermitted(
privilege,
((InheritsPermissions) object).getParent().get(),
role);
} else {
return result;
}
} else {
return result;
}
}
/** /**
* Checks if the current subject has a permission granting the provided * Checks if the current subject has a permission granting the provided
* privilege. If the current subject does not have a permission granting the * privilege. If the current subject does not have a permission granting the