Creating Permissions
Creating a Task Permission
To create a custom task permission in a package, add a permission key during installation like this:
public function install()
{
$pkg = parent::install();
\Concrete\Core\Permission\Key\Key::add('admin', 'change_theme_settings', 'Change Theme Settings', '', false, false, $pkg);
}
'admin'
: Permission category handle.'change_theme_settings'
: Permission key handle.'Change Theme Settings'
: Name of the permission.- Description and two boolean parameters for workflow trigger and custom class use.
$pkg
: Package object.
This permission will be available on the Task Permissions Dashboard page.
Creating a Page, File, or User Permission
For a permission related to existing objects like pages, change the category handle:
public function install()
{
$pkg = parent::install();
\Concrete\Core\Permission\Key\Key::add('page', 'change_custom_theme_settings', 'Change Theme Settings', '', false, false, $pkg);
}
Here, 'page'
is used as the permission category handle, defining it as a custom page permission.
Custom Access Entity in Concrete CMS
Concrete CMS provides various access entities like Group, User, and Page Owner. Developers can easily create custom access entities for more tailored permission settings.
eCommerce Scenario
For an eCommerce site, you might need a "Product Purchaser" Access Entity. This entity allows specific access based on product purchase, beyond what is possible with standard user groups.
Installing the Access Entity
Install the entity by updating the database. Add the following in your controller's install()
method:
use \Concrete\Core\Permission\Access\Entity\Type\Type;
use \Concrete\Core\Permission\Category;
$type = Type::getByHandle('product_purchaser');
if (!is_object($type)) {
$type = Type::add('product_purchaser', 'Product Purchaser', $pkg);
}
$category = Category::getByHandle('page');
$category->associateAccessEntityType($type);
This code registers a "Product Purchaser" entity for page-related permissions.
Backend Implementation
Create ProductPurchaserEntity.php
in packages/super_store/src/Concrete/Permission/Access/Entity/
with necessary functions like getAccessEntityUsers()
, getAccessEntityTypeLinkHTML()
, and others for handling user access based on product purchases.
Frontend Code
Add frontend interaction in packages/super_store/elements/permission/access/entity/types/product_purchaser.php
. This involves JavaScript for selecting products and updating the permissions interface.
Routing
Set up routing in your package controller’s on_start()
:
\Route::register(
'/tools/packages/super_store/permissions/access/entity/types/product_purchaser',
'\Concrete\Package\SuperStore\Controller\Permissions\Access\Entity\Types\ProductPurchaser::process'
);
Then create ProductPurchaser.php
in packages/super_store/controllers/permissions/access/entity/types/
for handling AJAX requests and returning JSON data for the entity.
This custom entity allows locking down site areas based on specific product purchases, providing a flexible permission system for eCommerce scenarios.
Creating a Permissions Category
For custom eCommerce solutions like \SuperStore\Product\Product
, adding unique permissions such as "View Product", "Edit Product", and "Delete Product" necessitates a new permission category. These permissions apply specifically to Product objects, allowing control over who can edit certain products. This requires both backend and frontend custom code within a Concrete package.
Creating the Custom Category Object
Prepare Controller
Add autoload configuration to controller.php
for the package:
$pkgAutoloaderMapCoreExtensions = true;
Create the Assignment Database Table
Create a table for Product-Permission assignments:
CREATE TABLE `SuperStoreProductAssignments` (
`productID` int(10) unsigned NOT NULL DEFAULT '0',
`pkID` int(10) unsigned NOT NULL DEFAULT '0',
`paID` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`cID`,`pkID`,`paID`),
KEY `paID` (`paID`,`pkID`),
KEY `pkID` (`pkID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Concrete CMS package database documentation.
Install Permission Category and Keys
In install()
method of the controller, set up the new category and permissions:
use Concrete\Core\Permission\Category\Category;
use Concrete\Core\Permission\Key\Key;
use Concrete\Core\Permission\Access\Entity\Type as AccessEntityType;
public function install() {
$pkg = parent::install();
// Category setup
$category = Category::getByHandle('product');
if (!is_object($category)) {
$category = Category::add('product', $pkg);
$category->associateAccessEntityType(AccessEntityType::getByHandle('group'));
$category->associateAccessEntityType(AccessEntityType::getByHandle('user'));
}
// Permission keys setup
// 'view_product', 'edit_product', 'delete_product'
}
Implement Concrete\Core\Permission\ObjectInterface
Ensure Products
class implements the permissions object interface:
namespace SuperStore\Product
use Concrete\Core\Permission\ObjectInterface;
class Products implements ObjectInterface {
// Implementation of the interface methods
}
Create the Classes
Create the required classes for custom permission:
- Key:
ProductKey extends Key
- Access:
ProductAccess extends Access
- Access List Item:
ProductListItem extends ListItem
- Response:
ProductResponse extends Response
- Assignment: Implement custom logic in
ProductAssignment extends Assignment
Handle custom logic in ProductAssignment
for querying SuperStoreProductAssignments
and managing permissions.
Creating the Category User Interface
To set new permissions for the Product object, create a Dashboard page. Follow Single Pages for guidance.
Create a Dashboard Page
Create a Dashboard Page in the Package controller. Example path:
/dashboard/super_store/product/permissions
This page loads a product by its ID:
http://www.example.com/dashboard/super_store/products/permissions/120
view()
method in Dashboard controller:
public function view($productID = null)
{
$product = \SuperStore\Product\Product::getByID($productID);
$this->set('product', $product);
}
Dashboard view form:
<form method="post" action="<?=$view->action('save_permissions')?>">
<input type="hidden" name="productID" value="<?=$product->getProductID()?>">
<?=$token->output('save_permissions')?>
<fieldset>
<div id="ccm-permission-list-form">
<?php View::packageElement('permission/lists/product', 'super_store', array(
"product" => $product)); ?>
</div>
</fieldset>
<div class="form-actions">
<button type="submit" name="submit" class="btn pull-right btn-primary"><?=t('Save Permissions')?></button>
</div>
</form>
Package element packages/super_store/elements/permission/lists/product.php
:
<table class="ccm-permission-grid table table-striped">
<!-- Permission rows -->
</table>
<script type="text/javascript">
ccm_permissionLaunchDialog = function(link) {
// JavaScript for dialog
}
</script>
- Create a table with permission keys.
- Loop through permission keys, setting the product object.
- Display permissions and access data.
- Include custom JavaScript for dialog interaction.
Define Route
Define a route in the package controller for permission dialogs:
public function on_start()
{
\Route::register(
Router::route(array('/permissions/dialogs/product', 'super_store')),
'\Concrete\Package\SuperStore\Controller\Permissions\ProductDialog::view'
);
}
Create ProductDialog
controller:
namespace Concrete\Package\SuperStore\Controller\Permissions;
class ProductDialog extends BackendInterfaceController
{
protected $viewPath = '/dialogs/permissions/product_dialog';
public function canAccess() {
// Access control logic
}
public function view() {
// View logic
}
}
Include permission/details/product.php
in the view.
Backend Permission Category Processor
Define a custom route for the automatically generated tools URL:
\Route::register('/tools/packages/super_store/permissions/categories/product',
'\Concrete\Package\SuperStore\Controller\Permissions::process'
);
Create Permissions
controller:
namespace Concrete\Package\SuperStore\Controller;
class Permissions extends \Concrete\Core\Controller\Controller
{
public function process() {
// Processing logic
}
}
Using the Permissions
Use custom permissions with:
$product = Product::getByID($productID);
$p = new Permissions($product);
if ($p->canViewProduct()) {
// Can view!
}
if ($p->canEditProduct()) {
// Can edit!
}
if ($p->canDeleteProduct()) {
// Can delete!
}
Expand product permissions over time, supporting all Concrete access entities and duration-based permissions.