Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix stack access with advanced permissions #7029

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion concrete/config/concrete.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/
'version' => '8.5.0a2',
'version_installed' => '8.5.0a2',
'version_db' => '20180905000000', // the key of the latest database migration
'version_db' => '20180905122100', // the key of the latest database migration

/*
* Installation status
Expand Down
7 changes: 7 additions & 0 deletions concrete/config/install/base/permissions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@
<permissionkey handle="edit_area_permissions" name="Edit Area Permissions" package="" description="Controls whether users can access the permissions on an area. Custom area permissions could override those of the page." category="area"/>
<permissionkey handle="delete_area_contents" name="Delete Area Contents" package="" description="Controls whether users can delete blocks from this area." category="area"/>
<permissionkey handle="schedule_area_contents_guest_access" name="Schedule Guest Access" description="Controls whether users can schedule guest access permissions on blocks in this area. Guest Access is a shortcut for granting permissions just to the Guest Group." package="" category="area" />
<permissionkey handle="add_subarea" name="Add Sub-Area" package="" description="Can add an area beneath the current area." category="area"/>
<permissionkey handle="approve_area_versions" name="Approve Area Versions" description="Can publish an unapproved version of the area." package="" category="area" can-trigger-workflow="true"/>
<permissionkey handle="delete_area" name="" description="Delete Area" package="Ability to delete this area." category="area" can-trigger-workflow="true"/>
<permissionkey handle="delete_area_versions" name="Delete Area Versions" description="Ability to remove old versions of this area." package="" category="area" can-trigger-workflow="true"/>
<permissionkey handle="view_area_versions" name="View Area Versions" description="Can view the area versions dialog and read past versions of an area." package="" category="area"/>
<permissionkey handle="move_or_copy_area" name="Move or Copy Area" description="Can move or copy this area to another location." package="" category="area" can-trigger-workflow="true" />
<permissionkey handle="edit_area_properties" name="Edit Properties" description="Ability to change anything in the Area Properties menu." package="" category="area"/>

<!-- blocks //-->
<permissionkey handle="view_block" name="View Block" package="" category="block" description="Controls whether users can view this block in the page." />
Expand Down
2 changes: 1 addition & 1 deletion concrete/controllers/backend/page/arrange_blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ArrangeBlocks extends Page
{
public function canAccess()
{
return $this->permissions->canEditPageContents();
return $this->stackPermissions ? $this->stackPermissions->canEditAreaContents() : $this->permissions->canEditPageContents();
}

public function arrange()
Expand Down
13 changes: 13 additions & 0 deletions concrete/controllers/backend/user_interface/page.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use Page as ConcretePage;
use Permissions;
use Concrete\Core\Area\Area;

abstract class Page extends \Concrete\Controller\Backend\UserInterface
{
Expand All @@ -12,6 +13,13 @@ abstract class Page extends \Concrete\Controller\Backend\UserInterface
/** @var Permissions This page's permissions */
protected $permissions;

/**
* Stack permissions (only if the current "page" is a stack).
*
* @var \Concrete\Core\Permission\Checker|null
*/
protected $stackPermissions;

public function on_start()
{
$request = $this->request;
Expand All @@ -36,6 +44,11 @@ public function setPageObject(ConcretePage $c)
{
$this->page = $c;
$this->permissions = new Permissions($this->page);
if ($this->page->getPageTypeHandle() === STACKS_PAGE_TYPE) {
$this->stackPermissions = new Permissions(Area::get($this->page, STACKS_AREA_NAME));
} else {
$this->stackPermissions = null;
}
$this->set('c', $this->page);
$this->set('cp', $this->permissions);
}
Expand Down
2 changes: 1 addition & 1 deletion concrete/controllers/page_types/core_stack.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function __construct(\Concrete\Core\Page\Page $c, ResponseFactory $factor

public function on_start()
{
$stacksPage = Page::getByPath('/dashboard/blocks/stacks');
$stacksPage = Page::getByPath(STACKS_LISTING_PAGE_PATH);
$stacksPerms = new Permissions($stacksPage);

// Make sure we can view the stacks page
Expand Down
2 changes: 1 addition & 1 deletion concrete/controllers/panel/add.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected function getSelectedTab()

protected function canAccess()
{
return $this->permissions->canEditPageContents();
return $this->stackPermissions ? $this->stackPermissions->canAddBlockToArea() : $this->permissions->canEditPageContents();
}

/**
Expand Down
30 changes: 21 additions & 9 deletions concrete/controllers/panel/page/versions.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Concrete\Core\Database\Connection\Connection;
use Concrete\Core\Page\Collection\Collection;
use Concrete\Core\Workflow\Request\UnapprovePageRequest;
use Permissions;
use Page;
use Loader;
use Core;
Expand All @@ -23,6 +22,9 @@ class Versions extends BackendInterfacePageController
protected $viewPath = '/panels/page/versions';
public function canAccess()
{
if ($this->stackPermissions) {
return $this->stackPermissions->canViewAreaVersions();
}
return $this->permissions->canViewPageVersions() || $this->permissions->canEditPageVersions();
}

Expand All @@ -35,7 +37,6 @@ protected function getPageVersionListResponse($currentPage = false)
$r = new PageEditVersionResponse();
$r->setPage($this->page);
$r->setVersionList($vl);
$cpCanDeletePageVersions = $this->permissions->canDeletePageVersions();
foreach ($vArray as $v) {
$r->addCollectionVersion($v);
}
Expand Down Expand Up @@ -121,9 +122,12 @@ public function delete()
/** @var \Concrete\Core\Page\Collection\Collection $c */
$c = $this->page;
$versions = $this->countVersions($c);

$cp = new Permissions($this->page);
if ($cp->canDeletePageVersions()) {
if ($this->stackPermissions) {
$canDelete = $this->stackPermissions->canDeleteAreaVersions();
} else {
$canDelete = $this->permissions->canDeletePageVersions();
}
if ($canDelete) {
$r = new PageEditVersionResponse();
$r->setPage($c);
if (is_array($_POST['cvID'])) {
Expand Down Expand Up @@ -174,10 +178,14 @@ private function countVersions(Collection $c)
public function approve()
{
$c = $this->page;
$cp = $this->permissions;
if ($this->validateAction()) {
$r = new PageEditVersionResponse();
if ($cp->canApprovePageVersions()) {
if ($this->stackPermissions) {
$canApprove = $this->stackPermissions->canApproveAreaVersions();
} else {
$canApprove = $this->permissions->canApprovePageVersions();
}
if ($canApprove) {
$ov = CollectionVersion::get($c, 'ACTIVE');
if (is_object($ov)) {
$ovID = $ov->getVersionID();
Expand Down Expand Up @@ -216,10 +224,14 @@ public function approve()
public function unapprove()
{
$c = $this->page;
$cp = $this->permissions;
if ($this->validateAction()) {
$r = new PageEditVersionResponse();
if ($cp->canApprovePageVersions()) {
if ($this->stackPermissions) {
$canApprove = $this->stackPermissions->canApproveAreaVersions();
} else {
$canApprove = $this->permissions->canApprovePageVersions();
}
if ($canApprove) {
$cvID = $this->request->request->get('cvID');
$r = new PageEditVersionResponse();
$r->setPage($c);
Expand Down
38 changes: 25 additions & 13 deletions concrete/controllers/single_page/dashboard/blocks/stacks.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Concrete\Controller\SinglePage\Dashboard\Blocks;

use Concrete\Core\Area\Area;
use Concrete\Core\Entity\Statistics\UsageTracker\StackUsageRecord;
use Concrete\Core\Http\Response;
use Concrete\Core\Multilingual\Page\Section\Section;
Expand Down Expand Up @@ -335,8 +336,14 @@ public function add_localized_stack()
$this->error->add(t(/*i18n %s is a language name*/ "There's already a version of this stack in %s", $section->getLanguageText()).' ('.$section->getLocale().')');
}
}
if ($neutralStack) {
$cpc = new Permissions(Area::get($neutralStack, STACKS_AREA_NAME));
if (!$cpc->canAddSubarea()) {
$this->error->add(t('Access denied'));
}
}
if (!$this->error->has()) {
$localizedStack = $neutralStack->addLocalizedStack($section);
$neutralStack->addLocalizedStack($section);
$this->redirect(
'/dashboard/blocks/stacks',
'view_details',
Expand Down Expand Up @@ -400,8 +407,8 @@ public function delete_stack()
}
}
if (!$this->error->has()) {
$sps = new Permissions($s);
if ($sps->canDeletePage()) {
$sps = new Permissions(Area::get($s, STACKS_AREA_NAME));
if ($sps->canDeleteArea()) {
$u = new \User();
$pkr = new DeletePageRequest();
$pkr->setRequestedPage($s);
Expand Down Expand Up @@ -435,8 +442,8 @@ public function approve_stack($stackID = false, $token = false)
$s = Stack::getByID($stackID);
if (is_object($s)) {
$isGlobalArea = $s->getStackType() == Stack::ST_TYPE_GLOBAL_AREA;
$sps = new Permissions($s);
if ($sps->canApprovePageVersions()) {
$sps = new Permissions(Area::get($s, STACKS_AREA_NAME));
if ($sps->canApproveAreaVersions()) {
$u = new User();
$v = Version::get($s, 'RECENT');
$pkr = new ApproveStackRequest();
Expand Down Expand Up @@ -491,15 +498,20 @@ public function rename($cID)
$this->error->add(t('Invalid stack'));
$this->view();
} else {
$sps = new Permissions($page);
if (!$sps->canEditPageProperties()) {
if ($isFolder) {
$this->error->add(t("You don't have the permission to rename this stack"));
} else {
if ($isFolder) {
$sps = new Permissions($page);
if (!$sps->canEditPageProperties()) {
$this->error->add(t("You don't have the permission to rename this stack folder"));
$this->view_details($viewCID);
}
$this->view_details($viewCID);
} else {
$sps = new Permissions(Area::get($page, STACKS_AREA_NAME));
if (!$sps->canEditAreaProperties()) {
$this->error->add(t("You don't have the permission to rename this stack"));
$this->view_details($viewCID);
}
}
if (!$this->error->has()) {
$this->set('renamePage', $page);
$this->set('isFolder', $isFolder);
$this->set('oldName', $isFolder ? $page->getCollectionName() : $stack->getStackName());
Expand Down Expand Up @@ -635,8 +647,8 @@ public function duplicate($cID)
if ($ns !== null) {
$this->redirect('/dashboard/blocks/stacks', 'duplicate', $ns->getCollectionID());
}
$sps = new Permissions($s);
if (!$sps->canMoveOrCopyPage()) {
$sps = new Permissions(Area::get($s, STACKS_AREA_NAME));
if (!$sps->canMoveOrCopyArea()) {
$this->error->add(t("You don't have the permission to clone this stack"));
$this->view_details($cID);
} else {
Expand Down
75 changes: 41 additions & 34 deletions concrete/single_pages/dashboard/blocks/stacks/view.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,37 @@
<?php
if ($stackToEdit === null) {
?>
<form method="post" action="<?=$view->action('add_localized_stack')?>">
<?=$token->output('add_localized_stack')?>
<?=$form->hidden('stackID', $neutralStack->getCollectionID());?>
<?=$form->hidden('locale', $localeCode);?>
<div class="alert alert-info">
<p>
<?=t(/*i18n: %1$s is a language name, %2$s is a language code*/'This stack is not defined for %1$s (%2$s): the default version will be used.', $localeName, $localeCode); ?>
</p>
<p>
<button class="btn btn-primary" type="submit"><?=$isGlobalArea ? t('Create localized global area version') : t('Create localized stack version')?></button><br />
</p>
</div>
</form>
<div class="alert alert-info">
<p>
<?=t(/*i18n: %1$s is a language name, %2$s is a language code*/'This stack is not defined for %1$s (%2$s): the default version will be used.', $localeName, $localeCode); ?>
</p>
<?php
$cpc = new Permissions(Area::get($neutralStack, STACKS_AREA_NAME));
if ($cpc->canAddSubarea()) {
?>
<form method="post" action="<?=$view->action('add_localized_stack')?>">
<?=$token->output('add_localized_stack')?>
<?=$form->hidden('stackID', $neutralStack->getCollectionID());?>
<?=$form->hidden('locale', $localeCode);?>
<p>
<button class="btn btn-primary" type="submit"><?=$isGlobalArea ? t('Create localized global area version') : t('Create localized stack version')?></button><br />
</p>
</form>
<?php
}
?>
</div>
<?php
} else {
$cpc = new Permissions($stackToEdit);
$a = Area::get($stackToEdit, STACKS_AREA_NAME);
$cpc = new Permissions($a);
$showApprovalButton = false;
$hasPendingPageApproval = false;
$workflowList = PageWorkflowProgress::getList($stackToEdit);
foreach ($workflowList as $wl) {
$wr = $wl->getWorkflowRequestObject();
$wrk = $wr->getWorkflowRequestPermissionKeyObject();
if ($wrk->getPermissionKeyHandle() == 'approve_page_versions') {
if ($wrk->getPermissionKeyHandle() == 'approve_area_versions') {
$hasPendingPageApproval = true;
break;
}
Expand All @@ -62,7 +70,7 @@
if (!$hasPendingPageApproval) {
$vo = $stackToEdit->getVersionObject();
$composer = Core::make('helper/concrete/composer');
if ($cpc->canApprovePageVersions()) {
if ($cpc->canApproveAreaVersions()) {
$publishTitle = $composer->getPublishButtonTitle($stackToEdit);
$showApprovalButton = true;
}
Expand All @@ -72,32 +80,32 @@
<nav class="navbar navbar-default">
<div class="container-fluid">
<ul class="nav navbar-nav small">
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#"><?=t('Add')?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a class="dialog-launch" dialog-modal="false" dialog-width="550" dialog-height="380" dialog-title="<?=t('Add')?>" href="<?=URL::to('/ccm/system/dialogs/page/add_block_list')?>?cID=<?=$stackToEdit->getCollectionID()?>&arHandle=<?=STACKS_AREA_NAME?>"><?=t('Add Block')?></a></li>
<li><a class="dialog-launch" dialog-modal="false" dialog-width="550" dialog-height="380" dialog-title="<?=t('Paste From Clipboard')?>" href="<?=URL::to('/ccm/system/dialogs/page/clipboard')?>?cID=<?=$stackToEdit->getCollectionID()?>&arHandle=<?=STACKS_AREA_NAME?>"><?=t('Paste From Clipboard')?></a></li>
</ul>
</li>
<li><a dialog-width="640" dialog-height="340" class="dialog-launch" id="stackVersions" dialog-title="<?=t('Version History')?>" href="<?=URL::to('/ccm/system/panels/page/versions')?>?cID=<?=$stackToEdit->getCollectionID()?>"><?=t('Version History')?></a></li>
<?php if (!$isGlobalArea && $cpc->canEditPageProperties()) { ?>
<?php if ($cpc->canAddBlockToArea()) { ?>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#"><?=t('Add')?> <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a class="dialog-launch" dialog-modal="false" dialog-width="550" dialog-height="380" dialog-title="<?=t('Add')?>" href="<?=URL::to('/ccm/system/dialogs/page/add_block_list')?>?cID=<?=$stackToEdit->getCollectionID()?>&arHandle=<?=STACKS_AREA_NAME?>"><?=t('Add Block')?></a></li>
<li><a class="dialog-launch" dialog-modal="false" dialog-width="550" dialog-height="380" dialog-title="<?=t('Paste From Clipboard')?>" href="<?=URL::to('/ccm/system/dialogs/page/clipboard')?>?cID=<?=$stackToEdit->getCollectionID()?>&arHandle=<?=STACKS_AREA_NAME?>"><?=t('Paste From Clipboard')?></a></li>
</ul>
</li>
<?php } ?>
<?php if ($cpc->canViewAreaVersions()) { ?>
<li><a dialog-width="640" dialog-height="340" class="dialog-launch" id="stackVersions" dialog-title="<?=t('Version History')?>" href="<?=URL::to('/ccm/system/panels/page/versions')?>?cID=<?=$stackToEdit->getCollectionID()?>"><?=t('Version History')?></a></li>
<?php } ?>
<?php if (!$isGlobalArea && $neutralStack === $stackToEdit && $cpc->canEditAreaProperties()) { ?>
<li><a href="<?=$view->action('rename', $neutralStack->getCollectionID())?>"><?=t('Rename')?></a></li>
<?php } ?>
<?php if ($cpc->canEditPagePermissions() && Config::get('concrete.permissions.model') == 'advanced') { ?>
<?php if ($cpc->canEditAreaPermissions() && Config::get('concrete.permissions.model') == 'advanced') { ?>
<li><a dialog-width="580" class="dialog-launch" dialog-append-buttons="true" dialog-height="420" dialog-title="<?=t('Stack Permissions')?>" id="stackPermissions" href="<?=REL_DIR_FILES_TOOLS_REQUIRED?>/edit_area_popup?cID=<?=$stackToEdit->getCollectionID()?>&arHandle=<?=STACKS_AREA_NAME?>&atask=groups"><?=t('Permissions')?></a></li>
<?php } ?>
<?php if (!$isGlobalArea && $cpc->canMoveOrCopyPage()) { ?>
<?php if (!$isGlobalArea && $cpc->canMoveOrCopyArea()) { ?>
<li><a href="<?=$view->action('duplicate', $neutralStack->getCollectionID())?>" style="margin-right: 4px;"><?=t('Duplicate')?></a></li>
<?php } ?>
<?php if (!$isGlobalArea) { ?>
<li>
<a dialog-width="640" dialog-height="340" class="dialog-launch" id="stackUsage" dialog-title="<?=t('Usage')?>" href="<?= $view->action('usage', $stackToEdit->getCollectionID()) ?>">
<?=t('Stack Usage')?>
</a>
</li>
<li><a dialog-width="640" dialog-height="340" class="dialog-launch" id="stackUsage" dialog-title="<?=t('Usage')?>" href="<?= $view->action('usage', $stackToEdit->getCollectionID()) ?>"><?=t('Stack Usage')?></a></li>
<?php } ?>
<?php
if ($cpc->canDeletePage()) {
if ($cpc->canDeleteArea()) {
if ($isGlobalArea) {
if ($stackToEdit !== $neutralStack) {
$deleteLabels = ['title' => t('Delete Localized Version'), 'button' => t('Delete')];
Expand Down Expand Up @@ -130,7 +138,6 @@

<div id="ccm-stack-container">
<?php
$a = Area::get($stackToEdit, STACKS_AREA_NAME);
$a->forceControlsToDisplay();
View::element('block_area_header', array('a' => $a));
foreach ($blocks as $b) {
Expand Down
Loading