Implementing access control on breeds form and single record page.
Files to create / update
update breedform.php /site/models/breedform.php
update default.php /site/views/breed/tmpl/default.php
update breed.php /site/controllers/breed.php
File Details
/site/models/breedform.php
public function delete($data)
{
$id = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('breed.id');
if (JFactory::getUser()->authorise('core.delete', 'com_breed.breed.' . $id) !== true)
{
throw new Exception(403, JText::_('JERROR_ALERTNOAUTHOR'));
}
$table = $this->getTable();
if ($table->delete($data['id']) === true)
{
return $id;
}
else
{
return false;
}
}
public function getCanSave()
{
$table = $this->getTable();
return $table !== false;
}
public function &getData($id = null)
{
if ($this->item === null)
{
$this->item = false;
if (empty($id))
{
$id = $this->getState('breed.id');
}
$table = $this->getTable();
if ($table !== false && $table->load($id))
{
$user = JFactory::getUser();
$id = $table->id;
if ($id)
{
$canEdit = $user->authorise('core.edit', 'com_breed. breed.' . $id) || $user->authorise('core.create', 'com_breed. breed.' . $id);
}
else
{
$canEdit = $user->authorise('core.edit', 'com_breed') || $user->authorise('core.create', 'com_breed');
}
if (!$canEdit && $user->authorise('core.edit.own', 'com_breed.breed.' . $id))
{
$canEdit = $user->id == $table->created_by;
}
if (!$canEdit)
{
throw new Exception(JText::_('JERROR_ALERTNOAUTHOR'), 500);
}
// Check published state.
if ($published = $this->getState('filter.published'))
{
if ($table->state != $published)
{
return $this->item;
}
}
$properties = $table->getProperties(1);
$this->item = ArrayHelper::toObject($properties, 'JObject');
}
}
return $this->item;
}
public function save($data)
{
$id = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('breed.id');
$state = (!empty($data['state'])) ? 1 : 0;
$user = JFactory::getUser();
if ($id)
{
$authorised = $user->authorise('core.edit', 'com_breed.breed.' . $id) || $authorised = $user->authorise('core.edit.own', 'com_breed.breed.' . $id);
if ($user->authorise('core.edit.state', 'com_breed.breed.' . $id) !== true && $state == 1)
{
$data['state'] = 0;
}
}
else
{
$authorised = $user->authorise('core.create', 'com_breed');
if ($user->authorise('core.edit.state', 'com_breed.breed.' . $id) !== true && $state == 1)
{
// The user cannot edit the state of the item.
$data['state'] = 0;
}
}
if ($authorised !== true)
{
throw new Exception(JText::_('JERROR_ALERTNOAUTHOR'), 403);
}
$table = $this->getTable();
if ($table->save($data) === true)
{
return $table->id;
}
else
{
return false;
}
}
}
In this step of the tutorial, we are trying to implement ACL for the breed entry form and single record page, so that only our desired user group should be able to make or edit an entry or be able to view a record.
So, to implement access control to the breed form, first open the breedform.php model file located in the site/models folder. As you can see in the above mentioned code, we have simply added the access control code before every operation that is carried out, like editing, deleting or creating. Like, in the delete () method of the breedform.php file, on line 46, we are making a check to whether the user who is trying to delete a record actually has the rights assigned to do so. Similarly, in the getData () method, we have implemented can edit and can edit their own check so that only the user group with assigned rights should be able to perform these operations. Now, coming to the save method, where we have restricted operations like editing, creating and editing states to only allowed groups.
/site/controllers/breed.php
public function remove()
{
$app = JFactory::getApplication();
$user = JFactory::getUser();
if ($user->authorise('core.delete', 'com_breed'))
{
$model = $this->getModel('Breed', 'BreedModel');
$id = $app->input->getInt('id', 0);
// Attempt to save the data.
$return = $model->delete($id);
if ($return === false)
{
$this->setMessage(JText::sprintf('Delete failed', $model->getError()), 'warning');
}
else
{
$app->setUserState('com_breed.edit.breed.id', null);
// Flush the data from the session.
$app->setUserState('com_breed.edit.breed.data', null);
$this->setMessage(JText::_('COM_BREED_ITEM_DELETED_SUCCESSFULLY'));
}
$menu = JFactory::getApplication()->getMenu();
$item = $menu->getActive();
$this->setRedirect(JRoute::_($item->link, false));
}
else
{
throw new Exception(500);
}
}
Now, in order to make ACL work on a single breed page, open the breed.php controller file, located in the controllers folder, and make the changes as shown in the above code. As you know, we have also included the delete a record functionality on the single breed page, so that the user can delete the record without going back to the listing page. So, now, in the delete () method of the controller file, on line 9 of the above code, we are making a check to whether the user group to which the user who is trying to delete a record belongs is actually allowed to execute this process. If it is not allowed, simply an exception will be thrown. So, making ACL work in Joomla is really a simple process.
/site/views/breed/tmpl/default.php
<?php
// No direct access
defined('_JEXEC') or die;
$canEdit = JFactory::getUser()->authorise('core.edit', 'com_breed.' . $this->item->id);
if (!$canEdit && JFactory::getUser()->authorise('core.edit.own', 'com_breed' . $this->item->id)) {
$canEdit = JFactory::getUser()->id == $this->item->created_by;
}
?>
<?php if ($this->item) : ?>
<div class="row" style="padding:24px;">
<h2> <?php echo JText::_('COM_BREED_FORM_LBL_BREED_BREEDNAME'); ?> :
<?php echo $this->item->breedname; ?> </h2> <br>
<div class="span4">
<?php
foreach ((array) $this->item->pic as $singleFile) :
if (!is_array($singleFile)) :
$uploadPath = 'components'.DIRECTORY_SEPARATOR.'com_breed'.DIRECTORY_SEPARATOR.'breedpic' . DIRECTORY_SEPARATOR . $singleFile;
echo '<a href="' . JRoute::_(JUri::root() . $uploadPath, false) . '" target="_blank"><img src="' . JRoute::_(JUri::root() . $uploadPath, false) . '" width="98%"></a> ';
endif;
endforeach;
?>
</div>
<div class="span7">
<b><?php echo JText::_('COM_BREED_FORM_LBL_BREED_BREEDCAT'); ?> : </b>
<?php echo $this->item->breedcat; ?> <br><br>
<b> <?php echo JText::_('COM_BREED_FORM_LBL_BREED_SHORTDESC'); ?> : </b>
<?php echo $this->item->shortdesc; ?>
<br><br>
<b> <?php echo JText::_('COM_BREED_FORM_LBL_BREED_DESC'); ?>: </b>
<?php echo $this->item->desc; ?>
</div>
</div>
<div style="width:99%;" align="center">
<?php if($canEdit && $this->item->checked_out == 0): ?>
<a class="btn" href="/nomi/<?php echo JRoute::_('index.php?option=com_breed&task=breed.edit&id='.$this->item->id); ?>"><?php echo JText::_("COM_BREED_EDIT_ITEM"); ?></a>
<?php endif; ?>
<?php if(JFactory::getUser()->authorise('core.delete','com_breed.breed.'.$this->item->id)):?>
<a class="btn" href="/nomi/<?php echo JRoute::_('index.php?option=com_breed&task=breed.remove&id=' . $this->item->id, false, 2); ?>"><?php echo JText::_("COM_BREED_DELETE_ITEM"); ?></a>
<?php endif; ?>
</div>
<?php
else:
echo JText::_('COM_BREED_ITEM_NOT_LOADED');
endif;
Now we are trying to control the display of delete and edit buttons on the single record listing page, so that they should only appear to authorized users. In order to make this happen, we have added some ACL code to the default.php template file, located in the/site/views/breed/tmpl folder. As you can see, on line 6 to 8, we have initialized the $canEdit variable, which will determine whether the current user is allowed to edit any record or whether he can only edit his own created record. Next, we have implemented this and the second check, $canDelete on the two buttons, edit and delete, respectively, as shown at the end of the file.