Running Metadata API in Apex as a specific user

Running Metadata API in Apex as a specific user

Calling the metadata API in Apex requires admin permission or at least the “Modify All Data” permission. To run the code as a non-admin user, you need to first login as the system administrator, get a session ID, pass it to the request header, and then make the call.

To achieve this, we can call SOAP API of Partner or Enterprise WSDL for login as the system administrator, get a session ID and then pass it to the request header, and then make a call.

Steps for obtaining partner and metadata wsdl and then create a webservice class from it.
– Generate from Setup in Salesforce (enter API in the Quick Find box, then select API)
– Download the appropriate WSDL document and save it to a local directory.
– Generate a Class from WSDL, by clicking “Generate WSDL” Button.

Example of accessing metadata for read listview with specific user:-

public static MetadataService.MetadataPort createService() {
    Boolean orgType;
    orgType = [SELECT Id, IsSandbox FROM Organization where Id = : UserInfo.getOrganizationId() LIMIT 1].IsSandbox;
    if(orgType){
        credentials = Credentials__c.getInstance('Sandbox');
    }
    else{
        credentials = Credentials__c.getInstance('Production');
    }
    final String USERNAME = credentials.User_Name__c;
    final String PASSWORD = credentials.Password__c;
    final String SECURITY_TOKEN = credentials.Security_Token__c;
    // Calling Partner class for login with specific user
    PartnerSoapSforceCom.Soap loginConnection = new PartnerSoapSforceCom.Soap();
    PartnerSoapSforceCom.LoginResult config = loginConnection.login(USERNAME,PASSWORD+SECURITY_TOKEN);
    userSessionId = config.sessionId;
    // Calling Metadata Class
    MetadataService.MetadataPort service = new MetadataService.MetadataPort();
    service.SessionHeader = new MetadataService.SessionHeader_element();
    service.SessionHeader.sessionId = userSessionId;
    return service;
}
// Calling createService method for reading list view.
MetadataService.MetadataPort metadataService = createService();
MetadataService.ListView readListView = (MetadataService.ListView)metadataService.readMetadata('ListView', new String[] { 'product2.'+listViewAPIName.DeveloperName}).getRecords()[0];
listviewCoumns.addAll(readListView.columns);