3

I have a Managed Package where I have Custom Object called Transaction and Apex Rest Resource for creating this object.

The Resource Code:

@RestResource(urlMapping='/v1/transaction/*')
global with sharing class TransactionRestResource{
    @HttpPost
    global static void createTransaction() {
        Transaction__c tran = new Transaction__c();
        // mapping some fields 
        insert tran;
    }
}

And I have Apex Method which calls this API from my Dev Org

Code:

public class TransactionRestResource{
    @AuraEnabled
    public static void createTransactionRecord(String json){
        System.RestContext.request = new RestRequest();
        RestContext.request.requestURI = '/v1/transaction/';
        RestContext.request.requestBody = Blob.valueOf(json);
        PackageName.TransactionRestResource.createTransaction();
    }
}

And I call this method on button click from the simplest LWC in DEV org.

----- The Problem: ------

If a user does NOT have create access to Transaction__c object, and presses the button the record is created without any errors. And this user marked as Created By.

From my understanding:
When we use with sharing keyword it should run in a user mode and throw an error here that a user does not have the access to create record.

I checked Object Permission records and this user does not have any access to the Custom Object.

I reviewed next docs:

------ Question: -----

So I want to know why it works in this way ?
I don't want a solution, but rather understand the cause of such behavior.
What can cause such behavior ? Is it something from sharing, Rest Resource or Managed Package ?

Any help will be appreciated

1 Answer 1

4

The default security mode for Apex does not check a user's object or field permissions, it only checks if the user has read, write, or owner permissions as determined by the sharing model. There are at least three easy solutions to this.


The simplest method is to add the as user keyword.

@RestResource(urlMapping='/v1/transaction/*')
global with sharing class TransactionRestResource{
    @HttpPost
    global static void createTransaction() {
        Transaction__c tran = new Transaction__c();
        // mapping some fields 
        insert tran as user;
    }
}

An exception will be thrown for users without access to the object.


You can also do this with the new AccessLevel feature:

Database.insert(tran, AccessLevel.USER_MODE);

Or, if you were developing for an older package, you should be using the appropriate describe information:

if(!sObjectType.Transaction__c.isAccessible()) {
  throw new SecurityException(); // Or similar
}

If you use none of these methods, you'd fail a Security Review, because of the exact reason you outlined--a user could do things they couldn't otherwise do through loopholes like this one.

2
  • Wow, you saved me tons of time again! Thank you so much. May 1, 2023 at 16:14
  • @VitaliiDehnerys No problem. Glad I could help.
    – sfdcfox
    May 1, 2023 at 16:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .