Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Access control

In Joomla users belong to groups, and groups are allowed or denied actions: create, edit, delete. A component declares the list of its actions, the administrator assigns them to groups, and before each operation the code asks: "may this user do it?".

Files

Both files are created by hand in the root of the administrator part:

administrator/components/com_hello/
├── access.xml           the list of actions
├── config.xml           the options screen with the permissions tab
├── hello.xml
└── ...

Add two lines to the files section inside administration in the manifest:

<filename>access.xml</filename>
<filename>config.xml</filename>

The list of actions

<?xml version="1.0" encoding="UTF-8"?>
<!-- administrator/components/com_hello/access.xml -->
<access component="com_hello">
    <section name="component">
        <action name="core.admin" title="JACTION_ADMIN" />
        <action name="core.manage" title="JACTION_MANAGE" />
        <action name="core.create" title="JACTION_CREATE" />
        <action name="core.edit" title="JACTION_EDIT" />
        <action name="core.delete" title="JACTION_DELETE" />
    </section>
</access>
ActionWhat it allows
core.adminChanging the component options and permissions
core.manageOpening the component in the panel
core.createCreating records
core.editEditing records
core.deleteDeleting records

The JACTION_... titles are ready-made translation keys from the core.

The options screen

<?xml version="1.0" encoding="UTF-8"?>
<!-- administrator/components/com_hello/config.xml -->
<config>
    <fieldset name="permissions" label="JCONFIG_PERMISSIONS_LABEL">
        <field name="rules" type="rules" label="JCONFIG_PERMISSIONS_LABEL"
               filter="rules" validate="rules"
               component="com_hello" section="component" />
    </fieldset>
</config>

A field of type rules renders the "group — action" table. To make this screen reachable, add a button to the list view:

// administrator/components/com_hello/src/View/Posts/HtmlView.php
ToolbarHelper::preferences('com_hello');

The post list now has an Options button. Press it, open the Permissions tab, select the Manager group and deny it the Create action.

Checking in code

// administrator/components/com_hello/src/View/Posts/HtmlView.php
use Joomla\CMS\Factory;
 
$user = Factory::getApplication()->getIdentity();
 
if ($user->authorise('core.create', 'com_hello')) {
    ToolbarHelper::addNew('post.add');
}
 
if ($user->authorise('core.admin', 'com_hello')) {
    ToolbarHelper::preferences('com_hello');
}

getIdentity() returns the current user, authorise() answers true or false. Log in to the panel as a user from the Manager group: the New button is gone.

Hiding a button is not enough — the action address can be typed by hand. But FormController itself checks core.create before add and core.edit before edit and save, so such a user is refused at the task=post.add address.

Your own controller actions

In your own methods you write the check yourself:

// administrator/components/com_hello/src/Controller/PostController.php
public function hide(): void
{
    $this->checkToken();
 
    if (!$this->app->getIdentity()->authorise('core.edit', 'com_hello')) {
        throw new \Exception('Not enough permissions', 403);
    }
 
    // change the record…
 
    $this->setRedirect('index.php?option=com_hello&view=posts', 'Post hidden');
}

User properties

ExpressionWhat it returns
$user->idThe user id; 0 for a guest
$user->guest1 if the user is not logged in
$user->name, $user->usernameThe name and the login
$user->authorise('core.edit', 'com_hello')Whether the action is allowed
$user->getAuthorisedViewLevels()The ids of the accessible view levels

View levels

Besides actions there are read access levels: Public, Registered, Special. They are assigned to modules, menu items and articles: a guest does not see a module with the Registered level. To restrict the records of your own component this way, add an access column to the table and compare it with the list from getAuthorisedViewLevels().

Common mistake

Permissions are checked only in the layout: the Delete button is hidden, and the job is considered done. A hidden button does not stop anyone from sending the request directly. The authorise() check must sit where the action is performed — in the controller or the model.

Thanks for reading!

Donate to the site — we work hard for you.