@ripeworks/xrm-api
Version:
Module that allows to invoke Microsoft Dynamics CRM services
739 lines (626 loc) • 29.4 kB
JavaScript
/*jslint nomen: true, stupid: true */
// module dependencies
var xpath = require("xpath");
var Cache = require("mem-cache");
var domParser = new (require("xmldom").DOMParser)();
var parseString = require("xml2js").parseString;
var traverse = require("traverse");
var constants = require("constants");
var Agentkeepalive = require("agentkeepalive");
var request = require("request");
var ntlm = require("httpntlm/ntlm.js");
var uuid = require("uuid");
// this class implements all features
var Util = function (settings) {
"use strict";
// Arguments validation
if (!settings || typeof settings !== "object") {
throw new Error("'settings' argument must be an object instance.");
}
if (!settings.hostName) {
// If no direct hostname was supplied, check information about domain, and, probably, domainUrlSuffix
if (!settings.domain || typeof settings.domain !== "string"){
throw new Error("'settings.domain' property is a required string.");
}
if (settings.domainUrlSuffix && typeof settings.domainUrlSuffix !== "string"){
throw new Error("'settings.domainUrlSuffix' must be string.");
}
}
// Set default value if organization name is missing
if (!settings.organizationName) {
settings.organizationName = "";
}
if (settings.timeout && typeof settings.timeout !== "number") {
throw new Error("'settings.timeout' property must be a number.");
}
if (settings.username && typeof settings.username !== "string") {
throw new Error("'settings.username' property must be a string.");
}
if (settings.password && typeof settings.password !== "string") {
throw new Error("'settings.password' property must be a string.");
}
if (settings.port && typeof settings.port !== "number") {
throw new Error("'settings.port' property must be a number.");
}
if (settings.organizationName && typeof settings.organizationName !== "string") {
throw new Error("'settings.organizationName' property must be a string.");
}
var authenticationTypes = ["live_id", "microsoft_online", "federation", "ntlm"];
// Set default value if authentication type is wrong or invalid
if (!settings.authType || typeof settings.authType !== "string" || authenticationTypes.indexOf(settings.authType) === -1) {
settings.authType = "live_id";
}
// Sets default arguments values
settings.timeout = settings.timeout || 15 * 60 * 1000; // default sessions timeout of 15 minutes in ms
settings.returnJson = true;
settings.port = settings.port || (settings.useHttp ? 80 : 443);
settings.hostName = settings.hostName || (function() {
if (settings.domainUrlSuffix) {
return settings.domain + settings.domainUrlSuffix;
}
// Default Url Suffix will point to CRM online instance
return settings.domain + ".api.crm.dynamics.com";
})();
settings.userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36";
settings.cacheTokenByAuth = new Cache(settings.timeout);
settings.cacheAuthByUser = new Cache(settings.timeout);
settings.tokensForDeviceCache = new Cache(settings.timeout);
var defaultUrlSuffix = ".api.crm.dynamics.com",
organizationPath = "/XRMServices/2011/Organization.svc",
organizationServiceEndpoint = "https://" + settings.hostName + organizationPath,
SOAPActionBase = "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/",
endpoints,
device,
fetchEndpoints,
loadOrRegisterDevice,
getTokenUsingDeviceId,
generateRandom,
renameKey,
executeSoapPost,
deepObjCopy,
defaultCb,
authenticateUsingMicrosoftOnline,
authenticateUsingLiveId,
authenticateUsingFederation,
authenticateUsingNTLM,
addSecureOptions,
parseResponse,
authenticate,
executePost,
//load templates once
microsoftOnlineSaml = `
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">{toMustUnderstand}</a:To>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken>
<o:Username>{username}</o:Username>
<o:Password>{password}</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<a:EndpointReference>
<a:Address>{endpoint}</a:Address>
</a:EndpointReference>
</wsp:AppliesTo>
<t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>`,
authRequestDeviceTokenMessage = `
<?xml version="1.0" encoding="utf-8" ?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
<a:MessageID>urn:uuid:{messageuuid}</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">{issuer}</a:To>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>{timeCreated}</u:Created>
<u:Expires>{timeExpires}</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="devicesoftware">
<o:Username>{deviceUsername}</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">{devicePassword}</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<a:EndpointReference>
<a:Address>{liveIdAppliesTo}</a:Address>
</a:EndpointReference>
</wsp:AppliesTo>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>`,
authRequestSTSTokenMessage = `
<?xml version="1.0" encoding="utf-8" ?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
<a:MessageID>urn:uuid:{messageuuid}</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">{issuer}</a:To>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>{created}</u:Created>
<u:Expires>{expires}</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="user">
<o:Username>{username}</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">{password}</o:Password>
</o:UsernameToken>
<wsse:BinarySecurityToken ValueType="urn:liveid:device" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<EncryptedData Id="BinaryDAToken0" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"></EncryptionMethod>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:KeyName>http://Passport.NET/STS</ds:KeyName>
</ds:KeyInfo>
<CipherData>
<CipherValue>{cipher}</CipherValue>
</CipherData>
</EncryptedData>
</wsse:BinarySecurityToken>
</o:Security>
</s:Header>
<s:Body>
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<a:EndpointReference>
<a:Address>urn:crmna:dynamics.com</a:Address>
</a:EndpointReference>
</wsp:AppliesTo>
<wsp:PolicyReference URI="MBI_FED_SSL" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"/>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>`,
faultTextXpath = "//*[local-name()='Fault']/*[local-name()='Reason']/*[local-name()='Text']/text()",
importLocationXpath = "//*[local-name()='import' and namespace-uri()='http://schemas.xmlsoap.org/wsdl/']/@location",
authenticationTypeXpath = "//*[local-name()='Authentication' and namespace-uri()='http://schemas.microsoft.com/xrm/2011/Contracts/Services']/text()",
issuerAddressXpath = "//*[local-name()='SignedSupportingTokens']/*[local-name()='Policy']/*[local-name()='IssuedToken']/*[local-name()='Issuer']/*[local-name()='Address']/text()",
liveAppliesToXpath = "//*[local-name()='LiveIdAppliesTo']/text()";
settings.organizationServiceEndpoint = organizationServiceEndpoint;
/*
* Default callback function, it only throws an exception if an error was received.
*/
defaultCb = function (err) {
if (err) {
throw err;
}
};
addSecureOptions = function (reqOptions) {
if (!settings.useHttp) {
reqOptions.secureOptions = constants.SSL_OP_NO_TLSv1_2;
reqOptions.ciphers = "ECDHE-RSA-AES256-SHA:AES256-SHA:RC4-SHA:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM";
reqOptions.honorCipherOrder = true;
}
};
settings.fetchEndpoints = function (cb) {
if (endpoints) {
return cb(null, endpoints);
}
var options = {
uri: settings.useHttp ? "http://" : "https://" + settings.hostName + ":" + settings.port + organizationPath + "?wsdl",
};
addSecureOptions(options);
request(options, function (err, res, body) {
if (err) {
return cb(err);
}
var resXml = domParser.parseFromString(body),
fault = xpath.select(faultTextXpath, resXml),
location,
opts;
if (fault.length > 0) {
return cb(new Error(fault.toString()), null);
}
location = xpath.select(importLocationXpath, resXml)
.map(function (attr) {
return attr.value;
})[0];
if (location.length > 0) {
opts = { url: location };
addSecureOptions(opts);
request(opts, function (err, res, body) {
if (err) {
return cb(err);
}
var resXmlImport,
faultImport,
authenticationType,
issuerAddress,
liveAppliesTo,
identifier,
keyType,
keySize,
requireClientEntropy;
resXmlImport = domParser.parseFromString(body);
faultImport = xpath.select(faultTextXpath, resXmlImport);
if (faultImport.length > 0) {
return cb(new Error(faultImport.toString()), null);
}
authenticationType = xpath.select(authenticationTypeXpath, resXmlImport).toString();
issuerAddress = xpath.select(issuerAddressXpath, resXmlImport).toString();
liveAppliesTo = xpath.select(liveAppliesToXpath, resXmlImport).toString();
identifier = xpath.select("//*[local-name()='Identifier']/text()", resXmlImport).toString();
keyType = xpath.select("//*[local-name()='KeyType']/text()", resXmlImport).toString();
keySize = xpath.select("//*[local-name()='KeySize']/text()", resXmlImport).toString();
requireClientEntropy = (body.indexOf("RequireClientEntropy") > -1);
endpoints = {
AuthenticationType: authenticationType,
IssuerAddress: issuerAddress,
DeviceAddUrl: "https://login.live.com/ppsecure/DeviceAddCredential.srf",
LiveIdAppliesTo: liveAppliesTo,
Identifier: identifier,
KeyType: keyType,
KeySize: keySize,
RequireClientEntropy: requireClientEntropy
};
return cb(null, endpoints);
});
}
});
};
loadOrRegisterDevice = function (options, cb) {
if (device) return cb(null, device);
var username = generateRandom(24, "aA#"),
password = generateRandom(24, "aA#");
var authCreateDeviceMessage = `
<?xml version="1.0"?>
<DeviceAddRequest>
<ClientInfo name="` + uuid.v4() + `" version="1.0" />
<Authentication>
<Membername>` + username + `</Membername>
<Password>` + password + `</Password>
</Authentication>
</DeviceAddRequest>`;
options = {
method: "POST",
uri: options.DeviceAddUrl,
body: authCreateDeviceMessage,
headers: {
"Content-Type": "application/soap+xml; charset=UTF-8",
"Content-Length": authCreateDeviceMessage.length
}
};
addSecureOptions(options);
request(options, function (err, res, body) {
if (err) {
return cb(err);
}
var resXml = domParser.parseFromString(body),
fault = xpath.select(faultTextXpath, resXml),
puid;
if (fault.length > 0) {
return cb(new Error(fault.toString()), null);
}
puid = xpath.select("/DeviceAddResponse/puid/text()", resXml).toString();
device = {
deviceUsername: username,
devicePassword: password,
puid: puid
};
return cb(null, device);
});
};
getTokenUsingDeviceId = function (options, cb) {
var timeCreated = new Date(),
timeExpires = new Date(timeCreated.getTime() + settings.timeout),
cipher = settings.tokensForDeviceCache.get("auth_tokenrequest_device"),
requestOptions;
if (cipher) {
return cb(null, cipher);
}
authRequestDeviceTokenMessage = authRequestDeviceTokenMessage
.replace("{messageuuid}", uuid.v4())
.replace("{timeCreated}", timeCreated.toISOString())
.replace("{timeExpires}", timeExpires.toISOString())
.replace("{issuer}", options.IssuerAddress)
.replace("{liveIdAppliesTo}", options.LiveIdAppliesTo)
.replace("{deviceUsername}", options.DeviceInfo.deviceUsername)
.replace("{devicePassword}", options.DeviceInfo.devicePassword);
requestOptions = {
method: "POST",
uri: options.IssuerAddress,
body: authRequestDeviceTokenMessage,
headers: {
"Content-Type": "application/soap+xml; charset=UTF-8",
"Content-Length": Buffer.byteLength(authRequestDeviceTokenMessage)
}
};
addSecureOptions(requestOptions);
request(requestOptions, function (err, res, body) {
if (err) {
return cb(err);
}
var resXml = domParser.parseFromString(body),
fault = xpath.select(faultTextXpath, resXml),
cipherValue;
if (fault.length > 0) {
return cb(new Error(fault.toString()), null);
}
cipherValue = xpath.select("//*[local-name()='RequestedSecurityToken' and namespace-uri()='http://schemas.xmlsoap.org/ws/2005/02/trust']/*[name()='EncryptedData']/*[name()='CipherData']/*[name()='CipherValue']/text()", resXml).toString();
cipher = {CipherValue: cipherValue};
settings.tokensForDeviceCache.set("auth_tokenrequest_device", cipher);
return cb(null, cipher);
});
};
generateRandom = function (length, chars) {
var mask = "",
result = "",
i;
if (chars.indexOf("a") > -1) {
mask += "abcdefghijklmnopqrstuvwxyz";
}
if (chars.indexOf("A") > -1) {
mask += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
if (chars.indexOf("#") > -1) {
mask += "0123456789";
}
if (chars.indexOf("!") > -1) {
mask += "~`!@#$%^&*()_+-={}[]:\";'<>?,./|\\";
}
for (i = length; i > 0; i = i - 1) {
result += mask[Math.round(Math.random() * (mask.length - 1))];
}
return result;
};
renameKey = function (objInd, prefixes) {
var rk = objInd;
prefixes.forEach(function (p) {
if (objInd.indexOf(p) === 0) {
rk = objInd.replace(p, "");
}
});
return rk;
};
parseResponse = function (body, cb) {
var data = body,
prefixes,
data_no_ns,
resXml = domParser.parseFromString(body),
fault = xpath.select(faultTextXpath, resXml);
if (fault.length > 0) {
return cb(new Error(fault.toString()));
}
if (settings.returnJson)
parseString(body, {explicitArray: false}, function (err, jsondata) {
if (err) {
return cb(err);
}
prefixes = [];
//removes namespaces
data_no_ns = traverse(jsondata).map(function () {
if (this.key !== undefined) {
var pos = this.key.indexOf("xmlns:"),
k = this.key.substring(6, this.key.length) + ":";
if (pos > -1 || this.key.indexOf("xmlns") > -1) {
if (prefixes.lastIndexOf(k) === -1) {
prefixes.push(k);
}
this.remove();
}
}
});
//removes 'xx:' prefixes
data = deepObjCopy(data_no_ns, prefixes);
cb(null, data);
});
else cb(null, data);
};
executeSoapPost = function (options, action, template, body, cb) {
var timeCreated = new Date(),
timeExpires = new Date(timeCreated.getTime() + 5 * 60000),
requestOptions,
soapHeader,
xmlrequestbody,
soapPostMessage,
security,
ntlmOptions,
type1msg,
agent,
reqOptions,
url,
httpHeaders = {};
xmlrequestbody = template.replace("{requetbody}", body);
var soapEnvelopeMessage = `
<s:Envelope xmlns:s="{envelopeNS}" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
{header}
{body}
</s:Envelope>`;
if (settings.authType === "ntlm") {
soapPostMessage = soapEnvelopeMessage
.replace("{envelopeNS}", "http://schemas.xmlsoap.org/soap/envelope/")
.replace("{header}", "")
.replace("{body}", xmlrequestbody);
url = (settings.useHttp ? "http://" : "https://") + settings.hostName + ":" + settings.port + "/" + settings.organizationName + organizationPath + "/web";
httpHeaders.cookie = "ReqClientId=" + options.ReqClientId;
httpHeaders.SOAPAction = SOAPActionBase + action;
httpHeaders["Content-Length"] = Buffer.byteLength(soapPostMessage);
httpHeaders["Content-Type"] = "text/xml; charset=utf-8";
httpHeaders.Accept = "application/xml, text/xml, */*";
httpHeaders["User-Agent"] = settings.userAgent;
ntlmOptions = {
username: options.username || settings.username,
password: options.password || settings.password,
workstation: options.workstation || settings.workstation || "",
domain: options.ntlmDomain || settings.ntlmDomain || ""
};
type1msg = ntlm.createType1Message(ntlmOptions);
agent = settings.useHttp ? new Agentkeepalive() : new Agentkeepalive.HttpsAgent();
reqOptions = {
method: options.method || "GET",
url: url,
headers: {
Authorization: type1msg,
},
agent: agent,
timeout: settings.requestTimeout
};
addSecureOptions(reqOptions);
request(reqOptions, function (err, res) {
if (err) {
return cb(err);
}
if (!res.headers["www-authenticate"]) {
return cb(new Error("www-authenticate not found on response of second request"));
}
var type2msg = ntlm.parseType2Message(res.headers["www-authenticate"]),
type3msg = ntlm.createType3Message(type2msg, ntlmOptions);
httpHeaders.Authorization = type3msg;
reqOptions = {
method: "POST",
url: url,
body: soapPostMessage,
agent: agent,
timeout: settings.requestTimeout,
headers: httpHeaders
};
addSecureOptions(reqOptions);
request(reqOptions, function (err, res, body) {
if (err) {
return cb(err);
}
parseResponse(body, cb);
});
});
} else {
soapHeader = `
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/` + action + `</a:Action>
<a:MessageID>urn:uuid:` + uuid.v4() + `</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">` + organizationServiceEndpoint + `</a:To>
{security}
</s:Header>`;
if (options.encryptedData) {
security = `<wsse:Security s:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">\
<u:Created>` + timeCreated.toISOString() + `</u:Created>
<u:Expires>` + timeExpires.toISOString() + `</u:Expires>
</u:Timestamp>` + options.encryptedData + `</wsse:Security>`;
soapHeader = soapHeader.replace("{security}", security);
} else if (options.header) {
soapHeader = soapHeader.replace("{security}", options.header);
}
else {
return cb(new Error("Neither token or header found."));
}
url = (settings.useHttp ? "http://" : "https://") + settings.hostName + ":" + settings.port + organizationPath;
soapPostMessage = soapEnvelopeMessage
.replace("{envelopeNS}", "http://www.w3.org/2003/05/soap-envelope")
.replace("{header}", soapHeader)
.replace("{body}", xmlrequestbody);
httpHeaders["Content-Type"] = "application/soap+xml; charset=UTF-8";
httpHeaders["Content-Length"] = Buffer.byteLength(soapPostMessage);
requestOptions = {
method: "POST",
uri: url,
body: soapPostMessage,
headers: httpHeaders
};
addSecureOptions(requestOptions);
request(requestOptions, function (err, res, body) {
if (err) {
return cb(err);
}
parseResponse(body, cb);
});
}
};
deepObjCopy = function (dupeObj, pfxs) {
var retObj = {},
objInd,
rk;
if (typeof dupeObj === "object") {
if (dupeObj.length) {
retObj = [];
}
for (objInd in dupeObj) {
if (dupeObj.hasOwnProperty(objInd)) {
rk = renameKey(objInd, pfxs);
if (typeof dupeObj[objInd] === "object") {
retObj[rk] = deepObjCopy(dupeObj[objInd], pfxs);
} else if (typeof dupeObj[objInd] === "string") {
retObj[rk] = dupeObj[objInd];
} else if (typeof dupeObj[objInd] === "number") {
retObj[rk] = dupeObj[objInd];
} else if (typeof dupeObj[objInd] === "boolean") {
if (dupeObj[rk]) {
retObj[objInd] = true;
} else {
retObj[objInd] = false;
}
}
}
}
}
return retObj;
};
var auth = new (require("./auth.js"))(settings);
executePost = function (options, action, template, body, cb) {
var authItem;
// handles optional 'options' argument
if (!cb && typeof options === "function") {
cb = options;
options = {};
}
// sets default values
cb = cb || defaultCb;
options = options || {};
if (!options || typeof options !== "object") {
return cb(new Error("'options' argument is missing or invalid."));
}
if (options.encryptedData || options.header) {
executeSoapPost(options, action, template, body, cb);
} else if (options.auth) {
authItem = cacheTokenByAuth.get(options.auth);
options.encryptedData = authItem.token; //For LiveId an MSOnline
options.header = authItem.header; //For Federation
options.ReqClientId = authItem.ReqClientId; //For NTLM
executeSoapPost(options, action, template, body, cb);
} else {
auth.Do(options, function (err, data) {
if (err) {
return cb(err);
}
authItem = settings.cacheTokenByAuth.get(data.auth);
options.encryptedData = authItem.token; //For LiveId an MSOnline
options.header = authItem.header; //For Federation
executeSoapPost(options, action, template, body, cb);
});
}
};
this.executePostPromised = function(options, action, template, body) {
return new Promise(function (fulfill, reject) {
executePost(options, action, template, body, function (err, data) {
if (err) {
reject(err);
}
fulfill(data);
});
});
};
};
module.exports = Util;