0

When I create a change set, there is no option to pick the Contact.Email field. How can I deploy a standard field and include permissions for it?

4

There is currently no way to perform this task if you are exclusively using change sets. This is something which will have to be manually done via the point and click interface for every profile / field.

Here's an idea people voted on in order to support this feature.

ChangeSet functionality improvements
Globalization & Custom Schema

Would like to see the functionality to deploy standard objects via change sets.

This should include picklist changes and all page layouts.

It is frustrating that we need to replicate all picklist changes on standard objects when deploying from sandbox to live as changeset do not support standard objects.

Close Case page layout is missing from the changeset options and cannot be deployed.

It does not work properly for deploying email templates if they are in a sub folder. Even when adding the folder to the changeset it fails. the folder must manually be creating in the target ord before the change set can work.

That being said, there is a way to perform this task if you chose to use the metadata api. This does require either the use of tools such as Salesforce Migration Tool Kit, Eclipse (if the project is small enough), or 3rd party paid solutions which leverage the metadata api.

Here's some documentation in regards to what the profile metadata contains

You can retrieve and deploy access settings for the following managed components in profiles and permission sets:

  • Apex classes
  • Apps
  • Field permissions
  • Object permissions
  • Custom tab settings
  • External data sources
  • Record types
  • Visualforce pages

Documentation of Salesforce Migration Tool Kit

  • Can you include some relevant citations from those links? It will make your post much more accessible and durable over time (links can break). – Adrian Larson Feb 28 '17 at 22:32
1

With the below, it could be entirely possible that you could grab a profile from sandbox with all the necessary permissions and save it directly to production via an IDE (non-deploy, just compile and save) and it should do the same thing.....You would have to be extremely careful not to introduce artifacts that you do not want to update permissions for though.

Unfortunately, I do not have a production org I am able to test this out on, a bit of a scary prospect to do it without the safeguards of the deploy for profiles. ;)

Update Not sure if this is any better than manually doing it but I was able to to this using VF and JS. You will have to get the XML for the permissions but this shows that it works. Tested in a production NON DE org

Now that I think about it, would be cool if I built this out to allow the picking of object/field permission and selecting profiles to apply to and do it all in one shot......Could be a neat tool and if done right reduce the amount of clicks to apply field permission across multiple objects to multiple profiles at once

Setup to test:

  1. Create a profile named MyTest
  2. Ensure that the profile DOES NOT have access to the Contact.Description field - I used description before I saw you were using email
  3. Save profile
  4. Create a Remote Site Setting for the Visualforce URL you put in the page JS variable sfHost

VF Page

<apex:page id="Test_Metadata_Setup">

    <apex:includeScript value="{!URLFOR($Resource.[YOURJSRESOURCEHERE])}"/>

    <apex:form >
        <apex:commandButton onclick="updateProfileTest(function(msg){console.log(msg)}); return false" value="click me" reRender="msg"/>
    </apex:form>

    <script>
        var sessionId = '{!$Api.Session_ID}';
        var sfHost = 'xxxxx--c.na20.visual.force.com'; //Replace with you VF domain here excluding the https://
    </script>

</apex:page>

JS -- Put in a static resource

function getRequestHeader() {
    return '<?xml version="1.0" encoding="utf-8"?>' +
        '<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' +
        '<env:Header>' +
        '<urn:SessionHeader xmlns:urn="http://soap.sforce.com/2006/04/metadata">' +
        '<urn:sessionId>' + sessionId + '</urn:sessionId>' +
        '</urn:SessionHeader>' +
        '</env:Header>' +
        '<env:Body>';


}

function sendMetadataRequest(request, callback) {
    var binding = new XMLHttpRequest();

    binding.open('POST', 'https://' + sfHost + '/services/Soap/m/37.0');
    binding.setRequestHeader('SOAPAction', '""');
    binding.setRequestHeader('Content-Type', 'text/xml');
    binding.onreadystatechange =
        function () {
            if (this.readyState == 4) {
                var parser = new DOMParser();
                var doc = parser.parseFromString(this.response, 'application/xml');
                console.log(doc);

                var errors = doc.getElementsByTagName('errors');
                var faultstring = '';
                var messageText = '';

                faultstring = doc.getElementsByTagName('faultstring');

                if (faultstring.length != 0) {
                    messageText = faultstring[0].innerHTML;
                } else {
                    for (var errorIdx = 0; errorIdx < errors.length; errorIdx++)
                        messageText += errors.item(errorIdx).getElementsByTagName('message').item(0).innerHTML + '<br/>';
                }

                console.log(faultstring.length);

                console.log(errors.length != 0 || faultstring.length != 0);

                callback(
                    messageText == '' ? doc : ('Error ' + 'Making Configuration Changes: ' + messageText),
                );

            }
        };
    binding.send(request);

}

function updateProfileTest(callback) {

    var request =
        '<?xml version="1.0" encoding="utf-8"?>' +
        '<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' +
        '<env:Header>' +
        '<urn:SessionHeader xmlns:urn="http://soap.sforce.com/2006/04/metadata">' +
        '<urn:sessionId>' + sessionId + '</urn:sessionId>' +
        '</urn:SessionHeader>' +
        '</env:Header>' +
        '<env:Body>' +
        '<updateMetadata xmlns="http://soap.sforce.com/2006/04/metadata">' +

        '<metadata xsi:type="Profile">' +
        '<fullName>MyTest</fullName>' +
        '<fieldPermissions>' +
        '<editable>true</editable><field>Contact.Description</field><readable>true</readable>' +
        '</fieldPermissions>' +

        '</metadata>' +


        '</updateMetadata>' +
        '</env:Body>' +
        '</env:Envelope>';

    sendMetadataRequest(request, function (msg, err) {

            callback(msg);
    });
}

Then load the VF page and click the button. In the JS console you will see the output. You can then goto the profile you created and see that the profile now has access to the Contact.Description field

Note: Removed previous details as the other answer covers it

  • Thanks Eric, Can DreamFactory do that? – David Mycka Feb 28 '17 at 22:38
  • @DavidMycka - Doubt it, since it is all metadata API. I am going to throw a test together to see, gimme 30 mins or so – Eric Feb 28 '17 at 22:38
  • @DavidMycka - ok, I was able to do this in Prod via a VF page and JS Metadata API. Only downside it you have to get the FullName of the profile and the XML for the field permissions to build the string.....Updating answer – Eric Feb 28 '17 at 23:10
  • 1
    supposevely? I'm pretty sure this is why IdeaExchange needs a built-in spell-checker. – sfdcfox Feb 28 '17 at 23:15
  • @DavidMycka - answer updated. Make sure you replace the includeScript placeholder with the name of the JS file you save. Not sure if this is any better but hey, it was still fun – Eric Feb 28 '17 at 23:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.