diff --git a/wiki/src/org/labkey/wiki/WikiController.java b/wiki/src/org/labkey/wiki/WikiController.java index a48f322dd34..d5f307af81a 100644 --- a/wiki/src/org/labkey/wiki/WikiController.java +++ b/wiki/src/org/labkey/wiki/WikiController.java @@ -22,7 +22,6 @@ import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Strings; -import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -60,19 +59,24 @@ import org.labkey.api.security.User; import org.labkey.api.security.UserManager; import org.labkey.api.security.WikiTermsOfUseProvider; +import org.labkey.api.security.permissions.AbstractActionPermissionTest; import org.labkey.api.security.permissions.AbstractContainerScopingTest; import org.labkey.api.security.permissions.AdminPermission; import org.labkey.api.security.permissions.ReadPermission; +import org.labkey.api.security.permissions.UpdatePermission; import org.labkey.api.security.roles.EditorRole; import org.labkey.api.security.roles.FolderAdminRole; import org.labkey.api.security.roles.ReaderRole; import org.labkey.api.settings.AdminConsole; import org.labkey.api.settings.AppProps; +import org.labkey.api.test.TestWhen; import org.labkey.api.util.GUID; import org.labkey.api.util.HtmlString; import org.labkey.api.util.HtmlStringBuilder; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.util.Pair; +import org.labkey.api.util.TestContext; +import org.labkey.api.util.logging.LogHelper; import org.labkey.api.view.ActionURL; import org.labkey.api.view.GridView; import org.labkey.api.view.HtmlView; @@ -130,7 +134,7 @@ public class WikiController extends SpringActionController { - private static final Logger LOG = LogManager.getLogger(WikiController.class); + private static final Logger LOG = LogHelper.getLogger(WikiController.class, "Wiki action debugging"); private static final DefaultActionResolver _actionResolver = new DefaultActionResolver(WikiController.class); public WikiController() @@ -750,7 +754,8 @@ public String getCommandClassMethodName() public abstract Set getWikiTrees(FORM form, Container c); } - @RequiresPermission(ReadPermission.class) + // Require update to prevent bots from excessive crawling of expensive action, GitHub Issue #1415 + @RequiresPermission(UpdatePermission.class) public class PrintAllAction extends PrintMultipleAction { @Override @@ -766,7 +771,8 @@ public void addNavTrail(NavTree root) } } - @RequiresPermission(ReadPermission.class) + // Require update to prevent bots from excessive crawling of expensive action, GitHub Issue #1415 + @RequiresPermission(UpdatePermission.class) public class PrintBranchAction extends PrintMultipleAction { private Wiki _rootWiki; @@ -823,7 +829,8 @@ public void addNavTrail(NavTree root) } } - @RequiresPermission(ReadPermission.class) + // Require update to prevent bots from excessive crawling of expensive action, GitHub Issue #1415 + @RequiresPermission(UpdatePermission.class) public class PrintAllRawAction extends SimpleViewAction { @Override @@ -2747,7 +2754,8 @@ public ApiResponse execute(SetTocPreferenceForm form, BindException errors) } } - @RequiresPermission(ReadPermission.class) + // Require update to prevent bots from excessive crawling of expensive action, GitHub Issue #1415 + @RequiresPermission(UpdatePermission.class) public class BackLinksAction extends SimpleViewAction { @Override @@ -2972,7 +2980,36 @@ public void testAttachFilesRequiresUpdate() throws Exception // Positive control: an Editor passes the UpdatePermission guard. User editor = createUserInRole(folder, EditorRole.class); assertNotEquals("An editor must pass the attachment UpdatePermission guard, not be blocked at 403", - HttpServletResponse.SC_FORBIDDEN, post(url, editor).getStatus()); + HttpServletResponse.SC_FORBIDDEN, post(url, editor).getStatus()); + } + } + + @TestWhen(TestWhen.When.BVT) + public static class PermissionTestCase extends AbstractActionPermissionTest + { + @Override + @Test + public void testActionPermissions() + { + User user = TestContext.get().getUser(); + assertTrue(user.hasSiteAdminPermission()); + WikiController controller = new WikiController(); + + // TODO: Check more actions + + // @RequiresPermission(ReadPermission.class) + assertForReadPermission(user, false, + controller.new PageAction(), + controller.new PrintRawAction() + ); + + // @RequiresPermission(UpdatePermission.class) + assertForUpdateOrDeletePermission(user, + controller.new BackLinksAction(), + controller.new PrintAllAction(), + controller.new PrintAllRawAction(), + controller.new PrintBranchAction() + ); } } } diff --git a/wiki/src/org/labkey/wiki/WikiModule.java b/wiki/src/org/labkey/wiki/WikiModule.java index 7025564475b..0af37f0c893 100644 --- a/wiki/src/org/labkey/wiki/WikiModule.java +++ b/wiki/src/org/labkey/wiki/WikiModule.java @@ -199,7 +199,8 @@ private void loadWikiContent(@Nullable Container c, User user, String name, Stri { return Set.of( WikiManager.TestCase.class, - WikiController.CopyWikiContainerScopingTestCase.class + WikiController.CopyWikiContainerScopingTestCase.class, + WikiController.PermissionTestCase.class ); } diff --git a/wiki/src/org/labkey/wiki/WikiTOC.java b/wiki/src/org/labkey/wiki/WikiTOC.java index dca464d0487..b5a264c0e4f 100644 --- a/wiki/src/org/labkey/wiki/WikiTOC.java +++ b/wiki/src/org/labkey/wiki/WikiTOC.java @@ -23,6 +23,7 @@ import org.labkey.api.security.User; import org.labkey.api.security.permissions.AdminPermission; import org.labkey.api.security.permissions.InsertPermission; +import org.labkey.api.security.permissions.UpdatePermission; import org.labkey.api.util.DOM; import org.labkey.api.util.HtmlString; import org.labkey.api.util.LinkBuilder; @@ -100,26 +101,28 @@ private NavTree createNavMenu() ViewContext context = getViewContext(); User user = context.getUser(); - //output only this one if wiki contains no pages - boolean bHasInsert = _cToc.hasPermission("WikiTOC.getNavMenu()", user, InsertPermission.class); - boolean bHasCopy = _cToc.hasPermission("WikiTOC.getNavMenu()", user, AdminPermission.class) && !getElements().isEmpty(); - boolean bHasPrint = (bHasInsert || !isInWebPart(context)) && !getElements().isEmpty(); + //output "New" if wiki contains no pages + boolean hasInsert = _cToc.hasPermission("WikiTOC.getNavMenu()", user, InsertPermission.class); + boolean hasCopy = _cToc.hasPermission("WikiTOC.getNavMenu()", user, AdminPermission.class) && !getElements().isEmpty(); + // Must have update in the container since this is a folder-wide, potentially expensive operation. GitHub Issue #1415. + boolean hasUpdate = _cToc.hasPermission("WikiTOC.getNavMenu()", user, UpdatePermission.class); + boolean hasPrintAll = hasUpdate && !isInWebPart(context) && !getElements().isEmpty(); NavTree menu = new NavTree(); - if (bHasInsert) + if (hasInsert) { ActionURL newPageUrl = new ActionURL(WikiController.EditWikiAction.class, _cToc); newPageUrl.addParameter("cancel", context.getActionURL().getLocalURIString()); menu.addChild("New", newPageUrl.getLocalURIString()); } - if (bHasCopy) + if (hasCopy) { URLHelper copyUrl = new ActionURL(WikiController.CopyWikiLocationAction.class, _cToc); //pass in source container as a param. copyUrl.addParameter("sourceContainer", _cToc.getPath()); menu.addChild("Copy", copyUrl.toString()); } - if (bHasPrint) + if (hasPrintAll) { menu.addChild("Print all", new ActionURL(WikiController.PrintAllAction.class, _cToc).toString()); } diff --git a/wiki/src/org/labkey/wiki/model/BaseWikiView.java b/wiki/src/org/labkey/wiki/model/BaseWikiView.java index f9549f301b2..8a6b827a215 100644 --- a/wiki/src/org/labkey/wiki/model/BaseWikiView.java +++ b/wiki/src/org/labkey/wiki/model/BaseWikiView.java @@ -20,6 +20,7 @@ import org.labkey.api.data.PropertyManager; import org.labkey.api.portal.ProjectUrls; import org.labkey.api.security.User; +import org.labkey.api.security.permissions.UpdatePermission; import org.labkey.api.util.HtmlString; import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.ActionURL; @@ -31,6 +32,7 @@ import org.labkey.api.wiki.WikiRendererType; import org.labkey.wiki.BaseWikiPermissions; import org.labkey.wiki.WikiController; +import org.labkey.wiki.WikiController.PrintBranchAction; import org.labkey.wiki.WikiSelectManager; import java.util.Map; @@ -51,8 +53,7 @@ public abstract class BaseWikiView extends JspView public ActionURL manageURL; public ActionURL customizeURL; public ActionURL printURL; - - protected WikiVersion wikiVersion = null; // TODO: Used internally only? Pass to init()? + public ActionURL printBranchURL; protected int _webPartId = 0; @@ -62,7 +63,7 @@ protected BaseWikiView() } - protected void init(Container c, String name) + protected void init(Container c, String name, WikiVersion wikiVersion) { ViewContext context = getViewContext(); User user = context.getUser(); @@ -190,9 +191,15 @@ else if (folderHasWikis) } } - if (null == context.getRequest().getParameter(ActionURL.Param._print.name())) + if (null == context.getRequestOrThrow().getParameter(ActionURL.Param._print.name())) { printURL = wiki.getPageURL().addParameter(ActionURL.Param._print, 1); + // Must have update in the container, not just owner update on the wiki, since this is a folder-wide, + // potentially expensive operation. GitHub Issue #1415 + if (wiki.hasChildren() && c.hasPermission(user, UpdatePermission.class)) + { + printBranchURL = new ActionURL(PrintBranchAction.class, getContextContainer()).addParameter("name", wiki.getName()); + } } // Initialize Custom Menus @@ -273,9 +280,8 @@ private NavTree initNavMenu() NavTree print = new NavTree("Print", printURL); print.setNoFollow(true); menu.addChild(print); - if (wiki.hasChildren()) - menu.addChild("Print Branch", new ActionURL(WikiController.PrintBranchAction.class, - getContextContainer()).addParameter("name", wiki.getName())); + if (null != printBranchURL) + menu.addChild("Print Branch", printBranchURL); } } else if (!(isEmbedded() && getFrame() == WebPartView.FrameType.NONE)) diff --git a/wiki/src/org/labkey/wiki/model/WikiView.java b/wiki/src/org/labkey/wiki/model/WikiView.java index ce4d4d6caeb..9733fe3c915 100644 --- a/wiki/src/org/labkey/wiki/model/WikiView.java +++ b/wiki/src/org/labkey/wiki/model/WikiView.java @@ -16,21 +16,15 @@ package org.labkey.wiki.model; -/** - * User: adam - * Date: Aug 11, 2007 - * Time: 3:30:42 PM - */ public class WikiView extends BaseWikiView { - public WikiView(Wiki wiki, WikiVersion wikiversion, boolean hasContent) + public WikiView(Wiki wiki, WikiVersion wikiVersion, boolean hasContent) { super(); this.wiki = wiki; - this.wikiVersion = wikiversion; this.hasContent = hasContent; - init(getViewContext().getContainer(), wiki.getName()); + init(getViewContext().getContainer(), wiki.getName(), wikiVersion); // For the webpart version, see sibling class WikiWebPart setIsWebPart(false); diff --git a/wiki/src/org/labkey/wiki/model/WikiWebPart.java b/wiki/src/org/labkey/wiki/model/WikiWebPart.java index 6463f2fcff6..968153f8cc6 100644 --- a/wiki/src/org/labkey/wiki/model/WikiWebPart.java +++ b/wiki/src/org/labkey/wiki/model/WikiWebPart.java @@ -37,7 +37,7 @@ public WikiWebPart(int webPartId, Map props) String name = props.get("name"); name = (name != null) ? name : "default"; - init(c, name); + init(c, name, null); // display edit pencil in frameless webpart setShowFloatingCustomBtn(true);