Actions

Difference between revisions of "Adding ACL rules to your component"

From Joomla! Documentation

(Using Your Action Control In Code)
Line 173: Line 173:
 
}
 
}
 
</source>
 
</source>
 +
== Contributors ==
 +
[[User:mrs.siam|Prasit Gebsaap]]
 +
 +
[[Category:Development]]
 +
[[Category:Component Development]]
 +
[[Category:Tutorials]]
 +
[[Category:Access Control List]]
 +
[[Category:Joomla! 1.6]]
 +
[[Category:Joomla! 1.7]]

Revision as of 06:19, 5 December 2011

This tutorial will demonstrate how to add custom action permission to your component down to object level. Normally we familiar with ACL in global configuration level, category level and component level. Now we will learn how to add action permission control in our component. Joomla 1.6 Joomla 1.7

Contents

Using JTable To Handle Action Control Saving and Loading

JTable class has some built-in support for ACL, to use this you have to add one integer field in your table named 'asset_id'. This field will be used to perform action control for your object. Do not confused with 'access' field, that is only for access permission (read side) as Joomla! separates other actions from read acess.

Normally, we have to override __construct() method in our descendant class. We may also override check() method to validate our data before saving to database. For ACL action support we have to override these methods:-

  • public function bind($array, $ignore = ) to let JTable save rule data to Joomla's assets table.
  • protected function _getAssetName() to give asset name for our asset.
  • protected function _getAssetParentId($table = null, $id = null) to give parent id of our asset, normally Joomla! uses root (1) as a parent. Generally we will change parent of node to our component. Doing all of these made JTable handles storing and loading action controll setting for us.

JTable Example

class AstermanTableUnit extends JTable
{
        public function __construct($db)
        {
                parent::__construct('#__asterman_units', 'id', $db);
        }
 
        public function bind($array, $ignore = '')
        {
                // Bind the rules. 
                if (isset($array['rules']) && is_array($array['rules'])) { 
                        $rules = new JRules($array['rules']); 
                        $this->setRules($rules); 
                }
                return parent::bind($array, $ignore);
        }
 
        /**
         * Redefined asset name, as we support action control
         */
        protected function _getAssetName() {
                $k = $this->_tbl_key;
                return 'com_asterman.unit.'.(int) $this->$k;
        }
 
        /**
         * We provide our global ACL as parent
         * @see JTable::_getAssetParentId()
         */
        protected function _getAssetParentId($table = null, $id = null)
        {
                $asset = JTable::getInstance('Asset');
                $asset->loadByName('com_asterman');
                return $asset->id;
        }
 
}

Add Rules Field to Your Form

Next, we have to add two fields to our form so we will have action control setting input in the view. The first one is 'asset_id' and its type is hidden. This is same name as we provide in our table. The second one is 'rules' and its type is rules. We have to provide this name as it will be processed by JTable descandant class. Please see JTable class for more detail.

        <fieldset name="accesscontrol">
 
                <field name="asset_id" type="hidden" filter="unset" /> 
 
                <field
                        name="rules"
                        type="rules"
                        label="JFIELD_RULES_LABEL"
                        translate_label="false"
                        filter="rules"
                        validate="rules"
                        class="inputbox"
                        component="com_asterman"
                        section="unit" />
        </fieldset>

For rules field type, we have to provide component attribute as our component name and section attribute according to section define in our access.xml. Please see the example below.

<?xml version="1.0" encoding="UTF-8"?>
<access component="com_asterman">
        <section name="component">
        <!-- Actions to be used in our global component -->
                <action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
                <action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
                <action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
                <action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
                <action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
                <action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
                <action name="core.edit.own" title="JACTION_EDITOWN" description="JACTION_EDITOWN_COMPONENT_DESC" />
        </section>
        <section name="unit">
        <!-- Actions to be used in for unit -->
                <action name="core.create" title="JACTION_CREATE" description="COM_ASTERMAN_ACTION_CREATE_UNIT_DESC" />
                <action name="core.delete" title="JACTION_DELETE" description="COM_ASTERMAN_ACTION_CREATE_UNIT_DESC" />
                <action name="core.edit" title="JACTION_EDIT" description="COM_ASTERMAN_ACTION_EDIT_UNIT_DESC" />
                <action name="asterman.edit.basic" title="COM_ASTERMAN_ACTION_EDITBASIC" description="COM_ASTERMAN_ACTION_EDITBASIC_DESC" />
                <action name="core.edit.state" title="JACTION_EDITSTATE" description="COM_ASTERMAN_ACTION_EDITSTATE_UNIT_DESC" />
                <action name="core.edit.own" title="JACTION_EDITOWN" description="COM_ASTERMAN_ACTION_EDITOWN_UNIT_DESC" />
        </section>    
</access>

You will see that I have also create new action for my component. The "asterman.edit.basic" action is to control if user has right to edit some part of the record or not.

Using Your Action Control In Code

Using action control in your code is easy than you think, we use JUser 's method to do this. This method is authorise() which requires two parameters one is action and second one is assest name. Unlike our global component access control, here we refer to asset name per record, please JTable descandant class above.

      JFactory::getUser()->authorise($action, $assetName);

This is example of JModelAdmin descandant class that use this function.

public function getForm($data = array(), $loadData = true)
{
        // Get the form.
        $form = $this->loadForm('com_asterman.extension', //form name 
                'extension', //XML file name 
                array(
                        'control' => 'jform', 
                        'load_data' => $loadData
                ));
 
        if (empty($form)) {
                return false;
        }
 
        if ($this->getState('suffix')=='14') {
                // theses fields does not exists in Asterisk version 1.4
                $form->setFieldAttribute('call-limit', 'disabled', 'true');
                $form->setFieldAttribute('call-limit', 'filter', 'unset');
        }
 
        $user = JFactory::getUser();
 
        if (!empty($data['unit_id'])) {
                $assetName = $this->option.'.unit.'.$data['unit_id'];
 
                $canEdit = $user->authorise('core.edit', $assetName);
                $canEditBasic = $user->authorise('asterman.edit.basic', $assetName);
                $canEditState = $user->authorise('core.edit.state', $assetName);
        }else{
                $canEdit = $user->authorise('core.create', $this->option);
        } 
 
        if ( !$canEdit ) {
 
                $form->setFieldAttribute('unit_id', 'disabled', 'true');
                $form->setFieldAttribute('unit_id', 'filter', 'unset');
 
                if ( !$canEditBasic ) {
                        $form->setFieldAttribute('callerid', 'disabled', 'true');
                        $form->setFieldAttribute('secret', 'disabled', 'true');
                        $form->setFieldAttribute('allow', 'disabled', 'true');
                        $form->setFieldAttribute('callgroup', 'disabled', 'true');
                        $form->setFieldAttribute('pickupgroup', 'disabled', 'true');
                        $form->setFieldAttribute('call-limit', 'disabled', 'true');
 
                        $form->setFieldAttribute('callerid', 'filter', 'unset');
                        $form->setFieldAttribute('secret', 'filter', 'unset');
                        $form->setFieldAttribute('allow', 'filter', 'unset');
                        $form->setFieldAttribute('callgroup', 'filter', 'unset');
                        $form->setFieldAttribute('pickupgroup', 'filter', 'unset');
                        $form->setFieldAttribute('call-limit', 'filter', 'unset');
                }
                // Modify the form based on access controls.
                if ( !$canEditState ) {
                        // Disable fields for display.
                        $form->setFieldAttribute('host', 'disabled', 'true');
                        $form->setFieldAttribute('context', 'disabled', 'true');        
 
                        // Disable fields while saving.
                        // The controller has already verified this is a record you can edit.
                        $form->setFieldAttribute('host', 'filter', 'unset');
                        $form->setFieldAttribute('context', 'filter', 'unset');
                }
        }
 return $form;
}

Contributors

Prasit Gebsaap