· tutorials · 4 min read

How to Prevent Users Deleting Files in Salesforce

Learn how to prevent specific users from deleting files in Salesforce.

Learn how to prevent specific users from deleting files in Salesforce.

Salesforce has very granulated permissions that can control almost every aspect of a user’s experience. Unfortunately, the ability to prevent file deletion is not on that list. Users have been asking for this feature since 2008. It is possible to prohibit users from uploading and deleting files. But, to prevent users from deleting files, we need to put in place some apex code.

Requirements

You will need Enterprise edition or more to put in place this in Salesforce.

Creating a Custom Permission

Salesforce’s robust permission structure can be extended. We can create our own custom permissions. To do so:

  1. Go to Setup -> Custom Permission
  2. Create a custom permission called Delete Files

Additionally, we need a way to assign this to end users. With Salesforce sun-setting profiles in Spring ‘26, we should use permission sets to assign to users.

To assign the custom permission, perform the following:

  1. Create a permission set Delete Files.
  2. Add the custom permission to the permission set
  3. Assign to desired Users

Prevent Users From Deleting Files In Salesforce

Now it’s time to create the apex code that will prevent file deletion. The code will

  • Run every time a file ContentDocument is being deleted
  • Check if the current user has the Delete Files permission
  • If so, the file will be deleted.
  • If not, the file will not be deleted, and an error will ocurr.

We need to create a few classes to perform these tasks. This is to keep the code organized inside of Salesforce. First, we want to create an Apex class ContentDocumentException

public class ContentDocumentException extends Exception {}

This will allow us to throw a custom exception (error) when the end user does not have the required permissions.

Next, we want to create a class ContentDocumentTriggerHandler

public class ContentDocumentTriggerHandler {
  public static void beforeDeleteTriggerHandler(
    List<ContentDocument> contentDocumentList
  ) {
    if (!FeatureManagement.checkPermission('Delete_Files')) {
      throw new ContentDocumentException(
        'Cannot Delete File without the Delete Files Permission'
      );
    }
  }
}

This class will hold all the logic to see if a file is deleted.

Finally, we want to run this code every time a file is delete. We can do so by creating the trigger, ContentDocumentTrigger:

trigger ContentDocumentTrigger on ContentDocument(before delete) {
  if (Trigger.isBefore && Trigger.isDelete) {ContentDocumentTriggerHandler.beforeDeleteTriggerHandler(Trigger.old);
  }
}

Testing The Apex Code

To push this code to production, we need a test class that get’s at least 75% code coverage. To test this code, we can use the following class ContentDocumentTriggerTest

@isTest
public class ContentDocumentTriggerTest {
  @isTest(seeAllData=false)
  static void testDeleteWithPermission() {
    Profile p = [SELECT Id FROM Profile WHERE Name = 'Standard User'];

    User u1 = new User(
      Alias = 'newUser',
      Email = 'newuser@testorg.com',
      EmailEncodingKey = 'UTF-8',
      LastName = 'Testing',
      LanguageLocaleKey = 'en_US',
      LocaleSidKey = 'en_US',
      ProfileId = p.Id,
      TimeZoneSidKey = 'America/Los_Angeles',
      UserName = 'newuser@testorg.com'
    );

    String message;
    System.runAs(u1) {
      try {
        ContentVersion contentVersion = new ContentVersion(
          Title = 'Test',
          PathOnClient = 'test.jpg',
          VersionData = Blob.valueOf('Test Content'),
          IsMajorVersion = true
        );
        insert contentVersion;
        List<ContentDocument> documents = [
          SELECT Id, Title, LatestPublishedVersionId
          FROM ContentDocument
        ];
        delete documents;
      } catch (Exception e) {
        message = e.getMessage();
      }

      system.assert(
        message.contains(
          'Cannot Delete File without the Delete Files Permission'
        ) != null
      );
    }
  }

  @isTest(seeAllData=false)
  static void testDeleteWithoutPermission() {
    Profile p = [SELECT Id FROM Profile WHERE Name = 'Standard User'];

    User u1 = new User(
      Alias = 'newUser',
      Email = 'test@test.com',
      EmailEncodingKey = 'UTF-8',
      LastName = 'Testing',
      LanguageLocaleKey = 'en_US',
      LocaleSidKey = 'en_US',
      ProfileId = p.Id,
      TimeZoneSidKey = 'America/Los_Angeles',
      UserName = 'test@test.com'
    );
    insert u1;

    PermissionSet ps = [
      SELECT Id
      FROM PermissionSet
      WHERE Name = 'Delete_Files'
    ];

    PermissionSetAssignment psa = new PermissionSetAssignment(
      AssigneeId = u1.Id,
      PermissionSetId = ps.Id
    );

    insert psa;

    String message;
    System.runAs(u1) {
      ContentVersion contentVersion = new ContentVersion(
        Title = 'Test',
        PathOnClient = 'Test.jpg',
        VersionData = Blob.valueOf('Test Content'),
        IsMajorVersion = true
      );
      insert contentVersion;
      List<ContentDocument> documents = [
        SELECT Id, Title, LatestPublishedVersionId
        FROM ContentDocument
      ];
      try {
        delete documents;
      } catch (ContentVersionException e) {
        message = e.getMessage();
      }

      system.assertEquals(
        null,
        message,
        'User w/o custom permission should not be able to delete files'
      );
    }
  }
}

Each method will:

  1. Run as a new user.
  2. Create a new file.
  3. Attempt to delete the file.

Keep in mind that you may need to change the username to a unique value to get this working in your organization.

Conclusion

Salesforce does not have a native way of preventing file deletion. We can use Apex code and custom permissions to put in place file deletion ourselves.

Need Our Help To Get Your Data Into Salesforce?

Join dozens of other companies by learning how you can get all your company's data in one place.

Share:
Back to Blog