How do I HIDE the DELETE item in the LIST ACTIONS dropdown?

Tried adding a custom ACL to disallow DELETE as per

https://enricosimonetti.com/powerful-customisations-with-sugars-acl/

but this does NOT seem to work when I try it on Sugar 13.0.3

custom\Extension\modules\Contacts\Ext\Vardefs\acl.php

$dictionary['Contacts']['acls']['SugarACLDenyDelete'] = true;

custom\data\acl\SugarACLDenyDelete.php

class SugarACLDenyDelete extends SugarACLStrategy {
	// allowed user ids
    protected $user_ids_to_allow = array(
    );

    // denied actions: example was READ-ONLY, we want to deny only DELETE
    protected $denied_actions = array(
        //'edit',
        'delete',
        //'massupdate',
        //'import',
    );

    // our custom method to check permissions
    protected function _canUserWrite($context)
    {
        // retrieve user from context
        $user = $this->getCurrentUser($context);

        // allow only admin users or special users access
        if(/*$user->isAdmin() || */in_array($user->id, $this->user_ids_to_allow)) { //we DENY to ADMINS too
            return true;
        } else {
            return false;
        }
    }

    // runtime access check
    public function checkAccess($module, $view, $context)
    {
        $view = SugarACLStrategy::fixUpActionName($view);
        // if it is not a blocked action, or there is no bean, allow it
        if(!in_array($view, $this->denied_actions) || !isset($context['bean'])) {
            return true;
        }

        // can user write?
        if($this->_canUserWrite($context)) return true;

        // everyone else for everything else is denied
        return false;
    }

    // mostly for front-end access checks (cached on the application, per user)
    public function getUserAccess($module, $access_list = array(), $context = array())
    {
        // retrieve original ACL
        $acl = parent::getUserAccess($module, $access_list, $context);

        // if user can't write
        if(!$this->_canUserWrite($context)) {
            // override access, disable access where required if not admin and not special user
            foreach($acl as $access => $value) {
                if(in_array($access, $this->denied_actions)) {
                    $acl[$access] = 0;
                }
            }
        }

        // return modified acl
        return $acl;
    }
}

Can anyone point me to a way that works in v13+?

  • This is likely not the best way to do this, but it is a way...

    That delete button is part of the action dropdown list in the record view metadata for the module. One way to get rid of it is to edit/create a custom Contacts record viewdef (custom/modules/Contacts/clients/base/views/record/record.php) and in that file, look for:

                    [
                        'type' => 'rowaction',
                        'event' => 'button:audit_button:click',
                        'name' => 'audit_button',
                        'label' => 'LNK_VIEW_CHANGE_LOG',
                        'acl_action' => 'view',
                    ],
                    [
                        'type' => 'divider',
                    ],
                    [
                        'type' => 'rowaction',
                        'event' => 'button:delete_button:click',
                        'name' => 'delete_button',
                        'label' => 'LBL_DELETE_BUTTON_LABEL',
                        'acl_action' => 'delete',
                    ],
    

    From there, remove the last array member ('name' => 'delete_button') as well as the divider entry above it. Save the file to custom/modules/Contacts/clients/base/views/record/record.php and do a Quick Repair and Rebuild. That should remove the delete button from view entirely. You should still set up roles to handle the delete action on API calls as other clients can still send a delete request.

    I am guessing there are more elegant ways to achieve this through the extension framework, and I would highly recommend you use the extension framework for this. Hopefully this gives you some insight on one way to achieve what you want though.

    Robert Gonzalez

    Senior Director, Engineering

    Sugar Sell, Sugar Serve, Sugar Mobile

  • Hello  , 

    I still believe that the buttons shouldn't be showing up after restricting the ACL, especially given this parameter in the button definition:

    'acl_action' => 'delete',

    I'm not sure why or how it's appearing in the screenshot you shared—are you using an admin user or perhaps a user with admin access to Contacts?

    If you'd like, feel free to send me a message, and I'd be happy to help you figure out why this might not be working as expected.

    By the way, just a quick tip: if you restrict DELETE via ACL, you don’t need to add a custom exception. Sugar will automatically prevent deletions through the API endpoint as well.

    Hope this helps!

    Cheers,
    André