Skip to content

Instantly share code, notes, and snippets.

@andrei-markeev
Created October 29, 2017 09:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrei-markeev/5764e7b2177de73f0f5e0e34696857ec to your computer and use it in GitHub Desktop.
Save andrei-markeev/5764e7b2177de73f0f5e0e34696857ec to your computer and use it in GitHub Desktop.
Node.js Azure Functions #spsbcn
var csomapi = require("csom-node");
// this is an example of Azure Function that connects to SharePoint via JSOM
module.exports = function (azureContext, req) {
var web;
initializeJSOM()
.then(ctx => {
web = ctx.get_web();
ctx.load(web);
return executeJSOM(ctx);
})
.then(() => {
azureContext.log(web.get_title());
azureContext.res = { body: "Success!" };
azureContext.done();
})
.catch(function() {
azureContext.log("ERROR", arguments);
azureContext.res = { status: 500, body: "Error occured!" };
azureContext.done();
});
function initializeJSOM() {
return new Promise(function(resolve, reject) {
var settings = {
url: "https://markeev.sharepoint.com/",
clientId: process.env.SP_APP_ID,
clientSecret: process.env.SP_APP_SECRET
};
csomapi.setLoaderOptions({url: settings.url}); //set CSOM library settings
var authCtx = new AuthenticationContext(settings.url);
authCtx.acquireTokenForApp(settings.clientId, encodeURIComponent(settings.clientSecret), function (err, data) {
if (err) {
reject(err);
return;
}
var ctx = new SP.ClientContext("/"); //set root web
authCtx.setAuthenticationCookie(ctx); //authenticate
resolve(ctx);
});
});
}
function executeJSOM(ctx) {
return new Promise((resolve, reject) => ctx.executeQueryAsync(resolve, reject));
}
};
var XMLHttpRequest = require("xhr2");
// this is an example of Azure Function that connects to SharePoint via REST without using ADAL.js
module.exports = function (azureContext, req) {
var sp_url = "https://markeev.sharepoint.com/";
var sp_access_token = '';
getSharePointAccessToken(sp_url)
.then(access_token => {
sp_access_token = access_token;
// do REST calls here
return request(sp_url + "_api/web/title", { access_token: sp_access_token });
})
.then(responseText => {
azureContext.log(JSON.parse(responseText).value);
azureContext.done();
})
.catch(handleError);
function handleError(e) {
azureContext.log("Critical Error: ", e);
azureContext.res = { status: 500, body: e };
azureContext.done(e);
}
function getSharePointAccessToken(url) {
return new Promise((resolve, reject) => {
var redirecturi = "https://localhost"
var appResource = "00000003-0000-0ff1-ce00-000000000000"
request(url + "_vti_bin/client.svc", { method: 'POST', body: "", access_token: " ", returnHeader: "WWW-Authenticate" })
.then(wwwAuthHeader => {
if (!wwwAuthHeader) {
reject("Error retrieving realm!");
return;
}
var realm = wwwAuthHeader.split(",")[0].split("=")[1].slice(1, -1);
var body = {
grant_type: 'client_credentials',
client_id: process.env.SP_APP_ID + "@" + realm,
client_secret: process.env.SP_APP_SECRET,
resource: appResource + "/" + url.match(/^https:\/\/([A-Za-z\.-]+)\//)[1] + "@" + realm,
redirect_uri: redirecturi
};
var oauthUrl = "https://accounts.accesscontrol.windows.net/" + realm + "/tokens/OAuth/2";
request(oauthUrl, { format: 'urlencoded', body, method: 'POST' })
.then(responseText => resolve(JSON.parse(responseText).access_token))
.catch(reject);
})
.catch(reject);
});
}
function request(url, options) {
return new Promise((resolve, reject) => {
var postBody = null;
options = options || {};
if (options.body != null) {
if (options.format == 'urlencoded')
postBody = Object.keys(options.body).map(k => k + '=' + encodeURIComponent(options.body[k])).join('&');
else if (options.format == 'json')
postBody = JSON.stringify(options.body);
else
postBody = options.body;
}
var xhr = new XMLHttpRequest();
azureContext.log(options.method || "GET", url, "\n");
xhr.open(options.method || "GET", url, true);
//Send the proper header information along with the request
if (options.format == 'urlencoded')
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
else
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
if (options.access_token != null)
xhr.setRequestHeader("Authorization", "Bearer " + options.access_token);
xhr.onreadystatechange = function () {//Call a function when the state changes.
if (xhr.readyState == 4) {
//azureContext.log('\n\nHTTP/1.1 ' + xhr.status + '\n' + xhr.getAllResponseHeaders() + '\n\n' + xhr.responseText);
if (options.returnHeader)
resolve(xhr.getResponseHeader(options.returnHeader));
else if (xhr.status >= 200 && xhr.status <= 299)
resolve(xhr.responseText);
else
reject(xhr.status);
}
}
xhr.send(postBody);
});
}
}
var webpack = require('webpack');
// this webpack build is alternative to azure-functions-pack
// how to pack modules for using with Azure Functions (you need to know webpack basics to do it):
// 1. install modules that you want to pack with npm install <module>
// 2. provide the entry files of those modules under "entry" node
// 4. run webpack using this config file
// 5. packed modules will be in build/node_modules
// for more details, please see webpack documentation
// if a node module uses dynamic imports, you might need to do some more steps
// example of custom packaging for csom-node with explanations can be found in https://markeev.com/posts/jsom-azure-function
module.exports = {
entry: {
'xhr2': './node_modules/xhr2/lib/xhr2.js',
'lodash': './node_modules/lodash/lib/lodash.js'
},
output: {
path: __dirname + '/build',
libraryTarget: 'commonjs2',
filename: 'node_modules/[name].js'
},
target: 'node',
node: {
__dirname: false
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment