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>| Action | What it allows |
|---|---|
core.admin | Changing the component options and permissions |
core.manage | Opening the component in the panel |
core.create | Creating records |
core.edit | Editing records |
core.delete | Deleting 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
| Expression | What it returns |
|---|---|
$user->id | The user id; 0 for a guest |
$user->guest | 1 if the user is not logged in |
$user->name, $user->username | The 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.