4

Note: There is a related Salesforce Support Case #45059901


Convinced by the answers of some real ISV experts, I refactored my Managed Release Package from ugly Custom Settings to Custom Metadata with packaged records.

As proposed by many, I made the overall CMDT Public and the single record that comes with the package Protected. This way my app is open for customer records but I own my records and keep them behind a packaged setup UI.

Furthermore, I chose Field Manageability settings for the fields to be SubscriberEditable.

enter image description here

Updating such a record from a packaged setup UI in the subscriber org, fails with:

Not allowed to install or modify metadata via Apex

enter image description here

I am strongly convinced it is not a permission issue. Although the Customize Application and other permissions from the packaged Permset are lost mostly due to this Known Issue, the user still has a Full System Admin Profile which grants basically all rights.

I also make sure the DeveloperEditable field isIgnored during Metadata.Operations:

public static void persist(MyCMDT__mdt record) {
    String prefix = record.getSObjectType().getDescribe().getName().replace('__mdt', '');

    Metadata.CustomMetadata cmd = new Metadata.CustomMetadata();
    cmd.fullName = prefix + '.' + record.QualifiedApiName;
    cmd.label = record.MasterLabel;

    for (String fieldName : record.getPopulatedFieldsAsMap().keySet()) {
        if (isIgnored(fieldName)) {
            continue;
        }

        Metadata.CustomMetadataValue customField = new Metadata.CustomMetadataValue();
        customField.field = fieldName;
        customField.value = record.get(fieldName);

        cmd.values.add(customField);
    }

    Metadata.DeployContainer container = new Metadata.DeployContainer();
    container.addMetadata(cmd);

    Metadata.Operations.enqueueDeployment(container, new DeployCallback());
}
13
  • 1
    I will have a look see if I can spot a difference between our working set up and what you have. In the meantime, is your custom UI being invoked from a typical session for a normal admin user at some point after installation, or is it initiated from the package's post install page?
    – Phil W
    Aug 1 at 6:29
  • No post install scripts. Normal UI invoked by a User with App Admin permset. Is a SysAdmin now. My hope was that it can be a Standard user one day with the right permset. But anyhow it doesn't even work from a Sysadmin. Aug 1 at 7:58
  • Note: There is a related Salesforce Support Case #45059901 Aug 1 at 8:54
  • 1
    Looking at where we do this, the only difference I can see is that our custom metadata types are themselves "public" visibility, and we simply have "protected" records. We allow direct subscriber creation and management of extra records that are outside our namespace.
    – Phil W
    Aug 1 at 9:13
  • 1
    (I'm feeling really bad that you have taken my advice and it's causing a problem for you. We did hit various bumps, which I believe I flagged in the original Q&A, but not the issue you seem to have...)
    – Phil W
    Aug 1 at 11:07

2 Answers 2

3

Heaven (or Google) finally send me this article about Apex Metadata Deployments which states that:

When you develop a managed package, only certified packages are allowed to use this feature of deploying custom metadata records from Apex code.

There is “Deploy Metadata from Non-Certified Package Versions via Apex” checkbox setting, which enables beta packages to perform a custom metadata records deployment from Apex code. This checkbox can be found in Setup \ Build \ Develop \ Apex Settings menu in the setup configuration.

enter image description here

When I checked this box in any org where I installed the Managed Released Package Version everything worked as expected.

Because my Managed Package is not a Security Review approved one. Currently just an internal one.

The official Salesforce document describing the reason behind this is here.

Additionally, for managed packages, if the managed package is not approved by Salesforce via security review, Apex classes in the package cannot access metadata (public or protected) unless the Deploy Metadata from Non-Certified Package Versions via Apex org preference is enabled.

3
  • 1
    Was about to answer this for you but glad you got through it! Aug 1 at 18:51
  • @MohithShrivastava This would have saved me from 3 deprecated CMDT types an 10 Package Versions. ;-) Can you point me to a bit more detailed and official material please? Does that mean I need all internal orgs that use this tool to set this flag or go through a free Security Review? Aug 1 at 18:54
  • Shared the docs and other links in an another answer Aug 1 at 19:03
1

The official docs that describe why you need the setting is shared here

From the docs

Be aware of security considerations when accessing metadata using Apex. Generally, Apex classes installed in the subscriber org can access any public, supported metadata type or component in the subscriber org. Protected metadata, such as a custom metadata type that’s been marked protected, can only be accessed by Apex classes in the same namespace as the protected metadata.

Additionally, for managed packages, if the managed package is not approved by Salesforce via security review, Apex classes in the package cannot access metadata (public or protected) unless the Deploy Metadata from Non-Certified Package Versions via Apex org preference is enabled. This preference, located under Setup | Apex Settings, must be enabled if admins or developers are installing managed packages that haven’t passed security review for app testing or pilot purposes.

For deployments, because Metadata.Operations.enqueueDeployment() uses asynchronous Apex, queued deployment jobs and deployment callbacks are counted as asynchronous jobs in the current org. Queued deployment jobs and callbacks are subject to org limits on asynchronous Apex.

Apps that access metadata via Apex must notify users that the app can retrieve or deploy metadata in the subscriber org. For installs that access metadata, notify users in the description of your package. You can write your own notice, or use this sample:

This package can access and change metadata outside its namespace in the Salesforce org where it’s installed.

Salesforce verifies the notice during the security review.

You must log in to answer this question.

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