diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelController.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelController.java new file mode 100644 index 000000000..10f9afeed --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelController.java @@ -0,0 +1,73 @@ +/* + * 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 com.arsdigita.cms.ui.folder; + +import com.arsdigita.bebop.tree.TreeNode; + +import org.librecms.contentsection.Folder; +import org.librecms.contentsection.FolderRepository; + +import java.util.Iterator; +import java.util.Optional; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class FolderTreeModelController { + + @Inject + private FolderRepository folderRepo; + + private Folder getCurrentFolder(final TreeNode node) { + if (node == null) { + throw new IllegalArgumentException( + "Can't get current folder from null."); + } + + final Folder current = (Folder) node.getElement(); + + final Optional folder = folderRepo.findById(current + .getObjectId()); + if (folder.isPresent()) { + return folder.get(); + } else { + throw new IllegalArgumentException(String.format( + "The provided TreeNode contains a folder (%s) which is not in " + + "the database.", + folder.toString())); + } + } + + @Transactional(Transactional.TxType.REQUIRED) + public boolean hasChildren(final TreeNode node) { + return getCurrentFolder(node).getSubCategories().isEmpty(); + } + + @Transactional(Transactional.TxType.REQUIRED) + public Iterator getChildren(final TreeNode node) { + return getCurrentFolder(node).getSubFolders().iterator(); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSDirectPermissionsTableRow.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSDirectPermissionsTableRow.java new file mode 100644 index 000000000..7eb91b9dd --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSDirectPermissionsTableRow.java @@ -0,0 +1,69 @@ +/* + * 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 com.arsdigita.cms.ui.permissions; + +/** + * + * @author Jens Pelzetter + */ +class CMSDirectPermissionsTableRow { + + private long granteeKey; + + private String granteeName; + + private boolean permitted; + + private UserPrivilegeKey userPrivilegeKey; + + public long getGranteeKey() { + return granteeKey; + } + + protected void setGranteeKey(final long granteeKey) { + this.granteeKey = granteeKey; + } + + public String getGranteeName() { + return granteeName; + } + + protected void setGranteeName(final String granteeName) { + this.granteeName = granteeName; + } + + public boolean isPermitted() { + return permitted; + } + + protected void setPermitted(final boolean permitted) { + this.permitted = permitted; + } + + public UserPrivilegeKey getUserPrivilegeKey() { + return userPrivilegeKey; + } + + protected void setUserPrivilegeKey(final UserPrivilegeKey userPrivilegeKey) { + this.userPrivilegeKey = userPrivilegeKey; + } + + + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableColumn.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableColumn.java new file mode 100644 index 000000000..f623dea55 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableColumn.java @@ -0,0 +1,99 @@ +/* + * 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 com.arsdigita.cms.ui.permissions; + +import java.util.Objects; + +/** + * + * @author Jens Pelzetter + */ +class CMSPermissionsTableColumn { + + private String privilege; + private boolean permitted; + + public String getPrivilege() { + return privilege; + } + + protected void setPrivilege(final String privilege) { + this.privilege = privilege; + } + + public boolean isPermitted() { + return permitted; + } + + protected void setPermitted(final boolean permitted) { + this.permitted = permitted; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 83 * hash + Objects.hashCode(privilege); + hash = 83 * hash + (permitted ? 1 : 0); + return hash; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof CMSPermissionsTableColumn)) { + return false; + } + final CMSPermissionsTableColumn other + = (CMSPermissionsTableColumn) obj; + if (!other.canEqual(this)) { + return false; + } + + if (permitted != other.isPermitted()) { + return false; + } + return Objects.equals(privilege, other.getPrivilege()); + } + + public boolean canEqual(final Object obj) { + return obj instanceof CMSPermissionsTableColumn; + } + + @Override + public final String toString() { + return toString(""); + } + + public String toString(final String data) { + return String.format("%s{ " + + "privilege = \"%s\", " + + "permitted = %b%s" + + " }", + super.toString(), + privilege, + permitted, + data); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableController.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableController.java new file mode 100644 index 000000000..bd6e0d23a --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableController.java @@ -0,0 +1,106 @@ +/* + * 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 com.arsdigita.cms.ui.permissions; + +import com.arsdigita.cms.CMS; + +import org.libreccm.core.CcmObject; +import org.libreccm.security.Permission; +import org.libreccm.security.PermissionChecker; +import org.libreccm.security.PermissionManager; +import org.libreccm.security.Role; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.privileges.ItemPrivileges; + +import java.util.List; +import java.util.stream.Collectors; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +class CMSPermissionsTableController { + + @Inject + private PermissionManager permissionManager; + + @Inject + private PermissionChecker permissionChecker; + + @Transactional(Transactional.TxType.REQUIRED) + public List buildDirectPermissionsRows( + final CcmObject object) { + + final List roles = CMS.getContext().getContentSection().getRoles(); + + return roles.stream() + .map(role -> buildRow(role, object)) + .sorted((row1, row2) -> { + return row1.getRoleName().compareTo(row2.getRoleName()); + }) + .collect(Collectors.toList()); + } + + private CMSPermissionsTableRow buildRow(final Role role, + final CcmObject object) { + final List privileges = permissionManager + .listDefiniedPrivileges(ItemPrivileges.class); + + final List columns = privileges.stream() + .map(privilege -> buildColumn(role, object, privilege)) + .collect(Collectors.toList()); + + final CMSPermissionsTableRow row = new CMSPermissionsTableRow(); + row.setRoleName(role.getName()); + row.setColumns(columns); + + return row; + } + + private CMSPermissionsTableColumn buildColumn(final Role role, + final CcmObject object, + final String privilege) { + final CMSPermissionsTableColumn column = new CMSPermissionsTableColumn(); + + column.setPrivilege(privilege); + column.setPermitted(permissionChecker.isPermitted(privilege, + object, + role)); + + return column; + + } + + @Transactional(Transactional.TxType.REQUIRED) + public void togglePermission(final CcmObject object, + final String privilege, + final Role role) { + if (permissionChecker.isPermitted(privilege, object, role)) { + permissionManager.revokePrivilege(privilege, role, object); + } else { + permissionManager.grantPrivilege(privilege, role, object); + } + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableModel.java new file mode 100644 index 000000000..2c2fe9012 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableModel.java @@ -0,0 +1,77 @@ +/* + * 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 com.arsdigita.cms.ui.permissions; + +import com.arsdigita.bebop.table.TableModel; + +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.core.CcmObject; +import org.libreccm.security.PermissionManager; +import org.librecms.contentsection.privileges.ItemPrivileges; + +import java.util.Iterator; + +/** + * + * @author Jens Pelzetter + */ +class CMSPermissionsTableModel implements TableModel { + + private final Iterator iterator; + private CMSPermissionsTableRow currentRow; + + public CMSPermissionsTableModel(final CcmObject object) { + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final CMSPermissionsTableController controller = cdiUtil.findBean( + CMSPermissionsTableController.class); + + iterator = controller.buildDirectPermissionsRows(object).iterator(); + } + + @Override + public int getColumnCount() { + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final PermissionManager permissionManager = cdiUtil.findBean( + PermissionManager.class); + + return permissionManager.listDefiniedPrivileges(ItemPrivileges.class) + .size(); + } + + @Override + public boolean nextRow() { + if (iterator.hasNext()) { + currentRow = iterator.next(); + return true; + } else { + return false; + } + } + + @Override + public Object getElementAt(final int columnIndex) { + return currentRow.getColumns().get(columnIndex); + } + + @Override + public Object getKeyAt(final int columnIndex) { + return currentRow.getColumns().get(columnIndex).getPrivilege(); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableModelBuilder.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableModelBuilder.java new file mode 100644 index 000000000..f7a0505ee --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableModelBuilder.java @@ -0,0 +1,47 @@ +/* + * 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 com.arsdigita.cms.ui.permissions; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.TableModelBuilder; +import com.arsdigita.util.LockableImpl; + +import org.libreccm.core.CcmObject; + +/** + * + * @author Jens Pelzetter + */ +class CMSPermissionsTableModelBuilder extends LockableImpl + implements TableModelBuilder { + + private final CcmObject object; + + public CMSPermissionsTableModelBuilder(final CcmObject object) { + this.object = object; + } + + @Override + public TableModel makeModel(final Table table, final PageState state) { + return new CMSPermissionsTableModel(object); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableRow.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableRow.java new file mode 100644 index 000000000..4f09a35c3 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTableRow.java @@ -0,0 +1,105 @@ +/* + * 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 com.arsdigita.cms.ui.permissions; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * + * @author Jens Pelzetter + */ +class CMSPermissionsTableRow { + + private String roleName; + + private List columns; + + public String getRoleName() { + return roleName; + } + + protected void setRoleName(final String roleName) { + this.roleName = roleName; + } + + public List getColumns() { + return Collections.unmodifiableList(columns); + } + + protected void setColumns(final List columns) { + this.columns = columns; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 79 * hash + Objects.hashCode(roleName); + hash = 79 * hash + Objects.hashCode(columns); + return hash; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof CMSPermissionsTableRow)) { + return false; + } + final CMSPermissionsTableRow other = (CMSPermissionsTableRow) obj; + if (!other.canEqual(this)) { + return false; + } + + if (!Objects.equals(roleName, other.getRoleName())) { + return false; + } + if (Objects.equals(columns, other.getColumns())) { + } else { + return false; + } + return true; + } + + public boolean canEqual(final Object obj) { + return obj instanceof CMSPermissionsTableRow; + } + + @Override + public final String toString() { + return toString(""); + } + + public String toString(final String data) { + return String.format("%s{ " + + "roleName = \"%s\", " + + "columns = %s%s" + + " }", + super.toString(), + roleName, + Objects.toString(columns), + data); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTables.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTables.java index 2d7c399a8..08e3d9fdb 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTables.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/CMSPermissionsTables.java @@ -335,12 +335,11 @@ class CMSPermissionsTables { private final List userPrivileges = new ArrayList<>(); - private final Iterator iterator; + private Iterator iterator; private Permission currentPermission; public DirectPermissionsTableModel(final CcmObject object) { // this.iterator = permissions.iterator(); - throw new UnsupportedOperationException(); } @Override diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/PermissionStatus.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/PermissionStatus.java new file mode 100644 index 000000000..bb422dc54 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/PermissionStatus.java @@ -0,0 +1,67 @@ +/* + * 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 com.arsdigita.cms.ui.permissions; + +import org.libreccm.core.CcmObject; +import org.libreccm.security.Role; + +/** + * + * Structure to hold a permission and its current grant state + * + * + * + * @author Jens Pelzetter + */ +final class PermissionStatus { + + private final boolean granted; + private final CcmObject object; + private final Role role; + private final String privilege; + + PermissionStatus(final String privilege, + final CcmObject object, + final Role role, + final boolean granted) { + + this.granted = granted; + + this.object = object; + this.role = role; + this.privilege = privilege; + } + + boolean isGranted() { + return granted; + } + + CcmObject getObject() { + return object; + } + + Role getRole() { + return role; + } + + String getPrivilege() { + return privilege; + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/UserPrivilegeKey.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/UserPrivilegeKey.java new file mode 100644 index 000000000..c960b76db --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/permissions/UserPrivilegeKey.java @@ -0,0 +1,84 @@ +/* + * 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 com.arsdigita.cms.ui.permissions; + +/** + * Utility class to encode a user privilege in the bebop table. + * + * @author Jens Pelzetter + */ +final class UserPrivilegeKey { + + private final String objectId; + private final String granteeId; + private final String privilege; + private final boolean granted; + + public UserPrivilegeKey(final Long objectId, + final Long granteeId, + final String privilege, + final boolean granted) { + this.objectId = objectId.toString(); + this.granteeId = granteeId.toString(); + this.privilege = privilege; + this.granted = granted; + } + + @Override + public String toString() { + return String.format("%s{ %s }", + super.toString(), + String.join(".", privilege, + objectId, + granteeId, + Boolean.toString(granted))); + } + + /** + * Decodes the information in a key into the helper class + * + * @see PermissionStatus + */ + static PermissionStatus undescribe(final String key) { + + final int i = key.indexOf("."); + final int j = key.indexOf(".", i + 1); + final int k = key.lastIndexOf("."); + + final String privilege = key.substring(0, i); + final Long oID = Long.parseLong(key.substring(i + 1, j)); + final Long gID = Long.parseLong(key.substring(j + 1, k)); + + boolean granted = false; + final CMSUserObjectStruct uos; + try { + granted = Boolean.parseBoolean(key.substring(k + 1, k + 2)); + uos = new CMSUserObjectStruct(gID, oID); + } catch (NumberFormatException ex) { + // cannot decode + throw new IllegalArgumentException(ex.getMessage()); + } + + return new PermissionStatus(privilege, + uos.getObject(), + uos.getRole(), + granted); + } + +}