Block custom permission

I am trying to add a custom permission to my block so I can show certain content to specific users only.

What I did so far:
Create a new permission key in package install:

		if (!is_object(\Concrete\Core\Permission\Key\Key::getByHandle('my_custom_permission'))) {
			$pkUploadFiles = \Concrete\Core\Permission\Key\Key::add('block', 'my_custom_permission', t('Custom Permission'), t('Give custom permission to user'), '', '', $pkg);
		}

The new permission is visible in the block permission view, and I have assigned a user to it.
In my block controller view function I try to check the permission, however this will always stay false.

        $b = Block::getByID($this->bID);
      	$pk = \Concrete\Core\Permission\Key\Key::getByHandle('my_custom_permission');
      	$pk->setPermissionObject($b);
      	var_dump($pk->can());

Is there anything I am missing? Should I do this differently?


Running Concrete 8.5.12

Just a hunch but maybe try

$permission = new Permissions($b);
var_dump($permission->canMyCustomPermission());

Tried that as well. Unfortunately it gives me int(0).

This is my current code and I cant figure out why this is not working. Is my custom block permission overridden by a permission from the page?

class Controller extends BlockController{	
        ....
	public function view(){
		$b = Block::getByID($this->bID);
		$bp = new Permissions($b);

		var_dump($bp->canMyCustomPermission());
      ....

When you var_dump just $bp does it show evidence that the custom permission is actually getting loaded? I would imagine that custom permissions get pulled into the block view context but might be worth a look.

Unfortunately var_dump($bp) will give me an allowed memory size exhausted error.
I will try to setup a dev environment to be able to run xdebug on the running code.

try var_dump_safe($bp) instead

I have been digging using xdebug and found the following so far:

Permission/Key/Key->validate() :: Line 566

        $pae = $this->getPermissionAccessObject();
        if (is_object($pae)) {
            $valid = $pae->validate();
        } else {
            $valid = false;
        }

$this->getPermissionAccessObject() returned null, So $pae is null. This resulted in valid set to false.

Digging deeper into this function:

    public function getPermissionAccessObject()
    {
        $targ = $this->getPermissionAssignmentObject();

        return $targ->getPermissionAccessObject();
    }

$targ->permissionObjectToCheck is an instance of Page. Why??

Permission/Assignment/BlockAssignment :: Line 20


    public function setPermissionObject($b)
    {
        $this->permissionObject = $b;

        // if the area overrides the collection permissions explicitly (with a one on the override column) we check
        if ($b->overrideAreaPermissions()) {
            $this->permissionObjectToCheck = $b;
        } else {
            $a = $b->getBlockAreaObject();
            if ($a instanceof SubArea && !$a->overrideCollectionPermissions()) {
                $a = $a->getSubAreaParentPermissionsObject();
            }
            if (is_object($a)) {
                ....
            } else {
                $this->permissionObjectToCheck = Page::getCurrentPage();
            }
        }
    }

$b->overrideAreaPermissions() returns 0. And in the end this causes this function to return Page::getCurrentPage();.

Its strange this is 0 as in the GUI it saus the block overrides the permission.
image

Also, looking at the database the cbOverrideAreaPermissions for this block is set to 1. So why is overrideAreaPermissions() returning 0?

Clicking the “Revert to Area Permissions” button in the GUI will change this value to 0, and clicking “Override Permissions” will set it to 1.

So why is it not loaded correctly in the Block object?


So, to conclude…
In my controller I run:

$b = Block::getByID($this->bID);

The code in Block/Block.php does not load cbOverrideAreaPermissions from the database as no Collection or Area is provided.
As this is not set, the $b->overrideAreaPermissions() will set it to 0:

    public function overrideAreaPermissions()
    {
        if (!isset($this->cbOverrideAreaPermissions) || !$this->cbOverrideAreaPermissions) {
            $this->cbOverrideAreaPermissions = 0;
        }

        return $this->cbOverrideAreaPermissions;
    }

And thus the permissions will never work


So how to I get it to load this from the database? I could use something like below, but that does not work as I need to provided both the collection and area. How to I know the area?

		$b = Block::getByID($this->bID);
		$c = $b->getBlockCollectionObject();
		$b = Block::getByID($this->bID, $c);

A temporary workaround could be:

		$b = Block::getByID($this->bID);
		$b->cbOverrideAreaPermissions=1;
		$bp = new Permissions($b);

Now var_dump($bp->canMyCustomPermission()); will give int(1).

I assume this is a bug and created a bug report on github.

1 Like