3

I'm building Visualfroce for updating Custom Metadata.

When User without required permissions tries to update them he gets error message

I tried checking MetadataType__mdt.getSObjectType().getDescribe().isUpdatable(), but it returns false even for System Admin.

I know that I can query Profile and all associated Permission Sets to check if User has CustomizeApplication System Permission, but maybe there is a better way.

Please share your insights if you know of any other way to check it in Apex.

UPDATE:

I've already implemented functionality for updating Custom Metadata using Metadata API.

This error is thrown by Visualforce if the page has and User doesn't have permission necessary to update Custom Metadata.

4 Answers 4

5

Custom Metadata Type records cannot be updated via direct DML like

update myCMTRecord;

by anyone, including system administrators, because that's not supported in Apex at all.

To modify Custom Metadata in Apex, you must use the Apex Metadata API to perform an asynchronous deploy operation.

The Apex Metadata API essentially passes security through to the underlying Metadata API:

Apex Metadata API deployments always respect Metadata API permissions. Although you can write Apex code that lets end users enqueue a deployment, that deployment fails if the users don’t have the correct Metadata API permissions.

which requires the Modify All Data and API Enabled permissions, or the beta Modify Metadata permission.

I'd suggest taking two tacks here:

  • Since there will soon be multiple ways to obtain access to the Metadata API, it's probably a more stable approach to expose the editing interface based on a higher-level grouping, like System Administrators only, or an org-specific permission set that you establish. Check for that qualification before allowing the user to begin editing, so that you can show a friendly error message.
  • Use a wrapper class to hold values that are intended to be persisted as a CMT record during the editing process and bind Visualforce components only to the wrapper class. This would allow you to centralize permission management in the method which initiates the metadata update or insert operation, where you'd convert those wrappers into actual CMT records to pass to Apex.
5
  • Thanks David for detailed response. I've already implemented functionality for updating Custom Metadata using Apex Metadata API. The question is how to handle the situation when a user doesn't have necessary permissions.
    – ytiq
    Commented Aug 22, 2018 at 11:24
  • Here what is shown in Debug Logs "04:23:18.0 (26463530)|EXCEPTION_THROWN|[EXTERNAL]|System.VisualforceException: Update access denied for External_Systems_Info__mdt, controller action methods may not execute."
    – ytiq
    Commented Aug 22, 2018 at 11:24
  • Could you please edit your question to make that context clear?
    – David Reed
    Commented Aug 22, 2018 at 11:38
  • thanks, I updated the question's description. Hopefully, it better describes the problem now
    – ytiq
    Commented Aug 22, 2018 at 11:43
  • thanks for your suggestions. I think we'll do it based on specific Permission Set
    – ytiq
    Commented Aug 22, 2018 at 13:42
1

I suggest querying UserPermissionAccess which only has the row of the current user:

public Boolean userCanEditMetadata() {
  UserPermissionAccess perm = [SELECT Id, PermissionsCustomizeApplication FROM UserPermissionAccess];
  return perm.PermissionsCustomizeApplication;
}
1
  • This works a treat, except for in unit tests - the perm throws an exception that the [SELECT] list was empty :/
    – zaitsman
    Commented Apr 27, 2020 at 11:35
0

You can't currently manipulate Custom Metadata Types from Apex as they are considered metadata.But can try using Metadata Api hoping this will work.

Updating Answer:

Before any DML operation you should check the user have permission to do this dml or not.

for this you can check isUpdateable() if this return true than do the DML operation otherwise skip it.

For instance, if a User can Create Cases, but not Edit them, then all Fields on Case will return false for isUpdateable, regardless of Field type or Field Level Security. Object security will trump.

Case.Subject.getDescribe().isAccessible() --> true; Case.Subject.getDescribe().isCreateable() --> true; Case.Subject.getDescribe().isUpdateable() --> false

3
  • Yes, but they still can be used in <apex:inputText> for example. And since Visualforce checks FLS it throws an error.
    – ytiq
    Commented Aug 22, 2018 at 11:30
  • thanks, but isUpdateable() is always false for Custom Metadata
    – ytiq
    Commented Aug 22, 2018 at 13:41
  • Yes, isUpdateable is always false for metadata because you can not update metadata values in apex. If above information is helpful upvote this Commented Aug 22, 2018 at 13:44
0

This is what we use. Works with both, Permsets and Profiles.

    public static Boolean canCreateMetadata(Id thisUserId) {
        try {
            User thisUser = [
                    SELECT
                        Profile.PermissionsModifyAllData, 
                        Profile.PermissionsModifyMetadata
                    FROM User
                    WHERE Id =: thisUserId];
            Integer perms = [
                SELECT
                    COUNT()
                FROM
                    PermissionSetAssignment
                WHERE
                    AssigneeId =: thisUserId
                    AND
                    (PermissionSet.PermissionsModifyAllData = TRUE OR PermissionSet.PermissionsModifyMetadata = TRUE)
            ];
            return thisUser.Profile.PermissionsModifyAllData || thisUser.Profile.PermissionsModifyMetadata || (perms>0);
        } catch (Exception e) {
            return false;
        }
    }

You must log in to answer this question.

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