Joomla 4.x Tutorial - Extension Development - Access Control List (ACL)

Modify this post

Not everyone has the right to edit all content. For this purpose Joomla offers an access control list, the ACL. With this you manage user rights in your component.

For impatient people

View the changed program code in the Diff Viewgithub.com/astridx/boilerplate/compare/t9...t10 and incorporate these changes into your development version.

Step by step

In the following overview, the newly added files are marked with a background and the changed ones are outlined.

Overview of the files edited in this chapter

New files

administrator/components/com_foos/ access.xml

First, we set all possible permissions in an XML file.

administrator/components/com_foos/ access.xml

<!-- https://raw.githubusercontent.com/astridx/boilerplate/t10/src/administrator/components/com_foos/access.xml -->

<?xml version="1.0" encoding="utf-8"?>
<access component="com_foos">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN" />
		<action name="core.options" title="JACTION_OPTIONS" />
		<action name="core.manage" title="JACTION_MANAGE" />
		<action name="core.create" title="JACTION_CREATE" />
		<action name="core.delete" title="JACTION_DELETE" />
		<action name="core.edit" title="JACTION_EDIT" />
		<action name="core.edit.state" title="JACTION_EDITSTATE" />
		<action name="core.edit.own" title="JACTION_EDITOWN" />
	</section>
</access>

administrator/components/com_foos/ sql/updates/mysql/10.0.0.sql

Joomla stores the permissions in the database. During a Joomla update only database changes are relevant. We enter these in the file administrator/components/com_foos/sql/updates/mysql/VERSIONSNUMMER.sql, here this is specifically administrator/components/com_foos/sql/updates/mysql/10.0.0.sql. This file is only called during an update. In case of a new installation the database will be set up correctly via the main file administrator/components/com_foos/sql/install.mysql.utf8.sql.

administrator/components/com_foos/ sql/updates/mysql/10.0.0.sql

<!-- https://raw.githubusercontent.com/astridx/boilerplate/t10/src/administrator/components/com_foos/sql/updates/mysql/10.0.0.sql -->

ALTER TABLE `#__foos_details` ADD COLUMN  `access` int(10) unsigned NOT NULL DEFAULT 0 AFTER `alias`;

ALTER TABLE `#__foos_details` ADD KEY `idx_access` (`access`);

Modified files

administrator/components/com_foos/ config.xml

We set the permissions for the entire component in the configuration. For this we integrate a special form field. Joomla offers the type rules for this.

administrator/components/com_foos/ config.xml

 			<option value="1">JYES</option>
 		</field>
 	</fieldset>
	<fieldset
		name="permissions"
		label="JCONFIG_PERMISSIONS_LABEL"
		description="JCONFIG_PERMISSIONS_DESC"
		>
		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			validate="rules"
			filter="rules"
			component="com_foos"
			section="component"
		/>
	</fieldset>
 </config>

administrator/components/com_foos/ foos.xml

To make sure that everything runs smoothly during the installation, we add the new files sql/updates/mysql and access.xml here.

administrator/components/com_foos/ foos.xml

 			<file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
 		</sql>
 	</uninstall>
	<update>  <!-- Runs on update -->
		<schemas>
			<schemapath type="mysql">sql/updates/mysql</schemapath>
		</schemas>
	</update>
 	<!-- Frond-end files -->
 	<files folder="components/com_foos">
 		<folder>language</folder>

 			<menu link="option=com_foos">COM_FOOS</menu>
 		</submenu>
 		<files folder="administrator/components/com_foos">
			<filename>access.xml</filename>
 			<filename>foos.xml</filename>
 			<filename>config.xml</filename>
 			<folder>forms</folder>

administrator/components/com_foos/ forms/foo.xml

We extend the form for creating a new Foo item with the possibility to set permissions for a single item. We add the field name="access".

administrator/components/com_foos/ forms/foo.xml

 			size="45"
 			hint="JFIELD_ALIAS_PLACEHOLDER"
 		/>

		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			size="1"
		/>
 	</fieldset>
 </form>

administrator/components/com_foos/ sql/install.mysql.utf8.sql

The SQL script for a new installation of the component with this state of implementation is also extended with the necessary fields.

administrator/components/com_foos/ sql/install.mysql.utf8.sql

 ('Nina'),
 ('Astrid'),
 ('Elmar');

ALTER TABLE `#__foos_details` ADD COLUMN  `access` int(10) unsigned NOT NULL DEFAULT 0 AFTER `alias`;

ALTER TABLE `#__foos_details` ADD KEY `idx_access` (`access`);

administrator/components/com_foos/ src/Model/FoosModel.php

If you are not familiar with SQL so far, the database query will appear complex to you now. It is now necessary to combine data from two database tables. The table that manages the permissions of com_user #__viewlevels, and the one of our example component. Don't let this scare you. Joomla supports you in creating the queries.

administrator/components/com_foos/ src/Model/FoosModel.php

 		// Select the required fields from the table.
 		$query->select(
			$db->quoteName(array('id', 'name', 'alias'))
			$db->quoteName(array('a.id', 'a.name', 'a.alias', 'a.access'))
 		);
		$query->from($db->quoteName('#__foos_details'));

		$query->from($db->quoteName('#__foos_details', 'a'));

		// Join over the asset groups.
		$query->select($db->quoteName('ag.title', 'access_level'))
			->join(
				'LEFT',
				$db->quoteName('#__viewlevels', 'ag') . ' ON ' . $db->quoteName('ag.id') . ' = ' . $db->quoteName('a.access')
			);

 		return $query;
 	}

As a reminder, Joomla supports you in creating the database queries. If you use the available statements, Joomla will take care of security or different syntax in PostgreSQL and MySQL for you.

administrator/components/com_foos/ src/View/Foos/HtmlView.php

A button to create an element is only useful if this is allowed. Therefore we change the view - $canDo is added.

administrator/components/com_foos/ src/View/Foos/HtmlView.php

 \defined('_JEXEC') or die;

use Joomla\CMS\Helper\ContentHelper;
 use Joomla\CMS\Language\Text;
 use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
 use Joomla\CMS\Toolbar\Toolbar;

 	 */
 	protected function addToolbar()
 	{
		$canDo = ContentHelper::getActions('com_foos');

 		// Get the toolbar object instance
 		$toolbar = Toolbar::getInstance('toolbar');

 		ToolbarHelper::title(Text::_('COM_FOOS_MANAGER_FOOS'), 'address foo');

		$toolbar->addNew('foo.add');
		if ($canDo->get('core.create'))
		{
			$toolbar->addNew('foo.add');
		}

		$toolbar->preferences('com_foos');
		if ($canDo->get('core.options'))
		{
			$toolbar->preferences('com_foos');
		}
 	}

 }

administrator/components/com_foos/ tmpl/foo/edit.php

The entry <?php echo $this->getForm()->renderField(access); is necessary to include the field in the form, which we have already configured in the XML file. Only this way it is possible to change the permissions per element.

administrator/components/com_foos/ tmpl/foo/edit.php

 <form action="<?php echo Route::_('index.php?option=com_foos&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="foo-form" class="form-validate">
 	<?php echo $this->getForm()->renderField('name'); ?>
 	<?php echo $this->getForm()->renderField('alias'); ?>
	<?php echo $this->getForm()->renderField('access'); ?>
 	<input type="hidden" name="task" value="">
 	<?php echo HTMLHelper::_('form.token'); ?>
 </form>

administrator/components/com_foos/ tmpl/foos/default.php

Last but not least, we include a column in the overview for the authorization display.

administrator/components/com_foos/ tmpl/foos/default.php

 								<th scope="col" style="width:1%" class="text-center d-none d-md-table-cell">
 									<?php echo Text::_('COM_FOOS_TABLE_TABLEHEAD_NAME'); ?>
 								</th>
								<th scope="col" style="width:10%" class="d-none d-md-table-cell">
									<?php echo TEXT::_('JGRID_HEADING_ACCESS') ?>
								</th>
 								<th scope="col">
 									<?php echo Text::_('COM_FOOS_TABLE_TABLEHEAD_ID'); ?>
 								</th>

 										<?php echo $editIcon; ?><?php echo $this->escape($item->name); ?></a>

 								</th>
								<td class="small d-none d-md-table-cell">
									<?php echo $item->access_level; ?>
								</td>
 								<td class="d-none d-md-table-cell">
 									<?php echo $item->id; ?>
 								</td>

Note that I have not covered all cases here where permissions need to be handled. This description is intended as a best practice.

Test your Joomla component

  1. install your component in Joomla version 4 to test it:

Copy the files in the administrator folder to the administrator folder of your Joomla 4 installation.

Install your component as described in part one, after copying all files. Joomla will update the database for you during the installation.

  1. create a new item in your component. Make sure that you are offered a checkbox for saving a permission. The value you enter here will be saved with the item and can be queried when it is displayed in a list.

Joomla Configuration

  1. for a better overview the value is displayed in the main view.

Joomla Configuration

  1. open the options in the global configuration. Here you have the possibility to set the permissions for the use of the component itself.

Joomla Configuration

Play around with the settings. Allow once only the Super Admin to create new elements in your extension. Then log in as administrator and see that the 'New' button has disappeared.

Modify this post

Comments