A general practice of defining a controller is to prepend “with sharing” key word to “class”. This is to enforce the sharing rules that apply to the current user as otherwise sharing rules aren’t taken into account during code execution. Recently in a project I came across a requirement in which “without sharing” plays a role.
We have a custom object called “Payment” and a Approval Process is defined on this object. The requirement is that system should allow any users other than the user who submitted Payments for approval to bulk approve or reject Payment approval requests. Originally we focused on implementation of bulk approve/reject logic. We created a custom controller and a Visualfore page to did all it needs. It felt so good that we could programmatically approve/reject approval requests in a bulk in Apex code. But we got a bug from the customer saying “It only allows the manager of the users who submitted Payments for approval to approve/reject the Payments”. When other users are approving/rejecting Payments, they get the following error:
Process failed. First exception on row 0; first error: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, insufficient access rights on cross-reference id: 
The debug log shows that this error is thrown when Approval.process() method is invoked. This actually makes sense as the controller class has “with sharing” declared. Normally if a user submitted an object for approval, only the user that is assigned to this approval request (usually the manger of the submitting user) has the access rights to corresponding Approval Process work items. Other users won’t even be able to see the actions links on the form. Since the approval requests are programmatically processed via a page and a “with sharing” controller, a random person will be able to run the code but does surely not have the access rights to Approval Process work items. This is proved by the Salesforce documentation on Using the “with sharing” or “without sharing” Keywords. Related statement:
Enforcing the current user’s sharing rules can impact:
- SOQL and SOSL queries. A query may return fewer rows than it would operating in system context.
- DML operations. An operation may fail because the current user doesn’t have the correct permissions. For example, if the user specifies a foreign key value that exists in the organization, but which the current user does not have access to.
So I got back to the controller, changed the “with” to “without” and it fixed the problem. However, all related Profile based security rules should be programmatically implemented. The profile setting on access to the corresponding Visualforce page can be used to do a basic protection on access to this “bulk approve/reject” functionality.