3

Calling the metadata API in Apex requires admin permission (or at least the "Modify All Data" access). To run the code as a non-admin user I am thinking I need to first login as the sys admin, get a session ID, pass it to the request header, and then make the call. The problem is, I don't know how to do it inside Apex!

More precisely I need the readMetadata() method in the Metadata API to run as an admin user. Here's how the method currently looks:

    public MetadataAPI.IReadResult readMetadata(String type_x,String[] fullNames) {
        MetadataAPI.readMetadata_element request_x = new MetadataAPI.readMetadata_element();
        request_x.type_x = type_x;
        request_x.fullNames = fullNames;
        MetadataAPI.IReadResponseElement response_x;
        Map<String, MetadataAPI.IReadResponseElement> response_map_x = new Map<String, MetadataAPI.IReadResponseElement>();
        response_map_x.put('response_x', response_x);
        WebServiceCallout.invoke(
          this,
          request_x,
          response_map_x,
          new String[]{endpoint_x,
          '',
          'http://soap.sforce.com/2006/04/metadata',
          'readMetadata',
          'http://soap.sforce.com/2006/04/metadata',
          'readMetadataResponse',
          'MetadataAPI.read' + type_x + 'Response_element'}
        );
        response_x = response_map_x.get('response_x');
        return response_x.getResult();
    }

Basically it's about unwrapping the WebServiceCallout class (it's what SF uses to call its API), putting the session ID into its header, and then re-wrapping it.

Let me know if you have any ideas to share!

2
  • 1
    Why do you want to do this? Seems like it's be easier to just grant the user(s) in question the permission needed?
    – Matt Lacey
    Mar 4 '15 at 6:24
  • Because I want to replicate listviews in our portal app, and to get listviews we need to use the metadata api.
    – Mossi
    Mar 4 '15 at 18:46
4

The Wsdl2Apex based class will include some additional parts that identify the session.

There will be an inner class that contains the readMetadata method. It will probably be called something like MetadataPort or MetadataService. This class will include members like:

public soapSforceCom200604Metadata.SessionHeader_element SessionHeader;
private String SessionHeader_hns = 'SessionHeader=http://soap.sforce.com/2006/04/metadata';

It SessionHeader here contains the active SessionId of the user who is making the request. If you replace the value with the SessionId of a user with the "Modify All Data" permission then the call should succeed.

The trick then becomes how does a non-admin user get a valid admin users session.

If you had access to the admin users credentials, say via a protected custom setting that is hidden in a managed package, then you could call the login method via the Partner API to get a valid session.

Better yet, try using an oAuth flow to get a refresh token that can be used to get a valid session id. That way you only need to securely store the refresh token rather than the admins un and pw.

0

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.