Some refactoring, and permissions checks

Former-commit-id: 65ef6af336
pull/10/head
Jens Pelzetter 2021-02-03 20:26:22 +01:00
parent af0b0c12a0
commit 8aa371571d
10 changed files with 612 additions and 302 deletions

View File

@ -22,7 +22,7 @@ import org.librecms.contentsection.ContentItem;
/** /**
* Constants for privileges allowing actions on the items of a content section. * Constants for privileges allowing actions on the items of a content section.
* All privileges defined in this class can either be assigned for the complete * All privileges defined in this class can either be assigned for the complete
* {@link ContentSection} or for a specific documents/items {@link Folder}. * {@link ContentSection} or for a specific documents/items {@link Folder}.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
@ -33,45 +33,53 @@ public final class ItemPrivileges {
* Allows the user to edit the permissions for items. * Allows the user to edit the permissions for items.
*/ */
public static final String ADMINISTER = "administer_items"; public static final String ADMINISTER = "administer_items";
/**
* Allows the user to approve {@link ContentItem}s.
*/
public static final String APPROVE = "approve_items";
/**
* Allows the user to publish, republish and unpublish {@link ContentItem}.
*/
public static final String PUBLISH = "publish_items";
/**
* Allows the user to categorise {@link ContentItem}s.
*/
public static final String CATEGORIZE = "categorize_items";
/**
* Allows the user to create new {@link ContentItem}s.
*/
public static final String CREATE_NEW = "create_new_items";
/**
* Allows the user to delete {@link ContentItem}s.
*/
public static final String DELETE = "delete_items";
/**
* Allows the user to edit existing {@link ContentItem}s.
*/
public static final String EDIT = "edit_items";
/**
* Allows to user to view the draft version of {@link ContentItem}.
*/
public static final String PREVIEW = "preview_items";
/**
* Allows the user to view the live version of {@link ContentItems}.
*/
public static final String VIEW_PUBLISHED = "view_published_items";
/** /**
* Allows the user to apply another {@link Workflow} than the default one to * Allows the user to apply another {@link Workflow} than the default one to
* an {@link ContentItem}. * an {@link ContentItem}.
*/ */
public static final String APPLY_ALTERNATE_WORKFLOW public static final String APPLY_ALTERNATE_WORKFLOW
= "apply_alternate_workflow"; = "apply_alternate_workflow";
/**
* Allows the user to approve {@link ContentItem}s.
*/
public static final String APPROVE = "approve_items";
/**
* Allows the user to categorise {@link ContentItem}s.
*/
public static final String CATEGORIZE = "categorize_items";
/**
* Allows the user to create new {@link ContentItem}s.
*/
public static final String CREATE_NEW = "create_new_items";
/**
* Allows the user to delete {@link ContentItem}s.
*/
public static final String DELETE = "delete_items";
/**
* Allows the user to edit existing {@link ContentItem}s.
*/
public static final String EDIT = "edit_items";
/**
* Allows to user to view the draft version of {@link ContentItem}.
*/
public static final String PREVIEW = "preview_items";
/**
* Allows the user to publish, republish and unpublish {@link ContentItem}.
*/
public static final String PUBLISH = "publish_items";
/**
* Allows the user to view the live version of {@link ContentItems}.
*/
public static final String VIEW_PUBLISHED = "view_published_items";
private ItemPrivileges() { private ItemPrivileges() {
//Nothing //Nothing

View File

@ -5,7 +5,6 @@
*/ */
package org.librecms.ui.contentsections; package org.librecms.ui.contentsections;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.libreccm.api.Identifier; import org.libreccm.api.Identifier;
@ -145,144 +144,92 @@ public class DocumentFolderController {
@QueryParam("maxResults") @DefaultValue("20") final int maxResults @QueryParam("maxResults") @DefaultValue("20") final int maxResults
) { ) {
final long start = System.currentTimeMillis(); final long start = System.currentTimeMillis();
final Identifier identifier = identifierParser.parseIdentifier( final Optional<ContentSection> sectionResult = retrieveContentSection(
sectionIdentifier sectionIdentifier
); );
final Optional<ContentSection> sectionResult; LOGGER.info("Retrieved content section in {} ms",
switch (identifier.getType()) { System.currentTimeMillis() - start
case ID: );
sectionResult = sectionRepo.findById(
Long.parseLong(identifier.getIdentifier())
);
break;
case UUID:
sectionResult = sectionRepo.findByUuid(identifier
.getIdentifier());
break;
default:
sectionResult = sectionRepo.findByLabel(identifier
.getIdentifier());
break;
}
LOGGER.info("Retrieved content section in {} ms", System
.currentTimeMillis() - start);
if (sectionResult.isPresent()) { if (!sectionResult.isPresent()) {
final ContentSection section = sectionResult.get();
final long permissionCheckStart = System.currentTimeMillis();
if (permissionChecker.isPermitted(
ItemPrivileges.EDIT, section.getRootDocumentsFolder()
)) {
contentSectionModel.setSection(section);
LOGGER.info(
"Checked in permisisons in {} ms.",
System.currentTimeMillis() - permissionCheckStart
);
final Folder folder;
if (folderPath.isBlank()) {
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();
if (!permissionChecker.isPermitted(
ItemPrivileges.EDIT, folder
)) {
models.put("sectionidentifier", sectionIdentifier);
models.put("folderPath", folderPath);
return "org/librecms/ui/contentsection/access-denied.xhtml";
}
final List<DocumentFolderBreadcrumbModel> breadcrumbs
= new ArrayList<>();
final List<String> tokens = Arrays
.stream(folderPath.split("/"))
.filter(token -> !token.isEmpty())
.collect(Collectors.toList());
for (final String token : tokens) {
final String path = breadcrumbs
.stream()
.map(DocumentFolderBreadcrumbModel::getPathToken)
.collect(Collectors.joining("/"));
final DocumentFolderBreadcrumbModel breadcrumb
= new DocumentFolderBreadcrumbModel();
breadcrumb.setPath(path);
breadcrumb.setPathToken(token);
breadcrumbs.add(breadcrumb);
}
breadcrumbs
.get(breadcrumbs.size() - 1)
.setCurrentFolder(true);
documentFolderModel.setBreadcrumbs(breadcrumbs);
} else {
models.put("contentSection", section.getLabel());
models.put("folderPath", folderPath);
return "org/librecms/ui/contentsection/documentfolder/documentfolder-not-found.xhtml";
}
}
final long objectsStart = System.currentTimeMillis();
final List<DocumentFolderEntry> folderEntries = folderRepo
.getDocumentFolderEntries(
folder,
firstResult,
maxResults,
filterTerm
);
LOGGER.info(
"Retrieved objects in {} ms",
System.currentTimeMillis() - objectsStart
);
documentFolderModel.setCount(
folderRepo.countDocumentFolderEntries(folder, filterTerm)
);
documentFolderModel.setFirstResult(firstResult);
documentFolderModel.setMaxResults(maxResults);
LOGGER.info(
"Retrieved and counted objects in {} ms",
System.currentTimeMillis() - objectsStart
);
final List<FolderTreeNode> folderTree = buildFolderTree(
section, folder
);
contentSectionModel.setFolders(folderTree);
final long rowsStart = System.currentTimeMillis();
documentFolderModel.setRows(
folderEntries
.stream()
.map(entry -> buildRowModel(section, entry))
.collect(Collectors.toList())
);
LOGGER.info(
"Build rows in {} ms.",
System.currentTimeMillis() - rowsStart
);
documentFolderModel.setPath(folderPath);
documentFolderModel.setCanCreateSubFolders(
permissionChecker.isPermitted(
ItemPrivileges.CREATE_NEW, folder
)
);
return "org/librecms/ui/contentsection/documentfolder/documentfolder.xhtml";
} else {
models.put("sectionidentifier", sectionIdentifier);
return "org/librecms/ui/contentsection/access-denied.xhtml";
}
} else {
models.put("sectionIdentifier", sectionIdentifier); models.put("sectionIdentifier", sectionIdentifier);
return "org/librecms/ui/contentsection/contentsection-not-found.xhtml"; 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.EDIT, folder)) {
models.put("sectionidentifier", sectionIdentifier);
models.put("folderPath", folderPath);
return "org/librecms/ui/contentsection/access-denied.xhtml";
}
final List<DocumentFolderEntry> folderEntries = folderRepo
.getDocumentFolderEntries(
folder,
firstResult,
maxResults,
filterTerm
);
documentFolderModel.setCount(
folderRepo.countDocumentFolderEntries(folder, filterTerm)
);
documentFolderModel.setFirstResult(firstResult);
documentFolderModel.setMaxResults(maxResults);
final List<FolderTreeNode> folderTree = buildFolderTree(
section, folder
);
contentSectionModel.setFolders(folderTree);
documentFolderModel.setRows(
folderEntries
.stream()
.map(entry -> buildRowModel(section, entry))
.collect(Collectors.toList())
);
documentFolderModel.setPath(folderPath);
documentFolderModel.setCanCreateSubFolders(
permissionChecker.isPermitted(
ItemPrivileges.CREATE_NEW, folder
)
);
documentFolderModel.setCanCreateItems(
permissionChecker.isPermitted(
ItemPrivileges.CREATE_NEW, folder
)
);
return "org/librecms/ui/contentsection/documentfolder/documentfolder.xhtml";
} }
@GET @GET
@ -399,10 +346,64 @@ public class DocumentFolderController {
@PathParam("sectionIdentifier") final String sectionIdentifier, @PathParam("sectionIdentifier") final String sectionIdentifier,
@PathParam("parentFolderPath") final String parentFolderPath, @PathParam("parentFolderPath") final String parentFolderPath,
@FormParam("folderName") final String folderName @FormParam("folderName") final String folderName
) {
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 parentFolder;
if (parentFolderPath.isEmpty()) {
parentFolder = section.getRootDocumentsFolder();
} else {
final Optional<Folder> parentFolderResult = folderRepo
.findByPath(section, parentFolderPath,
FolderType.DOCUMENTS_FOLDER);
if (parentFolderResult.isPresent()) {
parentFolder = parentFolderResult.get();
} else {
models.put("contentSection", section.getLabel());
models.put("folderPath", parentFolderPath);
return "org/librecms/ui/contentsection/documentfolder/documentfolder-not-found.xhtml";
}
}
if (!permissionChecker.isPermitted(
ItemPrivileges.CREATE_NEW, parentFolder
)) {
models.put("sectionidentifier", sectionIdentifier);
models.put("folderPath", parentFolderPath);
return "org/librecms/ui/contentsection/access-denied.xhtml";
}
folderManager.createFolder(folderName, parentFolder);
return String.format(
"redirect:/%s/documentfolders/%s",
sectionIdentifier,
parentFolderPath
);
}
private Optional<ContentSection> retrieveContentSection(
final String sectionIdentifier
) { ) {
final Identifier identifier = identifierParser.parseIdentifier( final Identifier identifier = identifierParser.parseIdentifier(
sectionIdentifier sectionIdentifier
); );
final Optional<ContentSection> sectionResult; final Optional<ContentSection> sectionResult;
switch (identifier.getType()) { switch (identifier.getType()) {
case ID: case ID:
@ -419,57 +420,8 @@ public class DocumentFolderController {
.getIdentifier()); .getIdentifier());
break; break;
} }
return sectionResult;
if (sectionResult.isPresent()) {
final ContentSection section = sectionResult.get();
if (!permissionChecker.isPermitted(
ItemPrivileges.EDIT, section.getRootDocumentsFolder()
)) {
models.put("sectionidentifier", sectionIdentifier);
models.put("folderPath", parentFolderPath);
return "org/librecms/ui/contentsection/access-denied.xhtml";
}
final Folder parentFolder;
if (parentFolderPath.isEmpty()) {
parentFolder = section.getRootDocumentsFolder();
} else {
final Optional<Folder> parentFolderResult = folderRepo
.findByPath(section, parentFolderPath,
FolderType.DOCUMENTS_FOLDER);
if (parentFolderResult.isPresent()) {
parentFolder = parentFolderResult.get();
} else {
models.put("contentSection", section.getLabel());
models.put("folderPath", parentFolderPath);
return "org/librecms/ui/contentsection/documentfolder/documentfolder-not-found.xhtml";
}
}
if (permissionChecker.isPermitted(
ItemPrivileges.CREATE_NEW, parentFolder
)) {
folderManager.createFolder(folderName, parentFolder);
return String.format(
"redirect:/%s/documentfolders/%s",
sectionIdentifier,
parentFolderPath
);
} else {
models.put("sectionidentifier", sectionIdentifier);
models.put("folderPath", parentFolderPath);
return "org/librecms/ui/contentsection/access-denied.xhtml";
}
} else {
models.put("sectionIdentifier", sectionIdentifier);
return "org/librecms/ui/contentsection/contentsection-not-found.xhtml";
}
} }
private List<FolderTreeNode> buildFolderTree( private List<FolderTreeNode> buildFolderTree(
final ContentSection section, final Folder currentFolder final ContentSection section, final Folder currentFolder
@ -515,6 +467,7 @@ public class DocumentFolderController {
node.setPath(folderPath); node.setPath(folderPath);
node.setOpen(currentFolderPath.startsWith(folderPath)); node.setOpen(currentFolderPath.startsWith(folderPath));
node.setSelected(currentFolderPath.equals(folderPath)); node.setSelected(currentFolderPath.equals(folderPath));
node.setPermissions(buildItemPermissionsModel(folder));
node.setSubFolders( node.setSubFolders(
folder folder
.getSubFolders() .getSubFolders()
@ -534,6 +487,32 @@ public class DocumentFolderController {
return node; return node;
} }
private List<DocumentFolderBreadcrumbModel> buildBreadcrumbs(
final String folderPath
) {
final List<DocumentFolderBreadcrumbModel> breadcrumbs
= new ArrayList<>();
final List<String> tokens = Arrays
.stream(folderPath.split("/"))
.filter(token -> !token.isEmpty())
.collect(Collectors.toList());
for (final String token : tokens) {
final String path = breadcrumbs
.stream()
.map(DocumentFolderBreadcrumbModel::getPathToken)
.collect(Collectors.joining("/"));
final DocumentFolderBreadcrumbModel breadcrumb
= new DocumentFolderBreadcrumbModel();
breadcrumb.setPath(path);
breadcrumb.setPathToken(token);
breadcrumbs.add(breadcrumb);
}
breadcrumbs
.get(breadcrumbs.size() - 1)
.setCurrentFolder(true);
return breadcrumbs;
}
private DocumentFolderRowModel buildRowModel( private DocumentFolderRowModel buildRowModel(
final ContentSection section, final DocumentFolderEntry entry final ContentSection section, final DocumentFolderEntry entry
) { ) {
@ -575,6 +554,7 @@ public class DocumentFolderController {
"org.librecms.CmsAdminMessages" "org.librecms.CmsAdminMessages"
).getText("contentsection.documentfolder.types.folder") ).getText("contentsection.documentfolder.types.folder")
); );
row.setPermissions(buildItemPermissionsModel(folder));
} else { } else {
final ContentItem contentItem = itemRepo final ContentItem contentItem = itemRepo
.findById(entry.getEntryId()) .findById(entry.getEntryId())
@ -635,8 +615,9 @@ public class DocumentFolderController {
); );
row.setType( row.setType(
contentTypeRepo contentTypeRepo
.findByContentSectionAndClass(section, contentItem .findByContentSectionAndClass(
.getClass()) section, contentItem.getClass()
)
.map(ContentType::getLabel) .map(ContentType::getLabel)
.map( .map(
label -> globalizationHelper label -> globalizationHelper
@ -645,10 +626,125 @@ public class DocumentFolderController {
) )
).orElse("?") ).orElse("?")
); );
row.setPermissions(buildItemPermissionsModel(contentItem));
} }
return row; return row;
} }
private ItemPermissionsModel buildItemPermissionsModel(
final Folder folder
) {
final ItemPermissionsModel model = new ItemPermissionsModel();
model.setGrantedAdminister(
permissionChecker.isPermitted(
ItemPrivileges.ADMINISTER, folder
)
);
model.setGrantedApplyAlternateWorkflow(
permissionChecker.isPermitted(
ItemPrivileges.APPLY_ALTERNATE_WORKFLOW, folder
)
);
model.setGrantedApprove(
permissionChecker.isPermitted(
ItemPrivileges.APPROVE, folder
)
);
model.setGrantedCategorize(
permissionChecker.isPermitted(
ItemPrivileges.CATEGORIZE, folder
)
);
model.setGrantedCreateNew(
permissionChecker.isPermitted(
ItemPrivileges.CREATE_NEW, folder
)
);
model.setGrantedDelete(
permissionChecker.isPermitted(
ItemPrivileges.DELETE, folder
)
);
model.setGrantedEdit(
permissionChecker.isPermitted(
ItemPrivileges.EDIT, folder
)
);
model.setGrantedPreview(
permissionChecker.isPermitted(
ItemPrivileges.PREVIEW, folder
)
);
model.setGrantedPublish(
permissionChecker.isPermitted(
ItemPrivileges.PUBLISH, folder
)
);
model.setGrantedViewPublished(
permissionChecker.isPermitted(
ItemPrivileges.VIEW_PUBLISHED, folder
)
);
return model;
}
private ItemPermissionsModel buildItemPermissionsModel(
final ContentItem item
) {
final ItemPermissionsModel model = new ItemPermissionsModel();
model.setGrantedAdminister(
permissionChecker.isPermitted(
ItemPrivileges.ADMINISTER, item
)
);
model.setGrantedApplyAlternateWorkflow(
permissionChecker.isPermitted(
ItemPrivileges.APPLY_ALTERNATE_WORKFLOW, item
)
);
model.setGrantedApprove(
permissionChecker.isPermitted(
ItemPrivileges.APPROVE, item
)
);
model.setGrantedCategorize(
permissionChecker.isPermitted(
ItemPrivileges.CATEGORIZE, item
)
);
model.setGrantedCreateNew(
permissionChecker.isPermitted(
ItemPrivileges.CREATE_NEW, item
)
);
model.setGrantedDelete(
permissionChecker.isPermitted(
ItemPrivileges.DELETE, item
)
);
model.setGrantedEdit(
permissionChecker.isPermitted(
ItemPrivileges.EDIT, item
)
);
model.setGrantedPreview(
permissionChecker.isPermitted(
ItemPrivileges.PREVIEW, item
)
);
model.setGrantedPublish(
permissionChecker.isPermitted(
ItemPrivileges.PUBLISH, item
)
);
model.setGrantedViewPublished(
permissionChecker.isPermitted(
ItemPrivileges.VIEW_PUBLISHED, item
)
);
return model;
}
} }

View File

@ -34,7 +34,8 @@ public class DocumentFolderModel {
private String path; private String path;
private boolean canCreateSubFolders; private boolean canCreateSubFolders;
private boolean canCreateItems;
public long getCount() { public long getCount() {
return count; return count;
@ -102,4 +103,12 @@ public class DocumentFolderModel {
this.canCreateSubFolders = canCreateSubFolders; this.canCreateSubFolders = canCreateSubFolders;
} }
public boolean isCanCreateItems() {
return canCreateItems;
}
protected void setCanCreateItems(final boolean canCreateItems) {
this.canCreateItems = canCreateItems;
}
} }

View File

@ -35,6 +35,8 @@ public class DocumentFolderRowModel {
private String title; private String title;
private String type; private String type;
private ItemPermissionsModel permissions;
public String getCreated() { public String getCreated() {
return created; return created;
@ -128,4 +130,14 @@ public class DocumentFolderRowModel {
this.type = type; this.type = type;
} }
public ItemPermissionsModel getPermissions() {
return permissions;
}
protected void setPermissions(
final ItemPermissionsModel permissions
) {
this.permissions = permissions;
}
} }

View File

@ -5,6 +5,7 @@
*/ */
package org.librecms.ui.contentsections; package org.librecms.ui.contentsections;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -12,21 +13,23 @@ import java.util.List;
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
public class FolderTreeNode { public class FolderTreeNode {
private long folderId; private long folderId;
private String uuid; private String uuid;
private String name; private String name;
private String path; private String path;
private List<FolderTreeNode> subFolders; private List<FolderTreeNode> subFolders;
private boolean open; private boolean open;
private boolean selected; private boolean selected;
private ItemPermissionsModel permissions;
public long getFolderId() { public long getFolderId() {
return folderId; return folderId;
} }
@ -60,7 +63,7 @@ public class FolderTreeNode {
} }
public List<FolderTreeNode> getSubFolders() { public List<FolderTreeNode> getSubFolders() {
return subFolders; return Collections.unmodifiableList(subFolders);
} }
public void setSubFolders(final List<FolderTreeNode> subFolders) { public void setSubFolders(final List<FolderTreeNode> subFolders) {
@ -82,7 +85,15 @@ public class FolderTreeNode {
public void setSelected(final boolean selected) { public void setSelected(final boolean selected) {
this.selected = selected; this.selected = selected;
} }
public ItemPermissionsModel getPermissions() {
return permissions;
}
public void setPermissions(
final ItemPermissionsModel permissions
) {
this.permissions = permissions;
}
} }

View File

@ -0,0 +1,115 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.librecms.ui.contentsections;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ItemPermissionsModel {
private boolean grantedAdminister;
private boolean grantedApplyAlternateWorkflow;
private boolean grantedApprove;
private boolean grantedCategorize;
private boolean grantedCreateNew;
private boolean grantedDelete;
private boolean grantedEdit;
private boolean grantedPreview;
private boolean grantedPublish;
private boolean grantedViewPublished;
public boolean isGrantedAdminister() {
return grantedAdminister;
}
public void setGrantedAdminister(final boolean grantedAdminister) {
this.grantedAdminister = grantedAdminister;
}
public boolean isGrantedApplyAlternateWorkflow() {
return grantedApplyAlternateWorkflow;
}
public void setGrantedApplyAlternateWorkflow(
boolean grantedApplyAlternateWorkflow) {
this.grantedApplyAlternateWorkflow = grantedApplyAlternateWorkflow;
}
public boolean isGrantedApprove() {
return grantedApprove;
}
public void setGrantedApprove(final boolean grantedApprove) {
this.grantedApprove = grantedApprove;
}
public boolean isGrantedCategorize() {
return grantedCategorize;
}
public void setGrantedCategorize(final boolean grantedCategorize) {
this.grantedCategorize = grantedCategorize;
}
public boolean isGrantedCreateNew() {
return grantedCreateNew;
}
public void setGrantedCreateNew(final boolean grantedCreateNew) {
this.grantedCreateNew = grantedCreateNew;
}
public boolean isGrantedDelete() {
return grantedDelete;
}
public void setGrantedDelete(final boolean grantedDelete) {
this.grantedDelete = grantedDelete;
}
public boolean isGrantedEdit() {
return grantedEdit;
}
public void setGrantedEdit(final boolean grantedEdit) {
this.grantedEdit = grantedEdit;
}
public boolean isGrantedPreview() {
return grantedPreview;
}
public void setGrantedPreview(final boolean grantedPreview) {
this.grantedPreview = grantedPreview;
}
public boolean isGrantedPublish() {
return grantedPublish;
}
public void setGrantedPublish(final boolean grantedPublish) {
this.grantedPublish = grantedPublish;
}
public boolean isGrantedViewPublished() {
return grantedViewPublished;
}
public void setGrantedViewPublished(final boolean grantedViewPublished) {
this.grantedViewPublished = grantedViewPublished;
}
}

View File

@ -19,8 +19,16 @@
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.foldersnav.subfolders.expand']} <span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.foldersnav.subfolders.expand']}
</span> </span>
</button> </button>
<a class="pl-0" <c:choose>
href="#{basePath}#{folder.path}">#{folder.name}</a> <c:when test="#{folder.permissions.grantedEdit}">
<a class="pl-0"
href="#{basePath}#{folder.path}">#{folder.name}</a>
</c:when>
<c:otherwise>
<span>#{folder.name}</span>
</c:otherwise>
</c:choose>
</div> </div>
<ul class="border-0 #{!folder.open ? 'collapse' : 'collapse.show'} list-group" <ul class="border-0 #{!folder.open ? 'collapse' : 'collapse.show'} list-group"
id="#{folder.name}-subfolders"> id="#{folder.name}-subfolders">

View File

@ -114,70 +114,94 @@
${CmsAdminMessages.getMessage("contentsection.documentfolder.pageof", [DocumentFolderModel.currentPage, DocumentFolderModel.numberOfPages])} ${CmsAdminMessages.getMessage("contentsection.documentfolder.pageof", [DocumentFolderModel.currentPage, DocumentFolderModel.numberOfPages])}
</p> </p>
<div> <div>
<button class="btn btn-primary" <c:choose>
data-toggle="modal" <c:when test="#{DocumentFolderModel.canCreateSubFolders}">
data-target="#new-subfolder-dialog" <button class="btn btn-primary"
title="#{CmsAdminMessages['contentsection.documentfolder.add_subfolder']}"> data-toggle="modal"
<bootstrap:svgIcon icon="folder-plus" /> data-target="#new-subfolder-dialog"
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.add_subfolder']}</span> title="#{CmsAdminMessages['contentsection.documentfolder.add_subfolder']}">
</button> <bootstrap:svgIcon icon="folder-plus" />
<div aria-hidden="true" <span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.add_subfolder']}</span>
aria-labelledby="new-subfolder-dialog-title" </button>
class="modal fade" <div aria-hidden="true"
id="new-subfolder-dialog" aria-labelledby="new-subfolder-dialog-title"
tabindex="-1"> class="modal fade"
<div class="modal-dialog"> id="new-subfolder-dialog"
<form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documentfolders/#{DocumentFolderModel.path}" tabindex="-1">
class="modal-content" <div class="modal-dialog">
method="post"> <form action="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documentfolders/#{DocumentFolderModel.path}"
<div class="modal-header"> class="modal-content"
<h2 class="modal-title" method="post">
id="new-subfolder-dialog-title"> <div class="modal-header">
#{CmsAdminMessages['contentsection.documentfolder.new_subfolder_dialog.title']} <h2 class="modal-title"
</h2> id="new-subfolder-dialog-title">
<button aria-label="#{CmsAdminMessages['contentsection.documentfolder.new_subfolder_dialog.close']}" #{CmsAdminMessages['contentsection.documentfolder.new_subfolder_dialog.title']}
class="close" </h2>
data-dismiss="modal" <button aria-label="#{CmsAdminMessages['contentsection.documentfolder.new_subfolder_dialog.close']}"
type="button"> class="close"
<span aria-hidden="true">&times;</span> data-dismiss="modal"
</button> type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="new-subfolder-name">
#{CmsAdminMessages['contentsection.documentfolder.new_subfolder.name.label']}
</label>
<input aria-describedby="new-subfolder-name-help"
class="form-control"
id="new-subfolder-name"
name="folderName"
pattern="^([a-zA-Z0-9-_]*)$"
type="text"
value="" />
<small class="form-text text-muted"
id="new-subfolder-name-help">
#{CmsAdminMessages['contentsection.documentfolder.new_subfolder.name.help']}
</small>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-danger"
data-dismiss="modal"
type="button">
#{CmsAdminMessages['contentsection.documentfolder.new_subfolder_dialog.close']}
</button>
<button class="btn btn-success"
type="submit">
#{CmsAdminMessages['contentsection.documentfolder.new_subfolder_dialog.submit']}
</button>
</div>
</form>
</div> </div>
<div class="modal-body"> </div>
<div class="form-group"> </c:when>
<label for="new-subfolder-name"> <c:otherwise>
#{CmsAdminMessages['contentsection.documentfolder.new_subfolder.name.label']} <button class="btn btn-primary"
</label> disabled="disabled"
<input aria-describedby="new-subfolder-name-help" title="#{CmsAdminMessages['contentsection.documentfolder.add_subfolder']}">
class="form-control" <bootstrap:svgIcon icon="folder-plus" />
id="new-subfolder-name" <span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.add_subfolder']}</span>
name="folderName" </button>
pattern="^([a-zA-Z0-9-_]*)$" </c:otherwise>
type="text" </c:choose>
value="" /> <c:choose>
<small class="form-text text-muted" <c:when test="#{DocumentFolderModel.canCreateItems}">
id="new-subfolder-name-help"> <button class="btn btn-primary" title="#{CmsAdminMessages['contentsection.documentfolder.add_document']}">
#{CmsAdminMessages['contentsection.documentfolder.new_subfolder.name.help']} <bootstrap:svgIcon icon="file-earmark-plus" />
</small> <span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.add_document']}</span>
</div> </button>
</div> </c:when>
<div class="modal-footer"> <c:otherwise>
<button class="btn btn-danger" <button class="btn btn-primary"
data-dismiss="modal" disabled="disabled"
type="button"> title="#{CmsAdminMessages['contentsection.documentfolder.add_document']}">
#{CmsAdminMessages['contentsection.documentfolder.new_subfolder_dialog.close']} <bootstrap:svgIcon icon="file-earmark-plus" />
</button> <span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.add_document']}</span>
<button class="btn btn-success" </button>
type="submit"> </c:otherwise>
#{CmsAdminMessages['contentsection.documentfolder.new_subfolder_dialog.submit']} </c:choose>
</button>
</div>
</form>
</div>
</div>
<button class="btn btn-primary" title="#{CmsAdminMessages['contentsection.documentfolder.add_document']}">
<bootstrap:svgIcon icon="file-earmark-plus" />
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.add_document']}</span>
</button>
</div> </div>
</div> </div>
<table class="table table-hover documentfolder"> <table class="table table-hover documentfolder">
@ -201,22 +225,25 @@
<th> <th>
#{CmsAdminMessages['contentsection.documentfolder.headers.lastedit.label']} #{CmsAdminMessages['contentsection.documentfolder.headers.lastedit.label']}
</th> </th>
<th> <th class="text-center" colspan="3">
#{CmsAdminMessages['contentsection.documentfolder.headers.actions.label']} #{CmsAdminMessages['contentsection.documentfolder.headers.actions.label']}
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<c:forEach items="#{DocumentFolderModel.rows}" <c:forEach items="#{DocumentFolderModel.rows}"
var="row"> var="row">
<tr> <tr>
<td> <td>
<c:choose> <c:choose>
<c:when test="#{row.folder}"> <c:when test="#{row.folder and (row.permissions.grantedEdit or row.permissions.grantedPreview)}">
<a href="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documentfolders/#{row.folderPath}">#{row.name}</a> <a href="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documentfolders/#{row.folderPath}">#{row.name}</a>
</c:when> </c:when>
<c:otherwise> <c:when test="#{row.permissions.grantedApprove or row.permissions.grantedCategorize or row.permissions.grantedEdit or row.permissions.grantedPreview or row.permissions.grantedPublish}">
<a href="#">#{row.name}</a> <a href="#">#{row.name}</a>
</c:when>
<c:otherwise>
<span>#{row.name}</span>
</c:otherwise> </c:otherwise>
</c:choose> </c:choose>
</td> </td>
@ -247,11 +274,31 @@
</c:if> </c:if>
</c:if> </c:if>
</td> </td>
<td>
<c:if test="#{row.folder and row.permissions.grantedEdit}">
<button class="btn btn-info"
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"
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>
</c:if>
</td>
<td> <td>
<c:if test="#{row.deletable}"> <c:if test="#{row.deletable}">
<button class="btn btn-danger"> <button class="btn btn-danger"
title="#{CmsAdminMessages['contentsection.documentfolder.actions.delete.button.label']}">
<bootstrap:svgIcon icon="x-circle" /> <bootstrap:svgIcon icon="x-circle" />
<span>${CmsAdminMessages['contentsection.documentfolder.actions.delete.button.label']}</span> <span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.actions.delete.button.label']}</span>
</button> </button>
</c:if> </c:if>
</td> </td>

View File

@ -62,3 +62,5 @@ contentsection.documentfolder.new_subfolder.name.help=The new name of the subfol
contentsection.documentfolder.new_subfolder_dialog.submit=Create new subfolder contentsection.documentfolder.new_subfolder_dialog.submit=Create new subfolder
contentsection.documentfolder.new_subfolder_dialog.close=Cancel contentsection.documentfolder.new_subfolder_dialog.close=Cancel
contentsection.documentfolders.root.title=Documents contentsection.documentfolders.root.title=Documents
contentsection.documentfolder.actions.rename_folder.button.label=Rename folder
contentsection.documentfolder.actions.edit_permissions.button.label=Edit permissions

View File

@ -62,3 +62,5 @@ contentsection.documentfolder.new_subfolder.name.help=Der Name des neuen Ordners
contentsection.documentfolder.new_subfolder_dialog.submit=Neuen Ordner anlegen contentsection.documentfolder.new_subfolder_dialog.submit=Neuen Ordner anlegen
contentsection.documentfolder.new_subfolder_dialog.close=Abbrechen contentsection.documentfolder.new_subfolder_dialog.close=Abbrechen
contentsection.documentfolders.root.title=Dokumente contentsection.documentfolders.root.title=Dokumente
contentsection.documentfolder.actions.rename_folder.button.label=Ordner umbebennen
contentsection.documentfolder.actions.edit_permissions.button.label=Berechtigungen bearbeiten