Content Sections UI: Edit permissions, dialog for renaming folders

Jens Pelzetter 2021-02-06 20:06:40 +01:00
parent 3562852d18
commit d23b783607
6 changed files with 272 additions and 51 deletions

View File

@ -15,6 +15,7 @@ import org.libreccm.security.Permission;
import org.libreccm.security.PermissionChecker;
import org.libreccm.security.PermissionManager;
import org.libreccm.security.Role;
import org.libreccm.security.RoleRepository;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemL10NManager;
import org.librecms.contentsection.ContentItemManager;
@ -75,9 +76,6 @@ public class DocumentFolderController {
DocumentFolderController.class
);
@Inject
private CmsAdminMessages cmsAdminMessages;
@Inject
private ContentItemManager itemManager;
@ -90,9 +88,6 @@ public class DocumentFolderController {
@Inject
private ContentSectionModel contentSectionModel;
@Inject
private ContentTypeManager contentTypeManager;
@Inject
private ContentTypeRepository contentTypeRepo;
@ -123,6 +118,9 @@ public class DocumentFolderController {
@Inject
private PermissionManager permissionManager;
@Inject
private RoleRepository roleRepo;
@GET
@Path("/")
@AuthorizationRequired
@ -170,6 +168,8 @@ public class DocumentFolderController {
return "org/librecms/ui/contentsection/access-denied.xhtml";
}
contentSectionModel.setSection(section);
final Folder folder;
if (folderPath.isEmpty()) {
folder = section.getRootDocumentsFolder();
@ -417,6 +417,107 @@ public class DocumentFolderController {
);
}
@POST
@Path("/@permissions/{role}/")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String updatePermissions(
@PathParam("sectionIdentifier") final String sectionIdentifier,
@PathParam("role") final String roleParam,
@FormParam("permissions") final List<String> permissions
) {
return updatePermissions(
sectionIdentifier, "", roleParam, permissions
);
}
@POST
@Path("/@permissions/{role}/{folderPath:(.+)?}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String updatePermissions(
@PathParam("sectionIdentifier") final String sectionIdentifier,
@PathParam("folderPath") final String folderPath,
@PathParam("role") final String roleParam,
@FormParam("permissions") final List<String> permissions
) {
final Optional<ContentSection> sectionResult = retrieveContentSection(
sectionIdentifier
);
if (!sectionResult.isPresent()) {
models.put("sectionIdentifier", sectionIdentifier);
return "org/librecms/ui/contentsection/contentsection-not-found.xhtml";
}
final ContentSection section = sectionResult.get();
if (!permissionChecker.isPermitted(
ItemPrivileges.EDIT, section.getRootDocumentsFolder()
)) {
models.put("sectionidentifier", sectionIdentifier);
return "org/librecms/ui/contentsection/access-denied.xhtml";
}
final Folder folder;
if (folderPath.isEmpty()) {
folder = section.getRootDocumentsFolder();
documentFolderModel.setBreadcrumbs(Collections.emptyList());
} else {
final Optional<Folder> folderResult = folderRepo
.findByPath(
section,
folderPath,
FolderType.DOCUMENTS_FOLDER
);
if (folderResult.isPresent()) {
folder = folderResult.get();
documentFolderModel.setBreadcrumbs(buildBreadcrumbs(folderPath));
} else {
models.put("contentSection", section.getLabel());
models.put("folderPath", folderPath);
return "org/librecms/ui/contentsection/documentfolder/documentfolder-not-found.xhtml";
}
}
if (!permissionChecker.isPermitted(ItemPrivileges.ADMINISTER, folder)) {
models.put("sectionidentifier", sectionIdentifier);
models.put("folderPath", folderPath);
return "org/librecms/ui/contentsection/access-denied.xhtml";
}
final Optional<Role> roleResult = roleRepo.findByName(roleParam);
if (!roleResult.isPresent()) {
models.put("role", roleParam);
}
final Role role = roleResult.get();
final List<String> privileges = permissionManager
.listDefiniedPrivileges(ItemPrivileges.class);
privileges
.stream()
.filter(privilege -> permissions.contains(privilege))
.forEach(
privilege -> permissionManager.grantPrivilege(
privilege, role, folder
)
);
privileges
.stream()
.filter(privilege -> !permissions.contains(privilege))
.forEach(
privilege -> permissionManager.revokePrivilege(
privilege, role, folder
)
);
return String.format(
"redirect:/%s/documentfolders/%s",
sectionIdentifier,
folderPath
);
}
private Optional<ContentSection> retrieveContentSection(
final String sectionIdentifier
) {
@ -794,7 +895,8 @@ public class DocumentFolderController {
)
.collect(Collectors.toList());
final PrivilegesGrantedToRoleModel model = new PrivilegesGrantedToRoleModel();
final PrivilegesGrantedToRoleModel model
= new PrivilegesGrantedToRoleModel();
model.setGrantedPrivileges(grantedPrivilges);
model.setGrantee(role.getName());
@ -817,6 +919,8 @@ public class DocumentFolderController {
permission
-> permission.getGrantee().equals(role)
&& permission.getGrantedPrivilege().equals(privilege)
&& permission.getObject().equals(folder)
&& permission.getInheritedFrom() != null
)
);
model.setPrivilege(privilege);
@ -842,4 +946,5 @@ public class DocumentFolderController {
model.setGranted(permissionChecker.isPermitted(privilege, folder));
return model;
}
}

View File

@ -225,7 +225,7 @@
<th>
#{CmsAdminMessages['contentsection.documentfolder.headers.lastedit.label']}
</th>
<th class="text-center" colspan="3">
<th class="text-center" colspan="2">
#{CmsAdminMessages['contentsection.documentfolder.headers.actions.label']}
</th>
</tr>
@ -277,54 +277,57 @@
<td>
<c:if test="#{row.folder and row.permissions.grantedEdit}">
<button class="btn btn-info"
data-target="#rename-folder-#{row.name}-dialog"
data-toggle="modal"
title="#{CmsAdminMessages['contentsection.documentfolder.actions.rename_folder.button.label']}">
<bootstrap:svgIcon icon="pen" />
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.actions.rename_folder.button.label']}</span>
</button>
</c:if>
</td>
<td>
<c:if test="#{row.permissions.grantedAdminister}">
<button class="btn btn-info"
data-toggle="modal"
data-target="#edit-permissions-item-#{row.name}"
title="#{CmsAdminMessages['contentsection.documentfolder.actions.edit_permissions.button.label']}">
<bootstrap:svgIcon icon="shield" />
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.actions.edit_permissions.button.label']}</span>
</button>
<div aria-hidden="true"
aria-labelledby="edit-permisisons-item-#{row.name}-title"
id="edit-permissions-item-#{row.name}"
aria-labelledby="rename-folder-#{row.name}-dialog-title"
class="modal fade"
id="rename-folder-#{row.name}-dialog"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documentfolders/#{DocumentFolderModel.path}/#{row.name}"
class="modal-content">
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documentfolders/@rename/#{row.folderPath}"
class="modal-content"
method="post">
<div class="modal-header">
<h2 class="modal-title"
id="edit-permissions-item-#{row.name}-title">
<c:choose>
<c:when test="#{row.folder}">
#{CmsAdminMessages.getMessage('contentsection.documentfolder.edit_permissions_dialog.title.folder', [row.name])}
</c:when>
<c:otherwise>
#{CmsAdminMessages.getMessage('contentsection.documentfolder.edit_permissions_dialog.title.item', [row.name])}
</c:otherwise>
</c:choose>
<button aria-label="Close"
class="#{CmsAdminMessages['contentsection.documentfolder.edit_permissions_dialog.close']}"
id="rename-folder-#{row.name}-dialog-title">
#{CmsAdminMessages.getMessage('contentsection.documentfolder.rename_folder_dialog.title', [row.folderPath])}
</h2>
<button aria-label="#{CmsMessages['contentsection.documentfolder.rename_folder_dialog.close']}"
class="close"
data-dismiss="modal"
type="button" >
<span aria-hidden="true">&times;</span>
</button>
</h2>
</div>
<div class="modal-body">
<div class="form-group">
<label for="rename-folder-name">
#{CmsAdminMessages['contentsection.documentfolder.rename_folder.name.label']}
</label>
<input aria-describedby="rename-folder-name-help"
class="form-control"
id="rename-folder-name"
name="folderName"
pattern="^([a-zA-Z0-9-_]*)$"
type="text"
value="" />
<small class="form-text text-muted"
id="rename-folder-name-help">
#{CmsAdminMessages['contentsection.documentfolder.new_subfolder.name.help']}
</small>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >#{CmsAdminMessages['contentsection.documentfolder.rename_folder_dialog.close']}</button>
<button class="btn btn-primary"
type="submit">#{CmsAdminMessages['contentsection.documentfolder.rename_folder_dialog.save']}</button>
</div>
</form>
</div>
@ -397,7 +400,7 @@
</nav>
<h2>#{CmsAdminMessages['contentsection.documentfolder.your_permissions.title']}</h2>
<table class="table table-hover">
<table class="table table-hover permissions-table">
<thead class="thead-light">
<tr>
<c:forEach items="#{DocumentFolderModel.privileges}"
@ -412,7 +415,7 @@
<tr>
<c:forEach items="#{DocumentFolderModel.currentUserPermissions}"
var="granted">
<td class="text-center">
<td class="text-center permissions-col">
<c:choose>
<c:when test="#{granted.granted}">
<div class="text-success">
@ -446,6 +449,9 @@
<code>#{CmsAdminMessages['item_permissions.'.concat(privilege)]}</code>
</th>
</c:forEach>
<th>
#{CmsAdminMessages['contentsection.documentfolder.permissions.actions']}
</th>
</tr>
</thead>
<tbody>
@ -455,16 +461,16 @@
<td>#{permissions.grantee}</td>
<c:forEach items="#{permissions.grantedPrivileges}"
var="granted">
<td class="text-center">
<td class="text-center permissions-col">
<c:choose>
<c:when test="#{granted.inherited}">
<div class="text-success">
<div class="text-secondary">
<bootstrap:svgIcon icon="check" />
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.permissions.inherited']}</span>
</div>
</c:when>
<c:when test="#{granted.granted}">
<div class="text-secondary">
<div class="text-success">
<bootstrap:svgIcon icon="check" />
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.permissions.granted']}</span>
</div>
@ -478,6 +484,66 @@
</c:choose>
</td>
</c:forEach>
<td>
<button class="btn btn-info"
data-target="#edit-permissions-for-#{permissions.grantee}"
data-toggle="modal"
type="button">
<bootstrap:svgIcon icon="pen" />
<span>#{CmsAdminMessages['contentsection.documentfolder.permissions.edit']}</span>
</button>
<div aria-hidden="true"
aria-labelledby="edit-permissions-for-#{permissions.grantee}-title"
class="modal fade"
id="edit-permissions-for-#{permissions.grantee}"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documentfolders/@permissions/${permissions.grantee}/#{DocumentFolderModel.path}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="modal-title"
id="edit-permissions-for-#{permissions.grantee}-title">
#{CmsAdminMessages.getMessage('contentsection.documentfolder.permissions.dialog.title', [DocumentFolderModel.path, permissions.grantee])}
</h3>
<button aria-label="#{CmsAdminMessages['contentsection.documentfolder.permissions.dialog.close']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<c:forEach items="#{permissions.grantedPrivileges}"
var="granted">
<div class="form-check">
<input checked="#{granted.granted ? 'checked' : ''}"
class="form-check-input"
id="edit-permissions-for-#{permissions.grantee}-#{granted.privilege}"
name="permissions"
type="checkbox"
value="#{granted.privilege}" />
<label class="form-check-label"
for="edit-permissions-for-#{permissions.grantee}-#{granted.privilege}">
#{CmsAdminMessages['item_permissions.'.concat(granted.privilege)]}
</label>
<c:if test="#{granted.inherited}">
<span class="form-text">(#{CmsAdminMessages['contentsection.documentfolder.permissions.dialog.granted_by_inheritence']})</span>
</c:if>
</div>
</c:forEach>
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >#{CmsAdminMessages['contentsection.documentfolder.permissions.dialog.close']}</button>
<button class="btn btn-primary"
type="submit" >#{CmsAdminMessages['contentsection.documentfolder.permissions.dialog.submit']}</button>
</div>
</form>
</div>
</div>
</td>
</tr>
</c:forEach>
</tbody>

View File

@ -0,0 +1,25 @@
<!DOCTYPE html [<!ENTITY times '&#215;'>]>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:bootstrap="http://xmlns.jcp.org/jsf/composite/components/bootstrap"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:libreccm="http://xmlns.jcp.org/jsf/composite/components/libreccm"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/librecms/ui/content-section/contentsection.xhtml">
<ui:param name="activePage" value="documentFolders" />
<ui:param name="title" value="#{CmsAdminMessages['contentsection.documentfolders.title']}" />
<ui:define name="breadcrumb">
</ui:define>
<ui:define name="main">
<div class="container">
<div class="alert alert-warning">
#{CmsAdminMessages.getMessage("contentsections.role.not_found", [role])}
</div>
</div>
</ui:define>
</ui:composition>
</html>

View File

@ -83,3 +83,14 @@ item_permissions.preview_items=Preview
item_permissions.publish_items=Publish
item_permissions.view_published_items=View
contentsection.documentfolder.your_permissions.title=Your permissions
contentsection.documentfolder.permissions.edit=Edit
contentsection.documentfolder.permissions.actions=Actions
contentsection.documentfolder.permissions.dialog.title=Edit permissions of role {1} for folder {0}
contentsection.documentfolder.permissions.dialog.close=Cancel
contentsection.documentfolder.permissions.dialog.submit=Apply changed permissions
contentsection.documentfolder.permissions.dialog.granted_by_inheritence=Granted by inhertitence
contentsections.role.not_found=Role {0} not found
contentsection.documentfolder.rename_folder_dialog.title=Rename folder {0}
contentsection.documentfolder.rename_folder_dialog.close=Cancel
contentsection.documentfolder.rename_folder_dialog.save=Rename folder
contentsection.documentfolder.rename_folder.name.label=Name

View File

@ -83,3 +83,14 @@ item_permissions.preview_items=Vorschau
item_permissions.publish_items=Publizieren
item_permissions.view_published_items=Ansehen
contentsection.documentfolder.your_permissions.title=Ihre Berechtigungen
contentsection.documentfolder.permissions.edit=Bearbeiten
contentsection.documentfolder.permissions.actions=Aktionen
contentsection.documentfolder.permissions.dialog.title=Berechtigungen der Rolle {1} f\u00fcr Ordner {0} bearbeiten
contentsection.documentfolder.permissions.dialog.close=Abbrechen
contentsection.documentfolder.permissions.dialog.submit=Berechtigungen anwenden
contentsection.documentfolder.permissions.dialog.granted_by_inheritence=Durch \u00fcbergeordnetes Objekt gew\u00e4hrt
contentsections.role.not_found=Rolle {0} nicht gefunden
contentsection.documentfolder.rename_folder_dialog.title=Order {0} umbenennen
contentsection.documentfolder.rename_folder_dialog.close=Abbrechen
contentsection.documentfolder.rename_folder_dialog.save=Ordner umbenennen
contentsection.documentfolder.rename_folder.name.label=Name

View File

@ -77,3 +77,6 @@ table.contentsections-table {
}
}
table.permissions-table td.permissions-col {
font-size: 2em;
}