I'm getting some issues making my permission set works.
This is the use case. I have:
- A custom object with a single field and a button.
- Above button call a vf page that shows a button that execute a process
- Controller related to above vf page and runJob method that create some records, update them and delete a single record.
- A permission set with CRUD access but no ViewAll and ModifyAll checked. It has access to above vf page too.
- Object sharing settings are public Write/Read
- Grant access using hierarchies false
- A user related to a profile that has no access to anything (only custom object tab visibility)
- Permission Set is assigned to the user
Having above scenario, admin creates some records and run the job via the button.
If I login as the second user and open a record that was created by the admin, and run the process via the button I get this error:
If I try it manually, Update and Creation is ok, but Delete fails.
If I set ModifyAll value as true in the permission set, then I can execute my process without issues.
Why I cannot delete a record that other user has created? My object is public and the permission set gives me CRUD access. What am I missing?
This is the code just in case you want to reproduce by yourself
Controller
public with sharing class A_TestSecurityController
{
private Id recordId;
private ApexPages.StandardController theController;
public A_TestSecurityController(ApexPages.StandardController controller)
{
theController = controller;
recordId = theController.getId();
}
public PageReference runJob()
{
try
{
List<TestSecurity__c> listToUpdate = new List<TestSecurity__c>();
for(TestSecurity__c item : [Select Id, Check__c From TestSecurity__c])
{
item.Check__c = false;
listToUpdate.add(item);
}
update listToUpdate;
TestSecurity__c item = [Select Id From TestSecurity__c limit 1];
delete item;
List<TestSecurity__c> listToInsert = new List<TestSecurity__c>();
for(integer i=0; i<3; i++)
{
TestSecurity__c newItem = new TestSecurity__c();
listToInsert.add(newItem);
}
insert listToInsert;
return theController.view();
}
catch(Exception ex)
{
ApexPages.addMessages(ex);
return null;
}
}
}
Visualforce
<apex:page standardController="TestSecurity__c" extensions="A_TestSecurityController" >
<apex:form >
<apex:sectionHeader title="Test Security"/>
<apex:pageBlock title="Information">
<apex:pageBlockButtons >
<apex:commandButton value="Run Job" action="{!runJob}"/>
<apex:commandButton value="Cancel" action="{!cancel}"/>
</apex:pageBlockButtons>
<apex:pageMessages />
<apex:pageMessage summary="Please confirm you wish to start the job?" severity="info" strength="2" />
</apex:pageBlock>
</apex:form>
</apex:page>
Thanks
Best Answer
You're missing "full" control of the record.
The levels of control are, in ascending order:
Each level of control implies the additional permissions that are lower than that, unless prohibited by the profile.
Full control can generally only be granted by:
See the Help & Training modules on Sharing for more details, as well as other answers here on the SFSE.
"Full" control is also referred to as "Owner" permissions when viewed in Sharing, but basically just means "Delete", as that is the only additional permission it grants. You can have Transfer independently of Delete on some objects by Sharing Rules or Organization Wide Defaults, and you're also explicitly granted Transfer when a record is owned by a queue you are a member of or is in the same Territory as you with Territory Management and the appropriate settings.
As an exception to granting Full access, the "Financial Edition" of salesforce.com, used by companies like Merrill Lynch, offers the ability to create sharing rules that grant Full access to a record despite not meeting the usual criteria.