зеркало из
1
0
Форкнуть 0

"Recursive Lambda Refactor V1"

This commit is contained in:
Recursive Lambda God 2017-04-29 13:49:13 -04:00
Родитель 9999c49f15
Коммит 83f22432d8
80 изменённых файлов: 5515 добавлений и 5157 удалений

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -5,9 +5,10 @@
// This module is responsible for directing logging to the console.
// Implements same public functions as logwriter.js.
var core = require('./core'),
util = require('util'),
events = require('events');
var core = require('./core');
var util = require('util');
var events = require('events');
exports = module.exports = ConsoleLogWriter;

Просмотреть файл

@ -3,18 +3,19 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
var _ = require('underscore'),
_str = require('underscore.string');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
(function (exports) {
((exports => {
function curry(fn) {
var slice = Array.prototype.slice,
args = slice.call(arguments, 1);
var slice = Array.prototype.slice;
var args = slice.call(arguments, 1);
return function () {
return fn.apply(null, args.concat(slice.call(arguments)));
return fn(...args.concat(slice.call(arguments)));
};
}
@ -26,7 +27,7 @@ _.mixin(_str.exports());
}
function defineClass(ctor, instanceMembers, classMembers) {
ctor = ctor || function () { };
ctor = ctor || (() => { });
if (instanceMembers) {
extend(ctor.prototype, instanceMembers);
}
@ -41,14 +42,12 @@ _.mixin(_str.exports());
var prototype = {};
extend(prototype, basePrototype);
var getPrototype = function (name, fn) {
return function () {
var tmp = this._super;
this._super = basePrototype;
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
var getPrototype = (name, fn) => function(...args) {
var tmp = this._super;
this._super = basePrototype;
var ret = fn.apply(this, args);
this._super = tmp;
return ret;
};
if (instanceMembers) {
@ -60,16 +59,14 @@ _.mixin(_str.exports());
}
ctor = ctor ?
(function (fn) {
return function () {
var tmp = this._super;
this._super = basePrototype;
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(ctor)
: function () { };
((fn => function(...args) {
var tmp = this._super;
this._super = basePrototype;
var ret = fn.apply(this, args);
this._super = tmp;
return ret;
}))(ctor)
: () => { };
ctor.prototype = prototype;
ctor.prototype.constructor = ctor;
@ -318,12 +315,12 @@ _.mixin(_str.exports());
// If this is a merge conflict, the first parameter will be the original item
// involved in the update or delete
Object.defineProperty(this, 'isMergeConflict', {
get: function () {
get() {
return code === ErrorCodes.MergeConflict;
}
});
Object.defineProperty(this, 'isConflict', {
get: function () {
get() {
return code === ErrorCodes.Conflict;
}
});
@ -344,7 +341,7 @@ _.mixin(_str.exports());
this.code = code;
}
}, {
toString: function () {
toString() {
if (this.innerError) {
return this.innerError.toString(); // Preserve error type prefix (ie: SyntaxError:, SqlError:)
} else {
@ -432,9 +429,7 @@ _.mixin(_str.exports());
function getSystemProperty(name) {
name = name.toLowerCase();
return _.find(supportedSystemProperties, function (property) {
return property.name.toLowerCase() === name;
});
return _.find(supportedSystemProperties, property => property.name.toLowerCase() === name);
}
function validateAndNormalizeSystemProperties(systemProperties) {
@ -449,15 +444,13 @@ _.mixin(_str.exports());
// Check for the '*' (all system properties) value
if (isStarSystemProperty(systemProperties)) {
normalizedSystemProperties = supportedSystemProperties.map(function (property) {
return property.name;
});
normalizedSystemProperties = supportedSystemProperties.map(property => property.name);
}
else {
// otherwise, validate each individual system property
_.each(systemProperties, function (systemProperty) {
var original = systemProperty,
isKnownProperty = false;
_.each(systemProperties, systemProperty => {
var original = systemProperty;
var isKnownProperty = false;
if (isString(systemProperty)) {
// remove any whitespace and make all lower case
@ -595,9 +588,7 @@ _.mixin(_str.exports());
// Following paths in call stack do not point to file that caused the error.
var ignorePaths = ['Microsoft.Azure.Zumo.Runtime.Node.Test'];
function isIgnoredPathInFrame(frame) {
var found = _.any(ignorePaths, function(path) {
return frame.indexOf(path) > 0;
});
var found = _.any(ignorePaths, path => frame.indexOf(path) > 0);
return found;
}
@ -658,7 +649,7 @@ _.mixin(_str.exports());
var value;
Object.defineProperty(target, name, {
get: function () {
get() {
if (value === undefined) {
// if we haven't accessed the value yet, get it
// and cache it
@ -683,7 +674,7 @@ _.mixin(_str.exports());
if (!Array.isArray(array)) {
throw Error('First parameter must be an array');
}
array.forEach(function (item) {
array.forEach(item => {
var key = keySelector(item);
map[key] = item;
});
@ -693,7 +684,7 @@ _.mixin(_str.exports());
// should use this version of stringify to ensure that all
// byte arrays (Buffers in node.js) are serialized correctly.
function stringify(itemToStringify) {
return JSON.stringify(itemToStringify, function (item, value) {
return JSON.stringify(itemToStringify, (item, value) => {
if (Buffer.isBuffer(value)) {
value = value.toString('base64');
}
@ -705,10 +696,10 @@ _.mixin(_str.exports());
// run the specified array of functions in sequence
// series: array of functions
// done: the callback to call after all have been run
series: function (series, done) {
series(series, done) {
var stepIdx = 0;
var next = function (err) {
var next = err => {
if (err || stepIdx == (series.length)) {
done(err);
}
@ -723,16 +714,16 @@ _.mixin(_str.exports());
// run the specified array of functions in parallel
// series: array of functions
// done: the callback to call after all have been run
parallel: function (series, done) {
parallel(series, done) {
var completed = 0;
var complete = function (err) {
var complete = err => {
if (err || ++completed == series.length) {
done(err);
}
};
// start all functions in parallel
series.forEach(function (f) {
series.forEach(f => {
f(complete);
});
}
@ -919,4 +910,4 @@ _.mixin(_str.exports());
var stringIdValidatorRegex = /([\u0000-\u001F]|[\u007F-\u009F]|["\+\?\\\/\`]|^\.{1,2}$)/;
})(typeof exports === 'undefined' ? (this.core = {}) : exports);
}))(typeof exports === 'undefined' ? (this.core = {}) : exports);

Просмотреть файл

@ -9,7 +9,7 @@ var crypto = require('crypto');
function Encryptor() {
}
Encryptor.encrypt = function (key, plaintext) {
Encryptor.encrypt = (key, plaintext) => {
if (typeof plaintext !== 'string') {
throw new Error('plaintext must be a string.');
}
@ -18,7 +18,7 @@ Encryptor.encrypt = function (key, plaintext) {
return data;
};
Encryptor.decrypt = function (key, data) {
Encryptor.decrypt = (key, data) => {
var cipher = crypto.createDecipher('aes-256-cbc', key);
var plaintext = cipher.update(data, 'base64', 'utf8') + cipher.final('utf8');
return plaintext;

Просмотреть файл

@ -4,9 +4,10 @@
//
// Provides helper functions for interacting with the file system
var fs = require('fs'),
_ = require('underscore'),
_str = require('underscore.string');
var fs = require('fs');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
@ -18,7 +19,7 @@ exports.require = require;
var retriableFileErrorCodes = ['EBUSY'];
exports.removeExtension = function (fileName) {
exports.removeExtension = fileName => {
if (fileName) {
var idx = fileName.lastIndexOf('.');
if (idx > 0) {
@ -31,14 +32,14 @@ exports.removeExtension = function (fileName) {
// read a file asyncronously using the specified retry policy
// maxRetries and retryInterval are optional
exports.readFileWithRetries = function (filePath, logger, callback, maxRetries, retryInterval) {
var self = this,
retryCount = 0;
var self = this;
var retryCount = 0;
maxRetries = maxRetries || 3;
retryInterval = retryInterval || 500;
function readFileWithRetries() {
self.fs.readFile(filePath, 'utf8', function (err, data) {
self.fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
// if the error is retriable, try again, up to the max retry count
if (retriableFileErrorCodes.indexOf(err.code) !== -1 && retryCount++ < maxRetries) {
@ -64,9 +65,9 @@ exports.readFileWithRetries = function (filePath, logger, callback, maxRetries,
// read a node module using the specified retry policy
// maxRetries and retryInterval are optional
exports.requireWithRetries = function (filePath, logger, callback, maxRetries, retryInterval) {
var self = this,
retryCount = 0,
loadedModule;
var self = this;
var retryCount = 0;
var loadedModule;
maxRetries = maxRetries || 3;
retryInterval = retryInterval || 500;

Просмотреть файл

@ -4,10 +4,11 @@
//
// A simple filewatcher that monitors a single file for changes.
var core = require('./core'),
fs = require('fs'),
_ = require('underscore'),
_str = require('underscore.string');
var core = require('./core');
var fs = require('fs');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
@ -39,7 +40,7 @@ FileWatcher.prototype._createFileWatcher = function () {
this.logger.trace(logSource, _.sprintf("Starting filewatcher on file '%s'.", this.filepath));
// get the initial timestamp
this.fs.stat(this.filepath, function (err, stats) {
this.fs.stat(this.filepath, (err, stats) => {
if (!err) {
self.lastModified = stats.mtime;
}
@ -54,8 +55,8 @@ FileWatcher.prototype._createFileWatcher = function () {
// than fs.watch, because for networked files polling is the only reliable
// way of detecting changes (e.g. fs.watch file handles periodically become
// invalid).
self.interval = setInterval(function () {
self.fs.stat(self.filepath, function (err, stats) {
self.interval = setInterval(() => {
self.fs.stat(self.filepath, (err, stats) => {
if (!err) {
// determine whether the file has changed since the last time we checked
if (self.lastModified && self.lastModified.getTime() < stats.mtime.getTime()) {

Просмотреть файл

@ -4,11 +4,12 @@
//
// This module provides a json web token implementation
var crypto = require('crypto'),
Encryptor = require('./encryptor'),
Buffer = require('buffer').Buffer,
core = require('./core'),
_ = require('underscore');
var crypto = require('crypto');
var Encryptor = require('./encryptor');
var Buffer = require('buffer').Buffer;
var core = require('./core');
var _ = require('underscore');
exports = module.exports;
@ -34,7 +35,7 @@ exports.windowsLiveSigningSuffix = JsonWebToken.windowsLiveSigningSuffix;
// envelope is an object or string containing JWT envelope
// key is an object containing both the crypto key and the key used to build signature
// signingSuffix contains a suffix that is appended to the standard JWT signingKey
exports.create = function (claims, envelope, key, signingSuffix) {
exports.create = (claims, envelope, key, signingSuffix) => {
var jwt = new JsonWebToken(key, signingSuffix);
jwt.setEnvelope(envelope);
@ -60,7 +61,7 @@ exports.create = function (claims, envelope, key, signingSuffix) {
// x5t JWTs: [{ x5t: '<certThumprint>', certs: ['<cert1>', '<cert2>'] }]
// kid JWTs: { 'id': 'cert1', 'id1': 'cert2' }
// signingSuffix contains a suffix that is appended to the standard JWT signingKey when validating the signature
exports.parse = function (token, keyOrCertificates, signingSuffix) {
exports.parse = (token, keyOrCertificates, signingSuffix) => {
var jwt = new JsonWebToken(keyOrCertificates, signingSuffix);
// Get the token segments & perform validation
@ -81,9 +82,7 @@ exports.parse = function (token, keyOrCertificates, signingSuffix) {
};
// This is a test hook to allow replay of expired tokens for unit tests
exports.now = function () {
return new Date();
};
exports.now = () => new Date();
// determine whether this JWT instance has expired
JsonWebToken.prototype.isExpired = function () {
@ -145,9 +144,7 @@ JsonWebToken.prototype.verifyRsaSha256Signature = function () {
JsonWebToken.prototype.verifyRsaSha256SignatureX5t = function () {
var self = this;
var matchedPublicX5TSets = _.find(this._certificates, function (x5TCertificates) {
return x5TCertificates.x5t === self.envelope.x5t;
});
var matchedPublicX5TSets = _.find(this._certificates, x5TCertificates => x5TCertificates.x5t === self.envelope.x5t);
if (!matchedPublicX5TSets) {
// The cert was not found. Return this information in the error,
@ -158,9 +155,7 @@ JsonWebToken.prototype.verifyRsaSha256SignatureX5t = function () {
}
// Now check all certs listed as matching against the JWT signature
return _.some(matchedPublicX5TSets.certs, function (publicKey) {
return self.verifySignatureByCert(publicKey);
});
return _.some(matchedPublicX5TSets.certs, publicKey => self.verifySignatureByCert(publicKey));
};
JsonWebToken.prototype.verifyRsaSha256SignatureKid = function() {

Просмотреть файл

@ -2,11 +2,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
var core = require('./core'),
_ = require('underscore'),
_str = require('underscore.string'),
LogWriter = require('./logwriter'),
ConsoleLogWriter = require('./consolelogwriter');
var core = require('./core');
var _ = require('underscore');
var _str = require('underscore.string');
var LogWriter = require('./logwriter');
var ConsoleLogWriter = require('./consolelogwriter');
_.mixin(_str.exports());
@ -73,7 +74,7 @@ Logger.prototype.log = function (level, type, source, summary, details, immediat
// all entries regardless of log level
// we do this to to dump as much information as possible to the logs
// in unhandled exception scenarios
this.bufferedRequestLogEntries.forEach(function (entry) {
this.bufferedRequestLogEntries.forEach(entry => {
self.logWriter.writeSystem(entry);
});
this.bufferedRequestLogEntries = [];
@ -158,7 +159,7 @@ Logger.prototype.logUserUnhandled = function (err) {
Logger.prototype.logMetrics = function (metrics) {
var self = this;
metrics.forEach(function (metric) {
metrics.forEach(metric => {
self.logWriter.writeMetric(metric);
});
};
@ -174,11 +175,11 @@ function createSystemLogEntry(requestID, timestamp, level, type, source, summary
var entry = {
activityID: requestID,
timeCreated: timestamp,
level: level,
type: type,
source: source,
summary: summary,
details: details
level,
type,
source,
summary,
details
};
return entry;
@ -199,9 +200,9 @@ Logger.prototype._createUserLogEntry = function createUserLogEntry(source, type,
var entry = {
timeCreated: this._getTimestamp(),
type: type,
source: source,
message: message
type,
source,
message
};
return entry;
@ -230,7 +231,7 @@ Logger.prototype.clear = function () {
};
// performs global initialization of the Logger
Logger.initialize = function (logServiceURL, logServiceToken, isLoggingServiceDisabled) {
Logger.initialize = (logServiceURL, logServiceToken, isLoggingServiceDisabled) => {
if (isLoggingServiceDisabled) {
Logger.writer = new ConsoleLogWriter();
} else {
@ -240,11 +241,11 @@ Logger.initialize = function (logServiceURL, logServiceToken, isLoggingServiceDi
// force an immediate flush of all cached log entries
// not yet written
Logger.flush = function () {
Logger.flush = () => {
Logger.writer.flush();
};
// clear all cached log entries
Logger.clear = function () {
Logger.clear = () => {
Logger.writer.clear();
};

Просмотреть файл

@ -6,13 +6,14 @@
// It maintains a cache of log entries and flushes them in batches to the logging service
// at regular intervals.
var core = require('./core'),
http = require('http'),
url = require('url'),
util = require('util'),
events = require('events'),
_ = require('underscore'),
_str = require('underscore.string');
var core = require('./core');
var http = require('http');
var url = require('url');
var util = require('util');
var events = require('events');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
@ -83,7 +84,7 @@ LogWriter.prototype.queueFlush = function () {
// on the logging service by batching multiple log entries
// into a single request.
var self = this;
this.timer = setTimeout(function () {
this.timer = setTimeout(() => {
self.flush();
}, this.flushTimeout);
}
@ -129,8 +130,9 @@ LogWriter.prototype.clear = function () {
LogWriter.prototype._enforceSystemLogBufferLimit = function () {
if (this.systemLogs.length > this.maxLogEntryFlushCount) {
// fist, grab the first half of the logs
var count = this.systemLogs.length,
logs = this.systemLogs.slice(0, this.maxLogEntryFlushCount / 2);
var count = this.systemLogs.length;
var logs = this.systemLogs.slice(0, this.maxLogEntryFlushCount / 2);
// add a truncation entry to indicate logs were truncated
var truncationEntry = logs.slice(-1)[0];
@ -159,13 +161,13 @@ LogWriter.prototype._write = function (path, logEntries) {
return;
}
var self = this,
retryCount = 0;
var self = this;
var retryCount = 0;
// POST the log entries to the remote log service
try {
// define a function to actually build and issue the POST request
var postLogs = function (logEntries) {
var postLogs = logEntries => {
var logData = core.stringify(logEntries);
var logSize = Buffer.byteLength(logData, 'utf8');
@ -173,7 +175,7 @@ LogWriter.prototype._write = function (path, logEntries) {
// multiple batches, recursively if necessary.
if (logSize > self.maxRequestSize) {
var batches = self._splitEntries(logEntries);
batches.forEach(function (batch) {
batches.forEach(batch => {
postLogs(batch);
});
return;
@ -182,7 +184,7 @@ LogWriter.prototype._write = function (path, logEntries) {
var options = {
host: self.logServiceURL.hostname,
port: self.logServiceURL.port,
path: path,
path,
method: 'POST',
headers: {
'Host': self.logServiceURL.hostname,
@ -195,7 +197,7 @@ LogWriter.prototype._write = function (path, logEntries) {
function retryRequest(e) {
// if the request failed, retry up to the maximum retry limit
if (++retryCount <= self.requestRetryMaxAttempts) {
setTimeout(function () {
setTimeout(() => {
postLogs(logEntries);
}, self.requestRetryInterval);
} else {
@ -205,7 +207,7 @@ LogWriter.prototype._write = function (path, logEntries) {
}
}
var req = self._createHttpRequest(options, function (res) {
var req = self._createHttpRequest(options, res => {
if (res.statusCode >= 400) {
// Node's HTTP stack won't emit the error event for all error responses, so we need to handle errors here too.
var err = new Error("Error encountered communicating with the logging service, status code: " + res.statusCode);
@ -240,13 +242,11 @@ LogWriter.prototype._write = function (path, logEntries) {
};
// factored as a method to facilitate testability/mocking
LogWriter.prototype._createHttpRequest = function (options, callback) {
return http.request(options, function (res) {
callback(res);
});
};
LogWriter.prototype._createHttpRequest = (options, callback) => http.request(options, res => {
callback(res);
});
LogWriter.prototype._splitEntries = function (entries) {
LogWriter.prototype._splitEntries = entries => {
var batch1 = entries.slice(0, entries.length / 2);
var batch2 = entries.slice(entries.length / 2);
return [batch1, batch2];

Просмотреть файл

@ -26,7 +26,7 @@ function Metrics(logger, sampleTimeout) {
// Aggregate and send the logs every sampleTimeout ms
if (sampleTimeout) {
setInterval(function() {
setInterval(() => {
self.flush();
}, sampleTimeout);
}
@ -37,11 +37,11 @@ Metrics.prototype.reset = function() {
this.events = {};
};
Metrics.prototype.startEvent = function (name) {
Metrics.prototype.startEvent = name => {
name = name.toLowerCase();
var now = new Date();
return {
name: name,
name,
startTime: now.getTime()
};
};
@ -80,7 +80,7 @@ Metrics.prototype.event = function (name) {
name = name.toLowerCase();
var event = {
name: name,
name,
value: 0 // Events that are triggered via this function are for counting only
};
@ -235,8 +235,6 @@ InstallationsProcessor.prototype._setCacheExpiry = function (date) {
this.cacheExpiry = expiry;
};
InstallationsProcessor.prototype._addDays = function (date, days) {
// return a new date with the specified number of
// days added to the specified date
return new Date(date.setDate(date.getDate() + days));
};
InstallationsProcessor.prototype._addDays = (date, days) => // return a new date with the specified number of
// days added to the specified date
new Date(date.setDate(date.getDate() + days));

Просмотреть файл

@ -4,11 +4,12 @@
//
// Provides functionality for loading the New Relic module if found, and setting the appropriate configuration defaults
var path = require('path'),
resource = require('./resources'),
core = require('./core'),
_ = require('underscore'),
source = 'NewRelicAdapter';
var path = require('path');
var resource = require('./resources');
var core = require('./core');
var _ = require('underscore');
var source = 'NewRelicAdapter';
exports = module.exports = NewRelicAdapter;
@ -29,10 +30,9 @@ NewRelicAdapter.prototype.initialize = function (configPath, environment, module
// Skip initialization if there is no license key specified
if (environment.NEW_RELIC_LICENSE_KEY) {
var userdirectory = path.join(this.configPath, core.getScriptsDirName(configPath)),
configFilePath = path.join(environment.NEW_RELIC_HOME || userdirectory, 'newrelic.js'),
useConfigFile = fs.existsSync(configFilePath);
var userdirectory = path.join(this.configPath, core.getScriptsDirName(configPath));
var configFilePath = path.join(environment.NEW_RELIC_HOME || userdirectory, 'newrelic.js');
var useConfigFile = fs.existsSync(configFilePath);
// Allow the user to drop a 'newrelic.js' file into their service folder to configure the agent.
// If no such file is found, provide default settings
@ -52,10 +52,10 @@ NewRelicAdapter.prototype.initialize = function (configPath, environment, module
this.loaded = true;
var traceDetails = useConfigFile ? "Config file found at: " + configFilePath
: "No config file found at: " + configFilePath + " - using default New Relic settings";
this.systemTraceLogs.push({ source: source, summary: 'New Relic agent loaded successfully', details: traceDetails });
this.systemTraceLogs.push({ source, summary: 'New Relic agent loaded successfully', details: traceDetails });
}
catch (ex) {
this.systemTraceLogs.push({ source: source, summary: 'Failed to load New Relic module', details: ex.toString() });
this.systemTraceLogs.push({ source, summary: 'Failed to load New Relic module', details: ex.toString() });
this.userLogs.push({ source: '', type: 'error', message: resource.newRelicError });
}
}
@ -65,11 +65,11 @@ NewRelicAdapter.prototype.complete = function (logger, metrics) {
core.ensureParamNotNull(logger, 'logger');
core.ensureParamNotNull(metrics, 'metrics');
this.userLogs.forEach(function (log) {
this.userLogs.forEach(log => {
logger.logUser(log.source, log.type, log.message);
});
this.systemTraceLogs.forEach(function (log) {
this.systemTraceLogs.forEach(log => {
logger.trace(log.source, log.summary, log.details);
});

Просмотреть файл

@ -8,13 +8,14 @@
// GET http://myapp.azure-mobile.net/push/registrations?deviceId=<channelUri/deviceToken/gcmRegistrationId>&platform=<platform>
// These endpoints facilitate the client's registrations for NotificationHubs
var StatusCodes = require('../statuscodes').StatusCodes,
_ = require('underscore'),
_str = require('underscore.string'),
ApnsHandler = require('./nhregistrationhelpers/apns'),
GcmHandler = require('./nhregistrationhelpers/gcm'),
MpnsHandler = require('./nhregistrationhelpers/mpns'),
WnsHandler = require('./nhregistrationhelpers/wns');
var StatusCodes = require('../statuscodes').StatusCodes;
var _ = require('underscore');
var _str = require('underscore.string');
var ApnsHandler = require('./nhregistrationhelpers/apns');
var GcmHandler = require('./nhregistrationhelpers/gcm');
var MpnsHandler = require('./nhregistrationhelpers/mpns');
var WnsHandler = require('./nhregistrationhelpers/wns');
_.mixin(_str.exports());
exports = module.exports = NhRegistrationHandler;
@ -35,15 +36,15 @@ function NhRegistrationHandler(notificationHubService, extensionManager) {
// POST http://myapp.azure-mobile.net/push/registrationsids
// Success returns 201
NhRegistrationHandler.prototype.handlePost = function (req) {
var context = req._context,
responseCallback = context.responseCallback,
headers,
logger = context.logger,
metrics = context.metrics,
metricName = 'registration.createId';
var context = req._context;
var responseCallback = context.responseCallback;
var headers;
var logger = context.logger;
var metrics = context.metrics;
var metricName = 'registration.createId';
try {
this.notificationHubService.createRegistrationId(function (error, response) {
this.notificationHubService.createRegistrationId((error, response) => {
try {
if (error) {
metrics.event(_.sprintf('%s.%s', metricName, 'error'));
@ -90,16 +91,16 @@ NhRegistrationHandler.prototype.handlePost = function (req) {
// }
// Success returns 204
NhRegistrationHandler.prototype.handlePut = function (req) {
var context = req._context,
requestBody = req.body,
responseCallback = context.responseCallback,
platform,
registration,
logger = context.logger,
metrics = context.metrics,
metricName = 'registration.update',
installationId = req.headers['x-zumo-installation-id'],
self = this;
var context = req._context;
var requestBody = req.body;
var responseCallback = context.responseCallback;
var platform;
var registration;
var logger = context.logger;
var metrics = context.metrics;
var metricName = 'registration.update';
var installationId = req.headers['x-zumo-installation-id'];
var self = this;
if (!requestBody) {
throw new core.MobileServiceError('Creating or updating registrations requires a body containing a push registration', core.ErrorCodes.BadInput);
@ -118,7 +119,7 @@ NhRegistrationHandler.prototype.handlePut = function (req) {
}
}
this.extensionManager.runPushRegistrationScript(requestBody, req.user, function (scriptError) {
this.extensionManager.runPushRegistrationScript(requestBody, req.user, scriptError => {
try {
if (scriptError) {
handleUserScriptError(logger, responseCallback, scriptError, 'Registration script failed with error');
@ -129,7 +130,7 @@ NhRegistrationHandler.prototype.handlePut = function (req) {
registration.Tags = registration.Tags.join();
self.notificationHubService.createOrUpdateRegistration(registration, function (error) {
self.notificationHubService.createOrUpdateRegistration(registration, error => {
try {
if (error) {
metrics.event(_.sprintf('%s.%s', metricName, 'error'));
@ -163,7 +164,7 @@ NhRegistrationHandler.prototype.handlePut = function (req) {
// The first 2 parts of a inputRegistration for any service are:
// 1. registrationId (required)
// 2. tags (optional
NhRegistrationHandler.prototype.transformInputToNhBaseRegistration = function (inputRegistration) {
NhRegistrationHandler.prototype.transformInputToNhBaseRegistration = inputRegistration => {
var registration = {};
// The _ property on the registration is used by notificationHubService for storing various metadata such as the type of the registration object for SOAP
@ -191,14 +192,14 @@ NhRegistrationHandler.prototype.transformInputToNhBaseRegistration = function (i
// DELETE http://myapp.azure-mobile.net/push/registrations/<id>
// Success returns 200
NhRegistrationHandler.prototype.handleDelete = function (req) {
var context = req._context,
responseCallback = context.responseCallback,
logger = context.logger,
metrics = context.metrics,
metricName = 'registration.delete';
var context = req._context;
var responseCallback = context.responseCallback;
var logger = context.logger;
var metrics = context.metrics;
var metricName = 'registration.delete';
try {
this.notificationHubService.deleteRegistration(context.parsedRequest.id, function (error) {
this.notificationHubService.deleteRegistration(context.parsedRequest.id, error => {
try {
if (error) {
metrics.event(_.sprintf('%s.%s', metricName, 'error'));
@ -225,13 +226,13 @@ NhRegistrationHandler.prototype.handleDelete = function (req) {
// GET http://myapp.azure-mobile.net/push/registrations?deviceId=<channelUri/deviceToken/gcmRegistrationId>&platform=<platform>
// Success returns 200
NhRegistrationHandler.prototype.handleGet = function (req) {
var context = req._context,
platform = req.query.platform,
platformHandler,
logger = context.logger,
responseCallback = context.responseCallback,
metricName = _.sprintf('registration.list.%s', platform),
metrics = context.metrics;
var context = req._context;
var platform = req.query.platform;
var platformHandler;
var logger = context.logger;
var responseCallback = context.responseCallback;
var metricName = _.sprintf('registration.list.%s', platform);
var metrics = context.metrics;
try {
if (!req.query.deviceId) {
@ -240,7 +241,7 @@ NhRegistrationHandler.prototype.handleGet = function (req) {
platformHandler = this.getHandler(platform);
platformHandler.listRegistrations(req.query.deviceId, function (error, response) {
platformHandler.listRegistrations(req.query.deviceId, (error, response) => {
try {
handleListRegistrationsResponse(req, error, response, platform, platformHandler);
} catch (e) {
@ -256,11 +257,11 @@ NhRegistrationHandler.prototype.handleGet = function (req) {
// callback for converting the response for listing registrations
function handleListRegistrationsResponse(req, error, response, platform, platformHandler) {
var context = req._context,
responseCallback = context.responseCallback,
logger = context.logger,
metrics = context.metrics,
metricName = _.sprintf('registration.list.%s', platform);
var context = req._context;
var responseCallback = context.responseCallback;
var logger = context.logger;
var metrics = context.metrics;
var metricName = _.sprintf('registration.list.%s', platform);
if (error) {
metrics.event(_.sprintf('%s.%s', metricName, 'error'));
@ -291,7 +292,7 @@ NhRegistrationHandler.prototype.getHandler = function (platform) {
// Converting a success response for listing registrations to output format
function convertToOutputRegistrationArray(platformHandler, nhListResponse) {
var registrations = [];
_.each(nhListResponse, function (regFromNh) { convertToOutputRegistration(platformHandler, regFromNh, registrations); });
_.each(nhListResponse, regFromNh => { convertToOutputRegistration(platformHandler, regFromNh, registrations); });
return registrations;
}

Просмотреть файл

@ -59,13 +59,11 @@ ApnsHandler.prototype.listRegistrations = function (deviceId, callback) {
};
// Provides the specific property to snag the unique registration Id from
ApnsHandler.prototype.getDeviceIdFromNhRegistration = function (regFromNh) {
return regFromNh.DeviceToken;
};
ApnsHandler.prototype.getDeviceIdFromNhRegistration = regFromNh => regFromNh.DeviceToken;
// Converts any optional template members from Service Bus for this notifcation service into members of registration object
// for transfer to the client
ApnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = function (regFromNh, registration) {
ApnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = (regFromNh, registration) => {
if (regFromNh.Expiry) {
registration.expiry = regFromNh.Expiry;
}

Просмотреть файл

@ -54,13 +54,11 @@ GcmHandler.prototype.listRegistrations = function (deviceId, callback) {
};
// Provides the specific property to snag the unique registration Id from
GcmHandler.prototype.getDeviceIdFromNhRegistration = function (regFromNh) {
return regFromNh.GcmRegistrationId;
};
GcmHandler.prototype.getDeviceIdFromNhRegistration = regFromNh => regFromNh.GcmRegistrationId;
// Converts any optional template members from Service Bus for this notifcation service into members of registration object
// for transfer to the client
// regFromNh, registration are default params, but are unused
// Gcm currently has no optimal template properties
GcmHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = function () {
GcmHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = () => {
};

Просмотреть файл

@ -4,8 +4,9 @@
//
// This module is the helper to assist nhregistrationhandler with Mpns registration operations
var core = require('../../core'),
_ = require('underscore');
var core = require('../../core');
var _ = require('underscore');
exports = module.exports = MpnsHandler;
@ -39,7 +40,10 @@ MpnsHandler.prototype.transformInputToNhRegistration = function (inputRegistrati
registration.BodyTemplate = inputRegistration.templateBody;
if (inputRegistration.headers) {
registration.MpnsHeaders = {};
registration.MpnsHeaders.MpnsHeader = _.map(inputRegistration.headers, function (value, headerName) { return { Header: headerName, Value: value }; });
registration.MpnsHeaders.MpnsHeader = _.map(inputRegistration.headers, (value, headerName) => ({
Header: headerName,
Value: value
}));
}
if (inputRegistration.templateName) {
@ -60,17 +64,15 @@ MpnsHandler.prototype.listRegistrations = function (deviceId, callback) {
};
// Provides the specific property to snag the unique registration Id from
MpnsHandler.prototype.getDeviceIdFromNhRegistration = function (regFromNh) {
return regFromNh.ChannelUri;
};
MpnsHandler.prototype.getDeviceIdFromNhRegistration = regFromNh => regFromNh.ChannelUri;
// Converts any optional template members from Service Bus for this notifcation service into members of registration object
// for transfer to the client
MpnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = function (regFromNh, registration) {
MpnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = (regFromNh, registration) => {
if (regFromNh.MpnsHeaders) {
if (regFromNh.MpnsHeaders.MpnsHeader) {
registration.headers = {};
_.each(regFromNh.MpnsHeaders.MpnsHeader, function (header) {
_.each(regFromNh.MpnsHeaders.MpnsHeader, header => {
registration.headers[header.Header] = header.Value;
}, registration.headers);
}

Просмотреть файл

@ -4,8 +4,9 @@
//
// This module is the helper to assist nhregistrationhandler with Wns registration operations
var core = require('../../core'),
_ = require('underscore');
var core = require('../../core');
var _ = require('underscore');
exports = module.exports = WnsHandler;
@ -39,7 +40,10 @@ WnsHandler.prototype.transformInputToNhRegistration = function (inputRegistratio
registration.BodyTemplate = inputRegistration.templateBody;
if (inputRegistration.headers) {
registration.WnsHeaders = {};
registration.WnsHeaders.WnsHeader = _.map(inputRegistration.headers, function (value, headerName) { return { Header: headerName, Value: value }; });
registration.WnsHeaders.WnsHeader = _.map(inputRegistration.headers, (value, headerName) => ({
Header: headerName,
Value: value
}));
}
if (inputRegistration.templateName) {
@ -60,18 +64,16 @@ WnsHandler.prototype.listRegistrations = function (deviceId, callback) {
};
// Provides the specific property to snag the unique registration Id from
WnsHandler.prototype.getDeviceIdFromNhRegistration = function (regFromNh) {
return regFromNh.ChannelUri;
};
WnsHandler.prototype.getDeviceIdFromNhRegistration = regFromNh => regFromNh.ChannelUri;
// Converts any optional template members from Service Bus for this notifcation service into members of registration object
// for transfer to the client
WnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = function (regFromNh, registration) {
WnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = (regFromNh, registration) => {
if (regFromNh.WnsHeaders) {
if (regFromNh.WnsHeaders.WnsHeader) {
registration.headers = {};
// {"WnsHeader":[{"Header":"X-WNS-TTL","Value":"1"},{"Header":"X-WNS-Type","Value":"wns/toast"}]}
_.each(regFromNh.WnsHeaders.WnsHeader, function (header) {
_.each(regFromNh.WnsHeaders.WnsHeader, header => {
registration.headers[header.Header] = header.Value;
}, registration.headers);
}

Просмотреть файл

@ -4,16 +4,17 @@
//
// This module is used to create an azure notificationHubService
var ZumoCallback = require('../script/zumocallback'),
notify = require('./scripthelpers/notify'),
notifyWns = require('./scripthelpers/notify-wns'),
notifyMpns = require('./scripthelpers/notify-mpns'),
notifyApns = require('./scripthelpers/notify-apns'),
notifyGcm = require('./scripthelpers/notify-gcm'),
NhRegistrationHandler = require('./nhregistrationhandler'),
path = require('path'),
_ = require('underscore'),
azure;
var ZumoCallback = require('../script/zumocallback');
var notify = require('./scripthelpers/notify');
var notifyWns = require('./scripthelpers/notify-wns');
var notifyMpns = require('./scripthelpers/notify-mpns');
var notifyApns = require('./scripthelpers/notify-apns');
var notifyGcm = require('./scripthelpers/notify-gcm');
var NhRegistrationHandler = require('./nhregistrationhandler');
var path = require('path');
var _ = require('underscore');
var azure;
exports = module.exports = PushAdapter;
@ -62,18 +63,10 @@ PushAdapter.prototype.createPushForScripts = function (source, logger, metrics,
} else if (!this.notificationHubPush) {
var self = this;
// define lazy properties for push provider wrappers
core.createLazyProperty(push, 'wns', function () {
return notify.createWrappedClient(self.directPushClients.wnsClient, source, logger, metrics, responseCallback);
});
core.createLazyProperty(push, 'mpns', function () {
return notify.createWrappedClient(self.directPushClients.mpnsClient, source, logger, metrics, responseCallback);
});
core.createLazyProperty(push, 'apns', function () {
return notify.createWrappedClient(self.directPushClients.apnsClient, source, logger, metrics, responseCallback);
});
core.createLazyProperty(push, 'gcm', function () {
return notify.createWrappedClient(self.directPushClients.gcmClient, source, logger, metrics, responseCallback);
});
core.createLazyProperty(push, 'wns', () => notify.createWrappedClient(self.directPushClients.wnsClient, source, logger, metrics, responseCallback));
core.createLazyProperty(push, 'mpns', () => notify.createWrappedClient(self.directPushClients.mpnsClient, source, logger, metrics, responseCallback));
core.createLazyProperty(push, 'apns', () => notify.createWrappedClient(self.directPushClients.apnsClient, source, logger, metrics, responseCallback));
core.createLazyProperty(push, 'gcm', () => notify.createWrappedClient(self.directPushClients.gcmClient, source, logger, metrics, responseCallback));
}
return push;

Просмотреть файл

@ -1,13 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
var core = require('../../core'),
resources = require('../../resources'),
StatusCodes = require('../../statuscodes').StatusCodes,
_ = require('underscore'),
_str = require('underscore.string'),
apns = require('apn');
var core = require('../../core');
var ApnConnectionFactory = (function () {
var resources = require('../../resources');
var StatusCodes = require('../../statuscodes').StatusCodes;
var _ = require('underscore');
var _str = require('underscore.string');
var apns = require('apn');
var ApnConnectionFactory = ((() => {
function ApnConnectionFactory(certLoader, passphrase, gateway, timeout) {
this.certLoader = certLoader;
@ -43,7 +44,7 @@ var ApnConnectionFactory = (function () {
var pfxData = this.certLoader();
this.options = {
pfxData: pfxData,
pfxData,
passphrase: this.passphrase,
gateway: this.gateway
};
@ -62,14 +63,14 @@ var ApnConnectionFactory = (function () {
ApnConnectionFactory.prototype._disposeConnection = function () {
if (this.connection !== null) {
var self = this;
this.connection.sockets.forEach(function (socket) {
this.connection.sockets.forEach(socket => {
self.connection.destroyConnection(socket);
});
}
};
return ApnConnectionFactory;
})();
}))();
module.exports = exports = ApnConnectionFactory;

Просмотреть файл

@ -4,14 +4,15 @@
// This module supports sending push notifications to iOS clients using the
// Apple Push Notification Service
var core = require('../../core'),
resources = require('../../resources'),
apns = require('apn'),
notify = require('./notify'),
fs = require('fs'),
_ = require('underscore'),
_str = require('underscore.string'),
ApnConnectionFactory = require('./apnconnectionfactory');
var core = require('../../core');
var resources = require('../../resources');
var apns = require('apn');
var notify = require('./notify');
var fs = require('fs');
var _ = require('underscore');
var _str = require('underscore.string');
var ApnConnectionFactory = require('./apnconnectionfactory');
_.mixin(_str.exports());
@ -29,7 +30,7 @@ var statusDescriptions = {
255: 'None (unknown)'
};
exports.getCertLoader = function (apnsCertificatePath) {
exports.getCertLoader = apnsCertificatePath => {
var pfxData = null;
function getCertificate(action) {
@ -42,7 +43,7 @@ exports.getCertLoader = function (apnsCertificatePath) {
return getCertificate;
};
exports.createApnsContext = function (apnsCertificatePath, apnsPassword, apnsMode) {
exports.createApnsContext = (apnsCertificatePath, apnsPassword, apnsMode) => {
var gateway = (apnsMode == 'Prod') ? 'gateway.push.apple.com' : 'gateway.sandbox.push.apple.com';
@ -56,7 +57,7 @@ exports.createApnsContext = function (apnsCertificatePath, apnsPassword, apnsMod
// when sending notifications. We use an 'interval' of 0 below to ensure the feedback instance
// doesn't set it's own timer.
var feedbackOptions = null;
var feedbackOptionsFactory = function () {
var feedbackOptionsFactory = () => {
if (!feedbackOptions) {
feedbackOptions = {
pfxData: getCertificate('get APNS feedback'),
@ -89,7 +90,7 @@ exports.createApnsContext = function (apnsCertificatePath, apnsPassword, apnsMod
return result;
};
exports.send = function (connectionFactory, deviceToken, payload, ignore, errorCallback) {
exports.send = (connectionFactory, deviceToken, payload, ignore, errorCallback) => {
var connection = connectionFactory.getConnection();
if (!core.isString(deviceToken)) {
@ -108,7 +109,7 @@ exports.send = function (connectionFactory, deviceToken, payload, ignore, errorC
// Create the error callback; there is no success callback because Apple doesn't
// respond if the notification was received and validated successfully.
notification.errorCallback = function (error) {
notification.errorCallback = error => {
if (checkCertError(error, errorCallback)) {
return;
}
@ -130,7 +131,7 @@ exports.send = function (connectionFactory, deviceToken, payload, ignore, errorC
connection.sendNotification(notification);
};
exports.createNotificationFromPayload = function (payload) {
exports.createNotificationFromPayload = payload => {
var notification;
if (payload.aps) {
@ -162,19 +163,19 @@ exports.createNotificationFromPayload = function (payload) {
return notification;
};
exports.getFeedback = function (feedbackOptionsFactory, ignore, callback) {
exports.getFeedback = (feedbackOptionsFactory, ignore, callback) => {
var feedbackOptions = feedbackOptionsFactory();
var options = {};
core.extend(options, feedbackOptions);
// Set the feedback callback; this is the success callback
options.feedback = function (feedback) {
options.feedback = feedback => {
// We need to convert the feedback we get from the APN
// module to something more user friendly
var converted = [];
feedback.forEach(function (item) {
feedback.forEach(item => {
converted.push({
deviceToken: item.device.toString(),
timeStamp: new Date(item.time * 1000)
@ -185,7 +186,7 @@ exports.getFeedback = function (feedbackOptionsFactory, ignore, callback) {
};
// Set the errorCAllback; this is the error callback
options.errorCallback = function (error) {
options.errorCallback = error => {
if (checkCertError(error, callback)) {
return;
}

Просмотреть файл

@ -4,18 +4,19 @@
// This module supports sending push notifications to Android clients using
// Google Cloud Messaging
var dpush = require('dpush'),
notify = require('./notify'),
resources = require('../../resources');
var dpush = require('dpush');
exports.createGcmContext = function (googleApiKey) {
var notify = require('./notify');
var resources = require('../../resources');
exports.createGcmContext = googleApiKey => {
var result = {};
// transform the dpush.send and dpush.sendAdvanced methods
// gcm.send(recipiendId, message, [options]) -> dpush.send(googleApiKey, recipientId, message, callback):
result.send = notify.createWrapper(dpush, 'send', 2, 'gcm', null, null, true, true, function (args) {
result.send = notify.createWrapper(dpush, 'send', 2, 'gcm', null, null, true, true, args => {
if (!googleApiKey) {
throw new Error(resources.googleApiKeyMissing);
}
@ -37,7 +38,7 @@ exports.createGcmContext = function (googleApiKey) {
// gcm.sendAdvanced(content, retryCount, [options]) -> dpush.sendAdvanced(googleApiKey, content, retryCount, callback):
result.sendAdvanced = notify.createWrapper(dpush, 'sendAdvanced', 2, 'gcm', null, null, true, true, function (args) {
result.sendAdvanced = notify.createWrapper(dpush, 'sendAdvanced', 2, 'gcm', null, null, true, true, args => {
if (!googleApiKey) {
throw new Error(resources.googleApiKeyMissing);
}

Просмотреть файл

@ -4,11 +4,12 @@
// This module supports sending push notifications to Windows Phone 8 clients using
// Microsoft Push Notification Services
var core = require('../../core'),
mpns = require('mpns'),
notify = require('./notify');
var core = require('../../core');
exports.createMpnsContext = function () {
var mpns = require('mpns');
var notify = require('./notify');
exports.createMpnsContext = () => {
// - channel URL is passed to callbacks as part of the result or error object
function visitResult(item, args) {

Просмотреть файл

@ -4,14 +4,14 @@
// This module supports sending push notifications to Windows 8 clients using
// Windows Notification Services
var wns = require('wns'),
notify = require('./notify'),
core = require('../../core');
var wns = require('wns');
exports.createWnsContext = function (client_secret, client_id) {
var notify = require('./notify');
var core = require('../../core');
var result = {},
accessTokenContainer = {};
exports.createWnsContext = (client_secret, client_id) => {
var result = {};
var accessTokenContainer = {};
// - accessToken is not passed back to the caller throught the callback
// - only x-wns-* HTTP response headers are returned in the result or error
@ -26,7 +26,7 @@ exports.createWnsContext = function (client_secret, client_id) {
}
if (typeof item.headers === 'object') {
Object.getOwnPropertyNames(item.headers).forEach(function (header) {
Object.getOwnPropertyNames(item.headers).forEach(header => {
if (header.toLowerCase().indexOf('x-wns-') !== 0) {
delete item.headers[header];
}

Просмотреть файл

@ -4,12 +4,13 @@
// This module is the base for sending push notifications via Windows Azure Mobile Services
// WNS, MPNS, and APNS all use this module to build out their notification client objects.
var StatusCodes = require('../../statuscodes').StatusCodes,
core = require('../../core'),
scriptErrors = require('../../script/scripterror'),
ZumoCallback = require('../../script/zumocallback'),
_ = require('underscore'),
_str = require('underscore.string');
var StatusCodes = require('../../statuscodes').StatusCodes;
var core = require('../../core');
var scriptErrors = require('../../script/scripterror');
var ZumoCallback = require('../../script/zumocallback');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
@ -18,7 +19,17 @@ var logSource = "Push";
// transform methods to fit ZUMO esthetics:
// - success and error callbacks are separate and specified as properties of the options object
// - user can call these methods either with a single channel URL (or deviceToken) or with an array of channels (or deviceTokens)
exports.createWrapper = function (module, method, argsLength, moduleName, visitResult, visitOptions, disableAtomizingChannelArrays, skipModuleOptions, finalizeArgs) {
exports.createWrapper = (
module,
method,
argsLength,
moduleName,
visitResult,
visitOptions,
disableAtomizingChannelArrays,
skipModuleOptions,
finalizeArgs
) => {
var wrapper = function () {
// Copy the arguments array and extract the pipelineContext
var args = Array.prototype.slice.call(arguments);
@ -53,7 +64,7 @@ exports.createWrapper = function (module, method, argsLength, moduleName, visitR
options = empty;
}
var visitor = function (errOrResult) {
var visitor = errOrResult => {
if (visitResult) {
errOrResult = visitResult(errOrResult, args);
}
@ -125,7 +136,7 @@ exports.createWrapper = function (module, method, argsLength, moduleName, visitR
return wrapper;
};
exports.createWrappedClient = function (module, source, logger, metrics, responseCallback) {
exports.createWrappedClient = (module, source, logger, metrics, responseCallback) => {
// We instantiate the push client (wns, mpns, etc) when the server starts but we need to provide logging
// and responseCallbacks per request. In this method we are wrapping the client with
@ -133,10 +144,10 @@ exports.createWrappedClient = function (module, source, logger, metrics, respons
// Create the pipeline context object
var pipelineContext = {
logger: logger,
responseCallback: responseCallback,
logger,
responseCallback,
scriptSource: source,
metrics: metrics
metrics
};
// Curry the pipelineContext object into every method

Просмотреть файл

@ -2,7 +2,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
(function (global) {
((global => {
var core = require('../core');
@ -39,7 +39,7 @@
Expression = core.defineClass(
null, {
accept: function (visitor) {
accept(visitor) {
return visitor.visit(this);
}
},
@ -51,7 +51,7 @@
this.value = value;
this.expressionType = ExpressionType.Constant;
}, {
accept: function (visitor) {
accept(visitor) {
return visitor.visitConstant(this);
}
},
@ -64,7 +64,7 @@
this.right = right;
this.expressionType = expressionType;
}, {
accept: function (visitor) {
accept(visitor) {
return visitor.visitBinary(this);
}
},
@ -76,7 +76,7 @@
this.operand = operand;
this.expressionType = expressionType;
}, {
accept: function (visitor) {
accept(visitor) {
return visitor.visitUnary(this);
}
},
@ -90,7 +90,7 @@
this.member = member;
this.expressionType = ExpressionType.MemberAccess;
}, {
accept: function (visitor) {
accept(visitor) {
return visitor.visitMember(this);
}
},
@ -104,7 +104,7 @@
this.args = args;
this.expressionType = ExpressionType.Call;
}, {
accept: function (visitor) {
accept(visitor) {
return visitor.visitFunction(this);
}
},
@ -114,7 +114,7 @@
function () {
this.ExpressionType = ExpressionType.Parameter;
}, {
accept: function (visitor) {
accept(visitor) {
return visitor.visitParameter(this);
}
},
@ -127,10 +127,10 @@
this.operand = operand;
this.expressionType = ExpressionType.Convert;
}, {
accept: function (visitor) {
accept(visitor) {
return visitor.visitUnary(this);
}
},
null);
})(typeof exports === "undefined" ? this : exports);
}))(typeof exports === "undefined" ? this : exports);

Просмотреть файл

@ -2,22 +2,22 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
(function (global) {
((global => {
var core = require('../core');
require('./expressions');
var instanceMembers = {
visit: function (expr) {
visit(expr) {
return expr.accept(this);
},
visitConstant: function (expr) {
visitConstant(expr) {
return expr;
},
visitBinary: function (expr) {
visitBinary(expr) {
var left = null;
var right = null;
@ -34,7 +34,7 @@
return expr;
},
visitUnary: function (expr) {
visitUnary(expr) {
var operand = this.visit(expr.operand);
if (operand != expr.operand) {
return new UnaryExpression(operand, expr.expressionType);
@ -42,15 +42,15 @@
return expr;
},
visitMember: function (expr) {
visitMember(expr) {
return expr;
},
visitParameter: function (expr) {
visitParameter(expr) {
return expr;
},
visitFunction: function (expr) {
visitFunction(expr) {
var updated = false;
var instance = expr.instance;
@ -61,10 +61,10 @@
}
}
var args = [expr.args.length],
i = 0,
self = this;
expr.args.forEach(function (arg) {
var args = [expr.args.length];
var i = 0;
var self = this;
expr.args.forEach(arg => {
var newArg = self.visit(arg);
args[i++] = arg;
if (newArg != arg) {
@ -81,4 +81,4 @@
ExpressionVisitor = core.defineClass(null, instanceMembers);
})(typeof exports === "undefined" ? this : exports);
}))(typeof exports === "undefined" ? this : exports);

Просмотреть файл

@ -2,15 +2,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
(function (global) {
((global => {
require('./expressions');
var _ = require('underscore'),
_str = require('underscore.string'),
core = require('../core');
var _ = require('underscore');
var _str = require('underscore.string');
var core = require('../core');
_.mixin(_str.exports());
_.mixin(_str.exports());
TokenId = {
Unknown: 'Unknown',
@ -54,13 +53,13 @@
};
var classMembers = {
filter: function (predicate) {
filter(predicate) {
var parser = new QueryParser(predicate);
var filter = parser.parse();
return filter;
},
orderBy: function (ordering) {
orderBy(ordering) {
var parser = new QueryParser(ordering);
var orderings = parser.parseOrdering();
return orderings;
@ -68,7 +67,7 @@
};
var instanceMembers = {
parse: function () {
parse() {
var exprPos = this.token.pos;
var expr = this._parseExpression();
@ -76,7 +75,7 @@
return expr;
},
parseOrdering: function () {
parseOrdering() {
var orderings = [];
while (true) {
var expr = this._parseExpression();
@ -90,7 +89,7 @@
}
orderings.push({
selector: expr,
ascending: ascending
ascending
});
if (this.token.id != TokenId.Comma) {
break;
@ -101,16 +100,16 @@
return orderings;
},
_tokenIdentifierIs: function (id) {
_tokenIdentifierIs(id) {
return this.token.id == TokenId.Identifier && id == this.token.text;
},
_parseExpression: function () {
_parseExpression() {
return this._parseLogicalOr();
},
// 'or' operator
_parseLogicalOr: function () {
_parseLogicalOr() {
var left = this._parseLogicalAnd();
while (this.token.id == TokenId.Or) {
this._nextToken();
@ -121,7 +120,7 @@
},
// 'and' operator
_parseLogicalAnd: function () {
_parseLogicalAnd() {
var left = this._parseComparison();
while (this.token.id == TokenId.And) {
this._nextToken();
@ -131,7 +130,7 @@
return left;
},
_parseComparison: function () {
_parseComparison() {
var left = this._parseAdditive();
while (this.token.id == TokenId.Equal || this.token.id == TokenId.NotEqual || this.token.id == TokenId.GreaterThan ||
this.token.id == TokenId.GreaterThanEqual || this.token.id == TokenId.LessThan || this.token.id == TokenId.LessThanEqual) {
@ -167,7 +166,7 @@
},
// 'add','sub' operators
_parseAdditive: function () {
_parseAdditive() {
var left = this._parseMultiplicative();
while (this.token.id == TokenId.Add || this.token.id == TokenId.Sub) {
var opId = this.token.id;
@ -186,7 +185,7 @@
},
// 'mul', 'div', 'mod' operators
_parseMultiplicative: function () {
_parseMultiplicative() {
var left = this._parseUnary();
while (this.token.id == TokenId.Multiply || this.token.id == TokenId.Divide ||
this.token.id == TokenId.Modulo) {
@ -209,7 +208,7 @@
},
// -, 'not' unary operators
_parseUnary: function () {
_parseUnary() {
if (this.token.id == TokenId.Minus || this.token.id == TokenId.Not) {
var opId = this.token.id;
var opPos = this.token.pos;
@ -232,7 +231,7 @@
return this._parsePrimary();
},
_parsePrimary: function () {
_parsePrimary() {
var expr = this._parsePrimaryStart();
while (true) {
if (this.token.id == TokenId.Dot) {
@ -246,7 +245,7 @@
return expr;
},
_parseMemberAccess: function (instance) {
_parseMemberAccess(instance) {
var errorPos = this.token.pos;
var id = this._getIdentifier();
this._nextToken();
@ -264,7 +263,7 @@
}
},
_parseMappedFunction: function (mappedMember, errorPos) {
_parseMappedFunction(mappedMember, errorPos) {
var type = mappedMember.type;
var mappedMemberName = mappedMember.memberName;
var args;
@ -310,7 +309,7 @@
}
},
_beginValidateFunction: function (functionName, errorPos) {
_beginValidateFunction(functionName, errorPos) {
if (functionName === 'replace') {
// Security: nested calls to replace must be prevented to avoid an exploit
// wherein the client can force the server to allocate arbitrarily large
@ -322,7 +321,7 @@
}
},
_completeValidateFunction: function (functionName, functionArgs, errorPos) {
_completeValidateFunction(functionName, functionArgs, errorPos) {
// validate parameters
switch (functionName) {
case 'day':
@ -367,7 +366,7 @@
this.inStringReplace = false;
},
_validateFunctionParameters: function (functionName, args, expectedArgCount) {
_validateFunctionParameters(functionName, args, expectedArgCount) {
if (args.length !== expectedArgCount) {
var error = _.sprintf("Function '%s' requires %d %s",
functionName, expectedArgCount, (expectedArgCount > 1) ? "parameters." : "parameter.");
@ -375,7 +374,7 @@
}
},
_parseArgumentList: function () {
_parseArgumentList() {
this._validateToken(TokenId.OpenParen, "'(' expected");
this._nextToken();
var args = this.token.id != TokenId.CloseParen ? this._parseArguments() : [];
@ -384,7 +383,7 @@
return args;
},
_parseArguments: function () {
_parseArguments() {
var args = [];
while (true) {
args.push(this._parseExpression());
@ -396,7 +395,7 @@
return args;
},
_mapFunction: function (functionName) {
_mapFunction(functionName) {
var mappedMember = this._mapStringFunction(functionName);
if (mappedMember !== null) {
return mappedMember;
@ -415,7 +414,7 @@
return null;
},
_mapStringFunction: function (functionName) {
_mapStringFunction(functionName) {
if (functionName == 'startswith') {
return new MappedMemberInfo('string', functionName, false, true);
}
@ -436,7 +435,7 @@
}
else if (functionName == 'substringof') {
var memberInfo = new MappedMemberInfo('string', functionName, false, true);
memberInfo.mapParams = function (args) {
memberInfo.mapParams = args => {
// reverse the order of arguments for string.Contains
var tmp = args[0];
args[0] = args[1];
@ -463,7 +462,7 @@
return null;
},
_mapDateFunction: function (functionName) {
_mapDateFunction(functionName) {
if (functionName == 'day') {
return new MappedMemberInfo('date', functionName, false, true);
}
@ -485,7 +484,7 @@
return null;
},
_mapMathFunction: function (functionName) {
_mapMathFunction(functionName) {
if (functionName == 'floor') {
return new MappedMemberInfo('math', functionName, false, true);
}
@ -498,12 +497,12 @@
return null;
},
_getIdentifier: function () {
_getIdentifier() {
this._validateToken(TokenId.Identifier, 'Identifier expected');
return this.token.text;
},
_parsePrimaryStart: function () {
_parsePrimaryStart() {
switch (this.token.id) {
case TokenId.Identifier:
return this._parseIdentifier();
@ -520,7 +519,7 @@
}
},
_parseIntegerLiteral: function () {
_parseIntegerLiteral() {
this._validateToken(TokenId.IntegerLiteral);
var text = this.token.text;
@ -541,7 +540,7 @@
return new ConstantExpression(value);
},
_parseRealLiteral: function () {
_parseRealLiteral() {
this._validateToken(TokenId.RealLiteral);
var text = this.token.text;
@ -561,7 +560,7 @@
return new ConstantExpression(value);
},
_parseParenExpression: function () {
_parseParenExpression() {
this._validateToken(TokenId.OpenParen, "'(' expected");
this._nextToken();
var e = this._parseExpression();
@ -570,7 +569,7 @@
return e;
},
_parseIdentifier: function () {
_parseIdentifier() {
this._validateToken(TokenId.Identifier);
var value = this.keywords[this.token.text];
if (value) {
@ -593,7 +592,7 @@
throw this._parseError(_.sprintf("Unknown identifier '%s'", this.token.text));
},
_parseTypeConstruction: function (type) {
_parseTypeConstruction(type) {
var typeIdentifier = this.token.text;
var errorPos = this.token.pos;
this._nextToken();
@ -631,7 +630,7 @@
return typeExpression;
},
_parseStringLiteral: function () {
_parseStringLiteral() {
this._validateToken(TokenId.StringLiteral);
var quote = this.token.text[0];
// Unwrap string (remove surrounding quotes) and unwrap escaped quotes.
@ -641,13 +640,13 @@
return new ConstantExpression(s);
},
_validateToken: function (tokenId, error) {
_validateToken(tokenId, error) {
if (this.token.id != tokenId) {
throw this._parseError(error || 'Syntax error');
}
},
_createKeywords: function () {
_createKeywords() {
return {
"true": new ConstantExpression(true),
"false": new ConstantExpression(false),
@ -659,12 +658,12 @@
};
},
_setTextPos: function (pos) {
_setTextPos(pos) {
this.textPos = pos;
this.ch = this.textPos < this.textLen ? this.text[this.textPos] : '\\0';
},
_nextToken: function () {
_nextToken() {
while (this._isWhiteSpace(this.ch)) {
this._nextChar();
}
@ -762,7 +761,7 @@
this.token.id = this._reclassifyToken(this.token);
},
_reclassifyToken: function (token) {
_reclassifyToken(token) {
if (token.id == TokenId.Identifier) {
if (token.text == "or") {
return TokenId.Or;
@ -811,33 +810,33 @@
return token.id;
},
_nextChar: function () {
_nextChar() {
if (this.textPos < this.textLen) {
this.textPos++;
}
this.ch = this.textPos < this.textLen ? this.text[this.textPos] : '\\0';
},
_isWhiteSpace: function (ch) {
_isWhiteSpace(ch) {
return (/\s/).test(ch);
},
_validateDigit: function () {
_validateDigit() {
if (!core.isDigit(this.ch)) {
throw this._parseError('Digit expected', this.textPos);
}
},
_parseError: function (error, pos) {
_parseError(error, pos) {
pos = pos || this.token.pos || 0;
return new Error(error + ' (at index ' + pos + ')');
},
_isIdentifierStart: function (ch) {
_isIdentifierStart(ch) {
return core.isLetter(ch);
},
_isIdentifierPart: function (ch) {
_isIdentifierPart(ch) {
if (this._isIdentifierStart(ch)) {
return true;
}
@ -855,5 +854,4 @@
};
QueryParser = core.defineClass(ctor, instanceMembers, classMembers);
})(typeof exports === "undefined" ? this : exports);
}))(typeof exports === "undefined" ? this : exports);

Просмотреть файл

@ -6,17 +6,18 @@
// login modules, it implements a very specific interface that is documented in
// ../loginhandler.js.
var core = require('../../core'),
crypto = require('crypto'),
jsonWebToken = require('../../jsonwebtoken'),
Buffer = require('buffer').Buffer,
LoginHandler = require('../loginhandler.js'),
AadCert = require('./aadcert'),
certCacheHelper = require('./certcachehelper'),
_ = require('underscore'),
_str = require('underscore.string'),
request = require('request'),
xml2js = require('xml2js');
var core = require('../../core');
var crypto = require('crypto');
var jsonWebToken = require('../../jsonwebtoken');
var Buffer = require('buffer').Buffer;
var LoginHandler = require('../loginhandler.js');
var AadCert = require('./aadcert');
var certCacheHelper = require('./certcachehelper');
var _ = require('underscore');
var _str = require('underscore.string');
var request = require('request');
var xml2js = require('xml2js');
_.mixin(_str.exports());
@ -46,7 +47,7 @@ AadLoginHandler.prototype.initialize = function (done) {
this._initializeIssuers(done);
};
AadLoginHandler.prototype.isNewServerFlowRequest = function (request) {
AadLoginHandler.prototype.isNewServerFlowRequest = request => {
var isNewFlow = true;
// If the query includes either a 'id_token' parameter or an 'error' parameter
@ -74,7 +75,7 @@ AadLoginHandler.prototype.getNewServerFlowResponseHeaders = function (request, c
callback(null, headers);
};
AadLoginHandler.prototype.getProviderTokenFromClientFlowRequest = function (request, callback) {
AadLoginHandler.prototype.getProviderTokenFromClientFlowRequest = (request, callback) => {
callback(new core.MobileServiceError('POST of AAD token is not supported.', core.ErrorCodes.MethodNotAllowed), null);
};
@ -90,11 +91,11 @@ AadLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function (requ
return;
}
var clientId = this.authenticationCredentials.aad.clientId,
idToken = request.query.id_token,
self = this;
var clientId = this.authenticationCredentials.aad.clientId;
var idToken = request.query.id_token;
var self = this;
certCacheHelper.validateToken(this.aadCert, idToken, function (error, validatedToken) {
certCacheHelper.validateToken(this.aadCert, idToken, (error, validatedToken) => {
if (error) {
callback(error, null);
return;
@ -119,7 +120,7 @@ AadLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function (requ
});
};
AadLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function (request, claims, callback, options) {
AadLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = (request, claims, callback, options) => {
var authorizationDetails = {
providerId: claims.sub, // sub is the only 100% unique claims field that is on all AAD users regardless of their type
claims: {
@ -136,8 +137,8 @@ AadLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function (r
// resolve any configured tenant domains to their corresponding issuer values
// by querying AAD metadata for each
AadLoginHandler.prototype._initializeIssuers = function (done) {
var tenants = this.authenticationCredentials.aad.tenants,
self = this;
var tenants = this.authenticationCredentials.aad.tenants;
var self = this;
if (!tenants) {
// if no tenants are configured, no work to do
@ -148,21 +149,19 @@ AadLoginHandler.prototype._initializeIssuers = function (done) {
// create a set of tasks, each of which will query AAD metadata
// for a tenant domain and return the corresponding issuer
self.validIssuers = [];
var tasks = _.map(tenants, function (tenant) {
return function (done) {
self._getIssuerForTenantDomain(tenant, function (err, issuer) {
if (err) {
var msg = _.sprintf(
"Error attempting to query tenant metadata for tenant '%s'. Please verify that each of the " +
"tenants specified is a valid tenant domain (e.g., abc.onmicrosoft.com). %s", tenant, err);
var ex = new core.MobileServiceError(msg, core.ErrorCodes.BadInput);
self.logger.logUser('', LogType.Error, ex);
throw ex;
}
self.validIssuers.push(issuer);
done();
});
};
var tasks = _.map(tenants, tenant => done => {
self._getIssuerForTenantDomain(tenant, (err, issuer) => {
if (err) {
var msg = _.sprintf(
"Error attempting to query tenant metadata for tenant '%s'. Please verify that each of the " +
"tenants specified is a valid tenant domain (e.g., abc.onmicrosoft.com). %s", tenant, err);
var ex = new core.MobileServiceError(msg, core.ErrorCodes.BadInput);
self.logger.logUser('', LogType.Error, ex);
throw ex;
}
self.validIssuers.push(issuer);
done();
});
});
// now execute the tasks in parallel
@ -172,10 +171,10 @@ AadLoginHandler.prototype._initializeIssuers = function (done) {
// Call out to the AAD metadata endpoint for the specified tenant domain
// to get the issuer. E.g. test.onmicrosoft.com => https://sts.windows.net/ae549c78-14a5-4fc8-9719-df4e1007990a
AadLoginHandler.prototype._getIssuerForTenantDomain = function (tenant, callback) {
var metadataUri = _.sprintf('https://%s/%s/federationmetadata/2007-06/federationmetadata.xml', this.loginEndpoint, tenant),
parser = new xml2js.Parser();
var metadataUri = _.sprintf('https://%s/%s/federationmetadata/2007-06/federationmetadata.xml', this.loginEndpoint, tenant);
var parser = new xml2js.Parser();
request(metadataUri, function (err, res, body) {
request(metadataUri, (err, res, body) => {
if (res.statusCode != 200) {
// if the response body includes error details return them
err = body || 'An unspecified error occurred.';

Просмотреть файл

@ -43,7 +43,7 @@ AadCert.prototype.getCerts = function (callback, options) {
var self = this;
// Make call to get the certs
LoginHandler.makeSecureRequest(requestOptions, null, function (error, res, body) {
LoginHandler.makeSecureRequest(requestOptions, null, (error, res, body) => {
var result = null;
// Ensure that the request was successful
if (!error && res.statusCode !== 200) {
@ -68,12 +68,12 @@ AadCert.prototype.getCerts = function (callback, options) {
}
callback(error, result);
}.bind(this));
});
};
AadCert.parseCertificates = function (json) {
var parsedKeys = JSON.parse(json),
certArray = [];
AadCert.parseCertificates = json => {
var parsedKeys = JSON.parse(json);
var certArray = [];
for (var keyNum = 0; keyNum < parsedKeys.keys.length; keyNum++) {
var x5TCertLabel = parsedKeys.keys[keyNum].x5t;

Просмотреть файл

@ -8,7 +8,7 @@ var jsonWebToken = require('../../jsonwebtoken');
exports = module.exports;
exports.isExpired = function (expDate, now) {
exports.isExpired = (expDate, now) => {
if (!now) {
now = new Date();
}
@ -20,7 +20,7 @@ exports.createExpiryDateFromHours = function (hoursInFuture, now) {
return this.createExpiryDateFromMinutes(hoursInFuture * 60, now);
};
exports.createExpiryDateFromMinutes = function (minutesInFuture, now) {
exports.createExpiryDateFromMinutes = (minutesInFuture, now) => {
if (!now) {
now = new Date();
}
@ -34,8 +34,9 @@ exports.createExpiryDateFromMinutes = function (minutesInFuture, now) {
exports.refreshIntervalExpired = function (minRefreshIntervalMinutes, lastRefresh) {
// We allow a refresh only if we haven't refreshed in the
// last minRefreshIntervalMinutes
var notBeforeDate = this.createExpiryDateFromMinutes(minRefreshIntervalMinutes, lastRefresh),
now = new Date();
var notBeforeDate = this.createExpiryDateFromMinutes(minRefreshIntervalMinutes, lastRefresh);
var now = new Date();
return this.isExpired(notBeforeDate, now);
};
@ -43,13 +44,13 @@ exports.refreshIntervalExpired = function (minRefreshIntervalMinutes, lastRefres
// Attempts to validate the specified token using the provided cert manager.
// If the token fails validation due to a kid/x5t lookup failure, a cert
// refresh will be performed, and the validation will be attempted once more.
exports.validateToken = function (certManager, token, callback) {
exports.validateToken = (certManager, token, callback) => {
var retry = true;
// define a function to get the certs and validate the token,
// so that in the case of failures we can retry
var validateToken = function (options) {
certManager.getCerts(function (error, certs) {
var validateToken = options => {
certManager.getCerts((error, certs) => {
if (error) {
callback(error);
return;

Просмотреть файл

@ -6,12 +6,13 @@
// login modules, it implements a very specific interface that is documented in
// ../loginhandler.js.
var core = require('../../core'),
jsonWebToken = require('../../jsonwebtoken'),
url = require('url'),
LoginHandler = require('../loginhandler.js'),
_ = require('underscore'),
_str = require('underscore.string');
var core = require('../../core');
var jsonWebToken = require('../../jsonwebtoken');
var url = require('url');
var LoginHandler = require('../loginhandler.js');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
@ -35,7 +36,7 @@ function FacebookLoginHandler(authenticationCredentials, logger) {
this.logger = logger;
}
FacebookLoginHandler.prototype.isNewServerFlowRequest = function (request) {
FacebookLoginHandler.prototype.isNewServerFlowRequest = request => {
var isNewFlow = true;
// If the query includes either a 'code' parameter or an 'error' parameter
@ -134,7 +135,7 @@ FacebookLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = functi
method: 'GET'
};
LoginHandler.makeSecureRequest(graphApi, null, function (error, res, body) {
LoginHandler.makeSecureRequest(graphApi, null, (error, res, body) => {
var authorizationDetails = null;
// Ensure that the request was successful
@ -185,7 +186,7 @@ FacebookLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = functi
});
};
FacebookLoginHandler.prototype._getUrlByRequestMode = function (request, urlName) {
FacebookLoginHandler.prototype._getUrlByRequestMode = (request, urlName) => {
var providerMode = request.query.useBeta ? 'beta' : 'prod';
var url = urls[providerMode][urlName];
return url;
@ -205,7 +206,7 @@ FacebookLoginHandler.prototype._normalizeScope = function () {
};
function _retrieveLongLivedAccessToken(options, errorPrefix, callback) {
LoginHandler.makeSecureRequest(options, null, function (error, res, body) {
LoginHandler.makeSecureRequest(options, null, (error, res, body) => {
var providerToken = null;

Просмотреть файл

@ -6,13 +6,14 @@
// login modules, it implements a very specific interface that is documented in
// ../loginhandler.js.
var core = require('../../core'),
jsonWebToken = require('../../jsonwebtoken'),
LoginHandler = require('../loginhandler'),
_ = require('underscore'),
_str = require('underscore.string'),
GoogleCert = require('./googlecert'),
certCacheHelper = require('./certcachehelper');
var core = require('../../core');
var jsonWebToken = require('../../jsonwebtoken');
var LoginHandler = require('../loginhandler');
var _ = require('underscore');
var _str = require('underscore.string');
var GoogleCert = require('./googlecert');
var certCacheHelper = require('./certcachehelper');
_.mixin(_str.exports());
@ -25,7 +26,7 @@ function GoogleLoginHandler(authenticationCredentials, logger) {
this.logger = logger;
}
GoogleLoginHandler.prototype.isNewServerFlowRequest = function (request) {
GoogleLoginHandler.prototype.isNewServerFlowRequest = request => {
var isNewFlow = true;
// If the query includes either a 'code' parameter or an 'error' parameter
@ -52,11 +53,11 @@ GoogleLoginHandler.prototype.getNewServerFlowResponseHeaders = function (request
};
GoogleLoginHandler.prototype.getProviderTokenFromClientFlowRequest = function (request, callback) {
var body = request.body,
self = this;
var body = request.body;
var self = this;
if (_.isObject(body) && _.isString(body.id_token)) {
certCacheHelper.validateToken(this.googleCert, body.id_token, function (error, validatedIdToken) {
certCacheHelper.validateToken(this.googleCert, body.id_token, (error, validatedIdToken) => {
if (error) {
callback(error);
return;
@ -102,16 +103,17 @@ GoogleLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function (r
};
GoogleLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function (request, providerInformation, callback, options) {
var self = this,
providerId = providerInformation.id_token.claims.sub,
authorizationDetails = {
providerId: providerId,
claims: {
},
secrets: {
}
};
var self = this;
var providerId = providerInformation.id_token.claims.sub;
var authorizationDetails = {
providerId,
claims: {
},
secrets: {
}
};
var accessToken = providerInformation.access_token;
if (accessToken) {
// in the client flow, we won't have an access_token
@ -119,15 +121,16 @@ GoogleLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function
}
if (accessToken && options.usersEnabled) {
var googleUri = '/oauth2/v3/userinfo?access_token=' + encodeURIComponent(accessToken),
graphApi = {
host: 'www.googleapis.com',
port: 443,
path: googleUri,
method: 'GET'
};
var googleUri = '/oauth2/v3/userinfo?access_token=' + encodeURIComponent(accessToken);
LoginHandler.makeSecureRequest(graphApi, null, function (error, res, body) {
var graphApi = {
host: 'www.googleapis.com',
port: 443,
path: googleUri,
method: 'GET'
};
LoginHandler.makeSecureRequest(graphApi, null, (error, res, body) => {
if (error || res.statusCode !== 200) {
callback(new Error('Failed to retrieve user info for google due to error: ' + error));
}
@ -175,10 +178,11 @@ GoogleLoginHandler.prototype._getProviderToken = function (code, currentUri, idT
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
},
self = this;
};
LoginHandler.makeSecureRequest(options, authParams, function (error, res, authBody) {
var self = this;
LoginHandler.makeSecureRequest(options, authParams, (error, res, authBody) => {
// Ensure that the request was successful
if (!error && res.statusCode !== 200) {
error = new Error('The Google API request failed with HTTP status code ' + res.statusCode);
@ -191,11 +195,12 @@ GoogleLoginHandler.prototype._getProviderToken = function (code, currentUri, idT
// Response should contain accessToken and id_token. (If we change initial redirect
// to offline, it would also contain refresh_token)
var parsedResponse = JSON.parse(authBody),
idToken = parsedResponse.id_token;
var parsedResponse = JSON.parse(authBody);
var idToken = parsedResponse.id_token;
// Ensure the id_token returned is valid and stash the parsed response to re-use within getAuthorizationDetailsFromProviderToken
certCacheHelper.validateToken(self.googleCert, idToken, function (innerError, responseIdToken) {
certCacheHelper.validateToken(self.googleCert, idToken, (innerError, responseIdToken) => {
if (innerError) {
callback(innerError);
return;

Просмотреть файл

@ -4,8 +4,9 @@
//
// This module provides a way to asynchronously get Google certs to validate Google id tokens
var LoginHandler = require('../loginhandler.js'),
certCacheHelper = require('./certcachehelper');
var LoginHandler = require('../loginhandler.js');
var certCacheHelper = require('./certcachehelper');
exports = module.exports = GoogleCert;
@ -42,7 +43,7 @@ GoogleCert.prototype.getCerts = function (callback, options) {
var self = this;
// Make call to get the certs
LoginHandler.makeSecureRequest(requestOptions, null, function (error, res, body) {
LoginHandler.makeSecureRequest(requestOptions, null, (error, res, body) => {
var result = null;
// Ensure that the request was successful

Просмотреть файл

@ -9,11 +9,12 @@
// The server authentication flow is documented at:
// http://msdn.microsoft.com/en-us/library/live/hh243647.aspx#authcodegrant
var core = require('../../core'),
jsonWebToken = require('../../jsonwebtoken'),
LoginHandler = require('../loginhandler'),
_ = require('underscore'),
_str = require('underscore.string');
var core = require('../../core');
var jsonWebToken = require('../../jsonwebtoken');
var LoginHandler = require('../loginhandler');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
@ -25,7 +26,7 @@ function MicrosoftAccountLoginHandler(authenticationCredentials, logger) {
this.logger = logger;
}
MicrosoftAccountLoginHandler.prototype.isNewServerFlowRequest = function (request) {
MicrosoftAccountLoginHandler.prototype.isNewServerFlowRequest = request => {
var isNewFlow = true;
// If the query includes either a 'code' parameter or an 'error' parameter
@ -55,7 +56,7 @@ MicrosoftAccountLoginHandler.prototype.getNewServerFlowResponseHeaders = functio
callback(null, { Location: microsoftAccountUri });
};
MicrosoftAccountLoginHandler.prototype.getProviderTokenFromClientFlowRequest = function (request, callback) {
MicrosoftAccountLoginHandler.prototype.getProviderTokenFromClientFlowRequest = (request, callback) => {
var error = null;
var providerToken = null;
@ -107,7 +108,7 @@ MicrosoftAccountLoginHandler.prototype.getProviderTokenFromServerFlowRequest = f
}
};
LoginHandler.makeSecureRequest(options, data, function (error, res, body) {
LoginHandler.makeSecureRequest(options, data, (error, res, body) => {
var providerToken = null;
@ -147,13 +148,15 @@ MicrosoftAccountLoginHandler.prototype.getProviderTokenFromServerFlowRequest = f
};
MicrosoftAccountLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function (request, providerToken, callback, options) {
var self = this,
// Parse the authentication token portion of the providerToken
unparsedToken = providerToken.authenticationToken,
key = this.authenticationCredentials.microsoftaccount.clientSecret,
parsedToken = null,
error = null,
authorizationDetails = null;
var self = this;
var // Parse the authentication token portion of the providerToken
unparsedToken = providerToken.authenticationToken;
var key = this.authenticationCredentials.microsoftaccount.clientSecret;
var parsedToken = null;
var error = null;
var authorizationDetails = null;
try {
parsedToken = jsonWebToken.parse(unparsedToken, key, jsonWebToken.windowsLiveSigningSuffix);
@ -177,15 +180,16 @@ MicrosoftAccountLoginHandler.prototype.getAuthorizationDetailsFromProviderToken
}
if (authorizationDetails && authorizationDetails.secrets.accessToken && options.usersEnabled) {
var microsftUri = '/v5.0/me?access_token=' + encodeURIComponent(authorizationDetails.secrets.accessToken),
graphApi = {
host: 'apis.live.net',
port: 443,
path: microsftUri,
method: 'GET'
};
var microsftUri = '/v5.0/me?access_token=' + encodeURIComponent(authorizationDetails.secrets.accessToken);
LoginHandler.makeSecureRequest(graphApi, null, function (error, res, body) {
var graphApi = {
host: 'apis.live.net',
port: 443,
path: microsftUri,
method: 'GET'
};
LoginHandler.makeSecureRequest(graphApi, null, (error, res, body) => {
if (error || res.statusCode !== 200) {
callback(new Error('Failed to retrieve user info for microsoft account due to error: ' + error));
}

Просмотреть файл

@ -12,13 +12,14 @@
// An Example of this flow can be found at:
// https://gist.github.com/555607
var core = require('../../core'),
jsonWebToken = require('../../jsonwebtoken'),
OAuth = require('oauth').OAuth,
LoginHandler = require('../loginhandler'),
Encryptor = require('../../encryptor'),
_ = require('underscore'),
_str = require('underscore.string');
var core = require('../../core');
var jsonWebToken = require('../../jsonwebtoken');
var OAuth = require('oauth').OAuth;
var LoginHandler = require('../loginhandler');
var Encryptor = require('../../encryptor');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
@ -38,7 +39,7 @@ TwitterLoginHandler.prototype.oAuthStateNotSupported = true;
// is important. This ensures that the LoginHandler.js will clean up this cookie for us.
TwitterLoginHandler.RequestTokenCookieName = 'wams_rt';
TwitterLoginHandler.prototype.isNewServerFlowRequest = function (request) {
TwitterLoginHandler.prototype.isNewServerFlowRequest = request => {
var isNewFlow = true;
// If the query includes an 'oauth_verifier' parameter then this is the
@ -57,7 +58,7 @@ TwitterLoginHandler.prototype.getNewServerFlowResponseHeaders = function (reques
consumerSecret,
currentUri);
oauth.getOAuthRequestToken(function (error, requestToken, requestTokenSecret, results) {
oauth.getOAuthRequestToken((error, requestToken, requestTokenSecret, results) => {
if (error) {
error = new Error('Unable to obtain OAuth request token from Twitter.');
@ -84,7 +85,7 @@ TwitterLoginHandler.prototype.getNewServerFlowResponseHeaders = function (reques
});
};
TwitterLoginHandler.prototype.getProviderTokenFromClientFlowRequest = function (request, callback) {
TwitterLoginHandler.prototype.getProviderTokenFromClientFlowRequest = (request, callback) => {
var error = new core.MobileServiceError('POST of Twitter token is not supported.', core.ErrorCodes.MethodNotAllowed);
callback(error, null);
};
@ -138,7 +139,7 @@ TwitterLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function (
oauth.getOAuthAccessToken(requestToken.rt,
requestToken.rts,
request.query.oauth_verifier,
function (error, accessToken, accessTokenSecret, results) {
(error, accessToken, accessTokenSecret, results) => {
var providerToken = null;
if (error) {
@ -148,9 +149,9 @@ TwitterLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function (
// Create a 'providerToken' out of the accessToken, accessTokenSecret and results
if (!error) {
providerToken = {
accessToken: accessToken,
accessTokenSecret: accessTokenSecret,
results: results
accessToken,
accessTokenSecret,
results
};
}
@ -158,7 +159,7 @@ TwitterLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function (
});
};
TwitterLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function (request, providerToken, callback, options) {
TwitterLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = (request, providerToken, callback, options) => {
var error = null;
var authorizationDetails = null;
@ -170,7 +171,7 @@ TwitterLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = functio
else {
var providerId = providerToken.results.user_id;
authorizationDetails = {
providerId: providerId,
providerId,
claims: {
// name: providerToken.results.name
},

Просмотреть файл

@ -4,15 +4,16 @@
//
// This module is encapsulates the data operations invoked by scripts.
var Query = require('../Zumo.Node').Query,
scriptErrors = require('../script/scripterror'),
StatusCodes = require('../statuscodes').StatusCodes,
resource = require('../resources'),
core = require('../core'),
_ = require('underscore'),
_str = require('underscore.string');
var Query = require('../Zumo.Node').Query;
_.mixin(_str.exports());
var scriptErrors = require('../script/scripterror');
var StatusCodes = require('../statuscodes').StatusCodes;
var resource = require('../resources');
var core = require('../core');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
exports = module.exports = DataOperation;
@ -41,7 +42,7 @@ DataOperation.prototype.read = function (table, query, options, responseCallback
projection = query.getComponents().projection;
}
var responseEvaluator = function (results) {
var responseEvaluator = results => {
if (query.id !== undefined && results && (results.length === 0)) {
return { error: self._handleItemNotFound(query.id) };
} else {
@ -51,7 +52,7 @@ DataOperation.prototype.read = function (table, query, options, responseCallback
}
}
return { results: results };
return { results };
}
};
@ -71,7 +72,7 @@ DataOperation.prototype.read = function (table, query, options, responseCallback
DataOperation.prototype.update = function (table, item, options, responseCallback, scriptCallback) {
var self = this;
var responseEvaluator = function (rowCount) {
var responseEvaluator = rowCount => {
if (rowCount === 0) {
return { error: self._handleItemNotFound(item.id) };
} else {
@ -86,9 +87,9 @@ DataOperation.prototype.update = function (table, item, options, responseCallbac
};
DataOperation.prototype.del = function (table, itemOrId, options, responseCallback, scriptCallback) {
var self = this,
id = itemOrId,
version = null;
var self = this;
var id = itemOrId;
var version = null;
if (core.isObject(itemOrId))
{
@ -96,7 +97,7 @@ DataOperation.prototype.del = function (table, itemOrId, options, responseCallba
version = itemOrId.__version;
}
var responseEvaluator = function (rowCount) {
var responseEvaluator = rowCount => {
if (rowCount === 0) {
return { error: self._handleItemNotFound(id) };
} else {
@ -131,7 +132,7 @@ function unwrapInlineCount(results) {
DataOperation.prototype.createStorageCallback = function (table, successCode, responseCallback, scriptCallback, responseEvaluator) {
var self = this;
return function (err, results) {
return (err, results) => {
if (typeof responseEvaluator === 'function' && !err) {
// Use the passed in response evaluator function to update the error
// and results objects passed back from the storage layer.
@ -173,7 +174,7 @@ DataOperation.prototype.createStorageCallback = function (table, successCode, re
// if the specified query is a query builder, convert it back to our
// query representation
DataOperation.prototype.unwrapQueryBuilder = function (query) {
DataOperation.prototype.unwrapQueryBuilder = query => {
if (query && query.constructor === Query) {
var unwrapped = {};
@ -211,6 +212,4 @@ DataOperation.prototype.unwrapQueryBuilder = function (query) {
return query;
};
DataOperation.prototype._handleItemNotFound = function (id) {
return new core.MobileServiceError(_.sprintf(resource.itemNotFound, id.toString()), core.ErrorCodes.ItemNotFound);
};
DataOperation.prototype._handleItemNotFound = id => new core.MobileServiceError(_.sprintf(resource.itemNotFound, id.toString()), core.ErrorCodes.ItemNotFound);

Просмотреть файл

@ -6,17 +6,18 @@
// if defined for the operation. Script services are exposed to scripts via the context argument
// passed to the script function. A separate dataPipeline instance is created per request.
var core = require('../core'),
DataOperation = require('./dataoperation'),
scriptErrors = require('../script/scripterror'),
ScriptState = require('../script/scriptstate'),
ScriptManager = require('../script/scriptmanager'),
resource = require('../resources'),
Query = require('../Zumo.Node').Query,
_ = require('underscore'),
_str = require('underscore.string');
var core = require('../core');
_.mixin(_str.exports());
var DataOperation = require('./dataoperation');
var scriptErrors = require('../script/scripterror');
var ScriptState = require('../script/scriptstate');
var ScriptManager = require('../script/scriptmanager');
var resource = require('../resources');
var Query = require('../Zumo.Node').Query;
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
require('../storage/sqlhelpers');
@ -51,7 +52,7 @@ DataPipeline.prototype.read = function (query, responseCallback) {
// if this is a query by id, we wrap the response callback
// so we can do result validation to make sure only a singleton is returned
if (query.id) {
responseCallback = _.wrap(responseCallback, function (originalCallback, err, results, statusCode) {
responseCallback = _.wrap(responseCallback, (originalCallback, err, results, statusCode) => {
if (results && core.isArray(results)) {
if (results.length === 1) {
results = results[0];
@ -89,7 +90,7 @@ DataPipeline.prototype.update = function (item, responseCallback) {
// define a pre-execute callback to do validation of the operation
// prior to actually executing the data opration
var executeCallback = function (scriptArg) {
var executeCallback = scriptArg => {
if (scriptArg.id !== originalId) {
var error = new core.MobileServiceError("Update scripts cannot modify the id of the item to be updated.", core.ErrorCodes.ScriptError);
@ -141,7 +142,7 @@ DataPipeline.prototype._executeScript = function (operationName, scriptArg, resp
var logSourceName = self.scriptManager.getLogSourceName(this.table, operationName);
// Create a small state machine which will manage script execution.
var scriptState = new ScriptState(operationName, scriptArg, tableMetadata, responseCallback, self.logger, logSourceName);
scriptState.executeCallback = function (scriptCallback, systemParameters) {
scriptState.executeCallback = (scriptCallback, systemParameters) => {
// If the callback doesn't exist or returns true, run the data operation
if (!executeCallback || executeCallback(scriptArg)) {
var dataOperation = self._createDataOperation(operationName);
@ -150,14 +151,14 @@ DataPipeline.prototype._executeScript = function (operationName, scriptArg, resp
}
};
self.operationContext.execute = function (callbackOptions) {
self.operationContext.execute = callbackOptions => {
self.logger.trace(logSource, 'Script called execute');
scriptState.execute(callbackOptions);
};
self.operationContext.respond = function (statusCode, result) {
self.logger.trace(logSource, 'Script called respond');
scriptState.respond.apply(scriptState, arguments);
scriptState.respond(...arguments);
};
var runnerOptions = {
@ -211,22 +212,20 @@ DataPipeline.prototype.getQueryBuilder = function (query) {
return queryBuilder;
};
DataPipeline.prototype._wrapWithNoScriptErrorTransforms = function (responseCallback) {
return _.wrap(responseCallback, function (oldCallback, err, result, statusCode) {
// There is no script. Any non application level sql error will be treated
// as an end user input error.
if (SqlHelpers.isSqlError(err) && !SqlHelpers.isApplicationError(err)) {
oldCallback(new core.MobileServiceError(resource.badRequest, core.ErrorCodes.BadInput));
} else {
oldCallback(err, result, statusCode);
}
});
};
DataPipeline.prototype._wrapWithNoScriptErrorTransforms = responseCallback => _.wrap(responseCallback, (oldCallback, err, result, statusCode) => {
// There is no script. Any non application level sql error will be treated
// as an end user input error.
if (SqlHelpers.isSqlError(err) && !SqlHelpers.isApplicationError(err)) {
oldCallback(new core.MobileServiceError(resource.badRequest, core.ErrorCodes.BadInput));
} else {
oldCallback(err, result, statusCode);
}
});
DataPipeline.prototype._wrapWithUserLogging = function (responseCallback, operationName) {
var self = this;
return _.wrap(responseCallback, function (oldCallback, err, result, statusCode) {
return _.wrap(responseCallback, (oldCallback, err, result, statusCode) => {
// This callback pass-through will log any unhandled/unlogged SQL error messages
// that are about to be passed up stack and returned to the user.
// This block of code will log all unhandled SQL errors regardless of

Просмотреть файл

@ -6,9 +6,10 @@
// which is used by the availability monitoring feature. This endpoint is secured -
// it requires the master key header.
var StatusCodes = require('../statuscodes').StatusCodes,
_ = require('underscore'),
_str = require('underscore.string');
var StatusCodes = require('../statuscodes').StatusCodes;
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
@ -23,9 +24,9 @@ function DiagnosticsHandler(appName, version, storage) {
}
DiagnosticsHandler.prototype.handle = function (req, res) {
var logger = req._context.logger,
responseCallback = req._context.responseCallback,
status = StatusCodes.OK;
var logger = req._context.logger;
var responseCallback = req._context.responseCallback;
var status = StatusCodes.OK;
logger.trace(logSource, 'Processing request');
@ -40,7 +41,7 @@ DiagnosticsHandler.prototype.handle = function (req, res) {
}
};
this._getSqlStatus(req, function (err, sqlStatus) {
this._getSqlStatus(req, (err, sqlStatus) => {
if (err) {
// indicate degraded service via the top level status code
status = StatusCodes.SERVICE_UNAVAILABLE;
@ -58,19 +59,22 @@ DiagnosticsHandler.prototype.handle = function (req, res) {
};
DiagnosticsHandler.prototype._getSqlStatus = function (req, callback) {
var logger = req._context.logger,
sqlStatus = {
statusCode: StatusCodes.OK,
latencyMS: 0
},
startTime = new Date(),
options = {
disableUserLog: true
};
var logger = req._context.logger;
var sqlStatus = {
statusCode: StatusCodes.OK,
latencyMS: 0
};
var startTime = new Date();
var options = {
disableUserLog: true
};
logger.trace(logSource, 'Checking SQL connectivity');
this.storage.executeSql('SELECT', "SELECT getutcdate() AS currentDate", null, logger, options, function (err) {
this.storage.executeSql('SELECT', "SELECT getutcdate() AS currentDate", null, logger, options, err => {
if (err) {
sqlStatus.statusCode = StatusCodes.SERVICE_UNAVAILABLE;
var errDetails = [];

Просмотреть файл

@ -4,12 +4,13 @@
//
// This module has helper functions for transforming exceptions to http errors
var core = require('../core.js'),
StatusCodes = require('../statuscodes').StatusCodes;
var core = require('../core.js');
var StatusCodes = require('../statuscodes').StatusCodes;
ErrorHelper = {};
ErrorHelper.formatError = function (err, statusCode, requestID) {
ErrorHelper.formatError = (err, statusCode, requestID) => {
if (err) {
var formattedErr;
@ -75,11 +76,9 @@ ErrorHelper.formatError = function (err, statusCode, requestID) {
return err;
};
ErrorHelper.createInternalServerError = function () {
return {
code: StatusCodes.INTERNAL_SERVER_ERROR,
error: 'Error: Internal Server Error'
};
};
ErrorHelper.createInternalServerError = () => ({
code: StatusCodes.INTERNAL_SERVER_ERROR,
error: 'Error: Internal Server Error'
});
exports = module.exports = ErrorHelper;

Просмотреть файл

@ -4,12 +4,13 @@
//
// This module has helper functions for working with etags
var resource = require('../resources'),
core = require('../core.js');
var resource = require('../resources');
var core = require('../core.js');
ETagHelper = {};
ETagHelper.doesIfNoneMatchHeaderMatchesEtag = function (ifNoneMatch, etag) {
ETagHelper.doesIfNoneMatchHeaderMatchesEtag = (ifNoneMatch, etag) => {
// an if-none-match header can be a '*' or a comma-seperated list
// of etage values
var doesMatch = false;
@ -24,7 +25,7 @@ ETagHelper.doesIfNoneMatchHeaderMatchesEtag = function (ifNoneMatch, etag) {
// check each etag in the if-none-match header against
// the response etag
ifNoneMatch.split(",").forEach(function (ifNoneMatchValue) {
ifNoneMatch.split(",").forEach(ifNoneMatchValue => {
if (ifNoneMatchValue.trim() === etag) {
doesMatch = true;
}
@ -35,7 +36,7 @@ ETagHelper.doesIfNoneMatchHeaderMatchesEtag = function (ifNoneMatch, etag) {
return doesMatch;
};
ETagHelper.setVersionFromIfMatchHeader = function (request, item, tableMetadata, responseCallback) {
ETagHelper.setVersionFromIfMatchHeader = (request, item, tableMetadata, responseCallback) => {
// check for an if-match header and set the body version
if (!tableMetadata.supportsConflict) {
return true;
@ -55,7 +56,7 @@ ETagHelper.setVersionFromIfMatchHeader = function (request, item, tableMetadata,
return true;
};
ETagHelper.parseIfMatchHeader = function (request) {
ETagHelper.parseIfMatchHeader = request => {
var ifMatch = request.headers["if-match"];
if (!ifMatch || ifMatch.trim() === '*') {
return null;
@ -64,7 +65,7 @@ ETagHelper.parseIfMatchHeader = function (request) {
var etags = [];
try {
ifMatch.split(",")
.forEach(function (etag) {
.forEach(etag => {
etag = JSON.parse(etag.trim());
if (!core.isString(etag)) {
throw new core.MobileServiceError(resource.invalidIfMatchHeader, core.ErrorCodes.BadInput);

Просмотреть файл

@ -5,22 +5,22 @@
// Supplies CORS headers as per app configuration
function CorsHelper(options) {
var url = require('url');
var defaultCrossDomainWhitelist = [
{ host: 'localhost' }
],
configuredCrossDomainWhitelist = options.crossDomainWhitelist || defaultCrossDomainWhitelist,
isNullAllowed = false,
allowedHostNamesRegexes = getHostNameRegexesFromConfiguredWhitelist(configuredCrossDomainWhitelist),
allowedHeadersRegex = /^[a-z0-9\-\,\s]{1,500}$/i; // Lenient enough to match any header names we will ever use
]; // Lenient enough to match any header names we will ever use
var configuredCrossDomainWhitelist = options.crossDomainWhitelist || defaultCrossDomainWhitelist;
var isNullAllowed = false;
var allowedHostNamesRegexes = getHostNameRegexesFromConfiguredWhitelist(configuredCrossDomainWhitelist);
var allowedHeadersRegex = /^[a-z0-9\-\,\s]{1,500}$/i;
this.getCorsHeaders = function (request) {
var incomingHeaders = request.headers || {},
requestedOrigin = incomingHeaders.origin,
requestedHeaders = incomingHeaders['access-control-request-headers'],
corsHeaders = {};
var incomingHeaders = request.headers || {};
var requestedOrigin = incomingHeaders.origin;
var requestedHeaders = incomingHeaders['access-control-request-headers'];
var corsHeaders = {};
if (requestedOrigin && this.isAllowedOrigin(requestedOrigin)) {
// CORS doesn't permit multiple origins or wildcards, so the standard
@ -43,17 +43,20 @@ function CorsHelper(options) {
return corsHeaders;
};
this.isAllowedOrigin = function (origin) {
this.isAllowedOrigin = origin => {
// special case 'null' that is sent from browser on local files
if (isNullAllowed && origin === 'null') {
return true;
}
// Extract the components of the origin
var parsedOrigin = url.parse(origin),
originHostName = parsedOrigin && parsedOrigin.hostname, // Note that "host" includes the port; "hostname" doesn't
originProtocol = parsedOrigin && parsedOrigin.protocol,
originPath = parsedOrigin && parsedOrigin.path;
var parsedOrigin = url.parse(origin);
var // Note that "host" includes the port; "hostname" doesn't
originHostName = parsedOrigin && parsedOrigin.hostname;
var originProtocol = parsedOrigin && parsedOrigin.protocol;
var originPath = parsedOrigin && parsedOrigin.path;
// Validate protocol
if (!originProtocol || !isAllowedProtocol(originProtocol)) {
@ -70,17 +73,15 @@ function CorsHelper(options) {
return false;
}
return allowedHostNamesRegexes.some(function (hostNameRegex) {
return hostNameRegex.test(originHostName);
});
return allowedHostNamesRegexes.some(hostNameRegex => hostNameRegex.test(originHostName));
};
function isAllowedProtocol(protocol) {
// This means that filesystem origins ("null") aren't supported right now
// even if you allow "*"
return protocol === 'http:' || protocol === 'https:' || protocol === 'ms-appx-web:';
}
function isAllowedPath(path) {
// The W3C spec isn't especially clear about host origins should be formatted,
// so to be graceful we permit trailing slashes even though I'm not aware of a
@ -114,7 +115,7 @@ function CorsHelper(options) {
var result = [];
if (whitelist) {
whitelist.forEach(function (whitelistEntry) {
whitelist.forEach(whitelistEntry => {
if (!whitelistEntry) {
return;
}

Просмотреть файл

@ -17,19 +17,19 @@
exports = module.exports = CrossDomainHandler;
var core = require('../../core'),
templating = require('./templating'),
StatusCodes = require('../../statuscodes').StatusCodes,
logSource = 'CrossDomainHandler';
var core = require('../../core');
var templating = require('./templating');
var StatusCodes = require('../../statuscodes').StatusCodes;
var logSource = 'CrossDomainHandler';
function CrossDomainHandler(corsHelper) {
this.corsHelper = corsHelper;
}
CrossDomainHandler.prototype.handle = function (req, res) {
var logger = req._context.logger,
responseCallback = req._context.responseCallback;
var logger = req._context.logger;
var responseCallback = req._context.responseCallback;
logger.trace(logSource, 'Processing request');
switch (req.params.crossDomainItem) {
@ -63,13 +63,14 @@ CrossDomainHandler.prototype.handle = function (req, res) {
CrossDomainHandler.prototype._getAllowedOriginFromQueryParams = function (request, queryParamName, responseCallback) {
// This function returns a truthy value only if it satisfies the whitelist
var queryParams = request.query,
attemptedOrigin = queryParams && queryParams[queryParamName];
var queryParams = request.query;
var attemptedOrigin = queryParams && queryParams[queryParamName];
if (attemptedOrigin && this.corsHelper.isAllowedOrigin(attemptedOrigin)) {
return attemptedOrigin;
}
responseCallback(new core.MobileServiceError('Not a whitelisted origin: ' + attemptedOrigin), null, StatusCodes.UNAUTHORIZED);
return null;
};

Просмотреть файл

@ -6,14 +6,14 @@
// We could switch to a proper template engine at some point if desired
exports = module.exports = {
render: render
render
};
var fs = require('fs'),
path = require('path'),
StatusCodes = require('../../statuscodes').StatusCodes,
templatesDir = path.resolve(__dirname, 'templates'),
templatesCache = readAllTemplatesSync(templatesDir); // Load only once on app initialization
var fs = require('fs'); // Load only once on app initialization
var path = require('path');
var StatusCodes = require('../../statuscodes').StatusCodes;
var templatesDir = path.resolve(__dirname, 'templates');
var templatesCache = readAllTemplatesSync(templatesDir);
function render(responseCallback, templateName, data, responseHeaders) {
if (!templatesCache.hasOwnProperty(templateName)) {
@ -45,13 +45,11 @@ function replaceTokens(text, tokens) {
}
function readAllTemplatesSync(dir) {
var files = fs.readdirSync(dir),
htmlFiles = files.filter(function (filename) {
return path.extname(filename) == '.html';
}),
result = {};
var files = fs.readdirSync(dir);
var htmlFiles = files.filter(filename => path.extname(filename) == '.html');
var result = {};
htmlFiles.forEach(function (filename) {
htmlFiles.forEach(filename => {
result[filename] = fs.readFileSync(path.resolve(dir, filename), 'utf8');
});

Просмотреть файл

@ -50,21 +50,21 @@
exports = module.exports = LoginHandler;
var core = require('../core'),
UserService = require('../users/userService'),
jsonWebToken = require('../jsonwebtoken'),
StatusCodes = require('../statuscodes').StatusCodes,
templating = require('./html/templating'),
https = require('https'),
Encryptor = require('../encryptor'),
Twitter = require('./authentication/twitter'),
Google = require('./authentication/google'),
Facebook = require('./authentication/facebook'),
MicrosoftAccount = require('./authentication/microsoftaccount'),
Aad = require('./authentication/aad'),
resources = require('../resources'),
_ = require('underscore'),
_str = require('underscore.string');
var core = require('../core');
var UserService = require('../users/userService');
var jsonWebToken = require('../jsonwebtoken');
var StatusCodes = require('../statuscodes').StatusCodes;
var templating = require('./html/templating');
var https = require('https');
var Encryptor = require('../encryptor');
var Twitter = require('./authentication/twitter');
var Google = require('./authentication/google');
var Facebook = require('./authentication/facebook');
var MicrosoftAccount = require('./authentication/microsoftaccount');
var Aad = require('./authentication/aad');
var resources = require('../resources');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
@ -114,10 +114,10 @@ LoginHandler.prototype.initialize = function (done) {
};
LoginHandler.prototype.handle = function (req, res) {
var logger = req._context.logger,
metrics = req._context.metrics,
responseCallback = req._context.responseCallback,
request = req._context.parsedRequest;
var logger = req._context.logger;
var metrics = req._context.metrics;
var responseCallback = req._context.responseCallback;
var request = req._context.parsedRequest;
request.query = req.query; // login needs the raw query
request.authenticationProvider = req.params.authenticationProvider;
@ -135,10 +135,10 @@ LoginHandler.prototype.handle = function (req, res) {
var loginContext = {
loginHandler: this,
corsHelper: this.corsHelper,
request: request,
responseCallback: responseCallback,
logger: logger,
metrics: metrics
request,
responseCallback,
logger,
metrics
};
// If this is a completed server flow, just return OK
@ -199,7 +199,7 @@ LoginHandler.prototype._handleClientFlowRequest = function (loginContext) {
logger.trace(logSource, _.sprintf('Getting the %s provider token from the client flow request.', providerName));
// Get the provider's token out of the request
provider.getProviderTokenFromClientFlowRequest(request, function (error, providerToken) {
provider.getProviderTokenFromClientFlowRequest(request, (error, providerToken) => {
if (error) {
_respondWithError(loginContext, error);
return;
@ -208,18 +208,18 @@ LoginHandler.prototype._handleClientFlowRequest = function (loginContext) {
logger.trace(logSource, _.sprintf('Getting the %s provider token from the client flow request succeeded.', providerName));
logger.trace(logSource, _.sprintf('Exchanging the %s provider token for a Windows Azure Mobile Services token.', providerName));
handler.userService.isEnabled(function (err, usersEnabled) {
handler.userService.isEnabled((err, usersEnabled) => {
var options = {
usersEnabled: usersEnabled
usersEnabled
};
provider.getAuthorizationDetailsFromProviderToken(request, providerToken, function (innerError, authorizationDetails) {
provider.getAuthorizationDetailsFromProviderToken(request, providerToken, (innerError, authorizationDetails) => {
if (innerError) {
_respondWithError(loginContext, innerError);
return;
}
self._createResponseForLoginToken(logger, loginContext, authorizationDetails, providerName, function (err, responseBody) {
self._createResponseForLoginToken(logger, loginContext, authorizationDetails, providerName, (err, responseBody) => {
if (err) {
_respondWithError(loginContext, err);
return;
@ -232,7 +232,7 @@ LoginHandler.prototype._handleClientFlowRequest = function (loginContext) {
});
};
LoginHandler.prototype._handleServerFlowRequest = function (loginContext) {
LoginHandler.prototype._handleServerFlowRequest = loginContext => {
// A server authentication flow will consist of two requests. The client will first
// send a request to initiate the flow for a particular provider and we'll redirect
// the client to the provider's login page. After the user logs in with the provider,
@ -267,20 +267,20 @@ LoginHandler.prototype._handleServerFlowRequest = function (loginContext) {
// Any errors that might occur when making the request or getting the response are
// marshalled to the callback, which has the following signature:
// callback(error, response, responseBody)
LoginHandler.makeSecureRequest = function (requestOptions, requestBody, callback) {
LoginHandler.makeSecureRequest = (requestOptions, requestBody, callback) => {
var request = https.request(requestOptions, function (response) {
var request = https.request(requestOptions, response => {
var responseBody = '';
response.on('data', function (data) {
response.on('data', data => {
responseBody += data;
});
response.on('end', function () {
response.on('end', () => {
callback(null, response, responseBody);
});
});
request.on('error', function (error) {
request.on('error', error => {
callback(error, null, null);
});
@ -289,7 +289,7 @@ LoginHandler.makeSecureRequest = function (requestOptions, requestBody, callback
// Simplifies reading a value for a cookie from request/response headers.
// RETURNS: cookie value or null if there was no such cookie
LoginHandler.getCookieFromHeaders = function (name, headers) {
LoginHandler.getCookieFromHeaders = (name, headers) => {
// Get the cookie value and decode it
var cookies = _parseCookies(headers);
var value = cookies[name];
@ -302,7 +302,7 @@ LoginHandler.getCookieFromHeaders = function (name, headers) {
// Simplifies writing a value for a cookie to response headers.
// RETURNS: nothing
LoginHandler.addCookieToHeaders = function (name, value, headers) {
LoginHandler.addCookieToHeaders = (name, value, headers) => {
// Create the cookie
var encodedValue = encodeURIComponent(value);
if (encodedValue === 'deleted') {
@ -332,14 +332,12 @@ LoginHandler.addCookieToHeaders = function (name, value, headers) {
headers._parsedCookies[name] = value;
};
LoginHandler.createOAuthRedirectState = function () {
// Per OAuth 2, this function creates a unique per-request state that the
// authentication provider will echo back as a query parameter when redirecting
// client's browser back to the Zumo server. The server will then validate the
// value of the state. This state reflecting mechanism is meant to prevent certain
// class of cross-site scripting attacks.
return Math.floor(Math.random() * 100000000000).toString(16) + (new Date()).getTime().toString(16);
};
LoginHandler.createOAuthRedirectState = () => // Per OAuth 2, this function creates a unique per-request state that the
// authentication provider will echo back as a query parameter when redirecting
// client's browser back to the Zumo server. The server will then validate the
// value of the state. This state reflecting mechanism is meant to prevent certain
// class of cross-site scripting attacks.
Math.floor(Math.random() * 100000000000).toString(16) + (new Date()).getTime().toString(16);
function _handleNewServerFlowRequest(loginContext, currentUri) {
// This function handles the first request of the two-request server authentication flow.
@ -365,13 +363,13 @@ function _handleNewServerFlowRequest(loginContext, currentUri) {
logger.trace(logSource, _.sprintf('Initializing a new server authentication flow with provider: %s.', providerName));
loginContext.loginHandler.userService.isEnabled(function (err, usersEnabled) {
loginContext.loginHandler.userService.isEnabled((err, usersEnabled) => {
// Get the location header and any others from the provider-specific login handler as
// we're going to redirect the client to the login page for the given provider.
var options = {
usersEnabled: usersEnabled
usersEnabled
};
provider.getNewServerFlowResponseHeaders(request, currentUri, function (error, headers) {
provider.getNewServerFlowResponseHeaders(request, currentUri, (error, headers) => {
if (error) {
_redirectWithError(loginContext, error);
@ -435,7 +433,7 @@ function _handleContinuedServerFlowRequest(loginContext, currentUri) {
logger.trace(logSource, _.sprintf('Continuing a server authentication flow with provider: %s.', providerName));
provider.getProviderTokenFromServerFlowRequest(request, currentUri, function (error1, providerToken) {
provider.getProviderTokenFromServerFlowRequest(request, currentUri, (error1, providerToken) => {
if (error1) {
_performFailedServerFlowAction(loginContext, error1);
@ -445,18 +443,18 @@ function _handleContinuedServerFlowRequest(loginContext, currentUri) {
logger.trace(logSource, _.sprintf('Retrieved a %s provider token in a server authentication flow.', providerName));
logger.trace(logSource, _.sprintf('Exchanging the %s provider token for a Windows Azure Mobile Services token.', providerName));
handler.userService.isEnabled(function (err, usersEnabled) {
handler.userService.isEnabled((err, usersEnabled) => {
var options = {
usersEnabled: usersEnabled
usersEnabled
};
provider.getAuthorizationDetailsFromProviderToken(request, providerToken, function (error2, authorizationDetails) {
provider.getAuthorizationDetailsFromProviderToken(request, providerToken, (error2, authorizationDetails) => {
if (error2) {
_performFailedServerFlowAction(loginContext, error2);
return;
}
handler._createResponseForLoginToken(logger, loginContext, authorizationDetails, providerName, function (err, responseBody) {
handler._createResponseForLoginToken(logger, loginContext, authorizationDetails, providerName, (err, responseBody) => {
if (err) {
_respondWithError(loginContext, err);
}
@ -475,8 +473,9 @@ function _performCompletedServerFlowAction(loginContext, oAuthResponse) {
if (!completionAction) {
// Non-browser clients complete the flow by redirecting to a "done" URL
// with the oAuthResponse encoded into the hash
var encodedResponse = encodeURIComponent(JSON.stringify(oAuthResponse)),
redirectUri = _getFinalRedirectUri(loginContext) + '#token=' + encodedResponse;
var encodedResponse = encodeURIComponent(JSON.stringify(oAuthResponse));
var redirectUri = _getFinalRedirectUri(loginContext) + '#token=' + encodedResponse;
_redirectWithSuccess(loginContext, { Location: redirectUri });
} else {
// Browser clients send back a script that posts the token to the window opener
@ -500,8 +499,8 @@ function _performFailedServerFlowAction(loginContext, error) {
}
function _returnServerFlowCompletionScriptToBrowser(loginContext, completionAction, oAuthResponse, oAuthError) {
var responseCallback = loginContext.responseCallback,
responseHeaders = {};
var responseCallback = loginContext.responseCallback;
var responseHeaders = {};
// Ensure that all 'wams' cookies get cleaned up.
_deleteAllUnsetWAMSCookies(loginContext, responseHeaders);
@ -534,10 +533,10 @@ function _returnServerFlowCompletionScriptToBrowser(loginContext, completionActi
}
function _validateSingleSignOnRedirectUri(singleSignOnRedirectUri, loginContext) {
var logger = loginContext.logger,
packageSid = _getPackageSid(loginContext),
error = null,
isValid = true;
var logger = loginContext.logger;
var packageSid = _getPackageSid(loginContext);
var error = null;
var isValid = true;
if (!packageSid) {
error = new Error(resources.packageSidMissing);
@ -565,10 +564,10 @@ function _getPackageSid(loginContext) {
}
function _validateSingleSignOnRedirectUri(singleSignOnRedirectUri, loginContext) {
var logger = loginContext.logger,
packageSid = _getPackageSid(loginContext),
error = null,
isValid = true;
var logger = loginContext.logger;
var packageSid = _getPackageSid(loginContext);
var error = null;
var isValid = true;
if (!packageSid) {
error = new Error(resources.packageSidMissing);
@ -596,7 +595,7 @@ function _getPackageSid(loginContext) {
}
LoginHandler.prototype._createResponseForLoginToken = function (logger, loginContext, authorizationDetails, providerName, callback) {
this.userService.isEnabled(function (err, usersEnabled) {
this.userService.isEnabled((err, usersEnabled) => {
if (err) {
callback(err);
return;
@ -614,7 +613,7 @@ LoginHandler.prototype._createResponseForLoginToken = function (logger, loginCon
var providerKey = UserService.getProviderKeyByName(loginContext.provider.name);
this.userService.addUserIdentity(providerKey, authorizationDetails.providerId, properties, function (err, user) {
this.userService.addUserIdentity(providerKey, authorizationDetails.providerId, properties, (err, user) => {
if (err) {
callback(err);
return;
@ -625,17 +624,17 @@ LoginHandler.prototype._createResponseForLoginToken = function (logger, loginCon
responseBody.user.id = user.id;
callback(null, responseBody);
}.bind(this));
});
}
else {
var loginToken = _createLoginTokenFromAuthorizationDetails(loginContext, authorizationDetails, usersEnabled);
var responseBody = this._createResponseBodyForLoginToken(loginContext, authorizationDetails, usersEnabled);
callback(null, responseBody);
}
}.bind(this));
});
};
LoginHandler.prototype._createResponseBodyForLoginToken = function (loginContext, authorizationDetails, usersEnabled) {
LoginHandler.prototype._createResponseBodyForLoginToken = (loginContext, authorizationDetails, usersEnabled) => {
var loginToken = _createLoginTokenFromAuthorizationDetails(loginContext, authorizationDetails, usersEnabled);
var responseBody = {
user: {
@ -704,8 +703,8 @@ function _redirectWithSuccess(loginContext, headers) {
}
function _respondWithError(loginContext, error) {
var providerName = loginContext.request.authenticationProvider,
headers = {};
var providerName = loginContext.request.authenticationProvider;
var headers = {};
if (loginContext.provider) {
// ensure that the metric is logged only after we've validated the provider
@ -724,9 +723,10 @@ function _respondWithError(loginContext, error) {
function _redirectWithError(loginContext, error) {
// Create a redirect URL that includes the error
var redirectUri = _getFinalRedirectUri(loginContext) + '#error=' + encodeURIComponent(error),
headers = { Location: redirectUri },
providerName = loginContext.request.authenticationProvider;
var redirectUri = _getFinalRedirectUri(loginContext) + '#error=' + encodeURIComponent(error);
var headers = { Location: redirectUri };
var providerName = loginContext.request.authenticationProvider;
// Ensure that all 'wams' cookies get cleaned up.
_deleteAllUnsetWAMSCookies(loginContext, headers);
@ -750,7 +750,7 @@ function _parseCookies(headers) {
var cookies = headers.cookie;
var result = {};
if (cookies) {
cookies.split(';').forEach(function (cookie) {
cookies.split(';').forEach(cookie => {
cookie = cookie.replace(/ /g, '');
var i = cookie.indexOf('=');
if (i > 0) {
@ -775,7 +775,7 @@ function _deleteAllUnsetWAMSCookies(loginContext, responseHeaders) {
// Get the cookies sent by the client
var cookies = _parseCookies(loginContext.request.headers);
Object.getOwnPropertyNames(cookies).forEach(function (cookieName) {
Object.getOwnPropertyNames(cookies).forEach(cookieName => {
// Only delete cookies that begin with 'wams_'
if (cookieName.indexOf('wams_') === 0) {
@ -844,8 +844,8 @@ function _addCompletionActionCookie(completionAction, headers) {
}
function _getCompletionActionFromQueryString(query) {
var completionType = query.completion_type,
completionOrigin = query.completion_origin;
var completionType = query.completion_type;
var completionOrigin = query.completion_origin;
if (completionType && completionOrigin) {
return { type: completionType, origin: completionOrigin };
} else {

Просмотреть файл

@ -6,8 +6,9 @@
// setting the Allow header to the specified methods. Express doesn't seem to provide any support
// like this out of the box, so this middleware must be applied to each route with an 'all' specifier.
var StatusCodes = require('../../statuscodes').StatusCodes,
_ = require('underscore');
var StatusCodes = require('../../statuscodes').StatusCodes;
var _ = require('underscore');
// pass in as parameters one or more HTTP methods
// e.g. allowHandler('get', 'post') or allowHandler(['get', 'post'])
@ -21,13 +22,11 @@ exports = module.exports = function allowHandler() {
}
// ensure the methods are all uppercase
methods = _.map(methods, function (method) {
return method.toUpperCase();
});
methods = _.map(methods, method => method.toUpperCase());
var allowHeader = { 'Allow': methods.join(', ') };
return function (req, res) {
return (req, res) => {
req._context.responseCallback(null, null, StatusCodes.METHOD_NOT_ALLOWED, allowHeader);
};
};

Просмотреть файл

@ -7,26 +7,27 @@
// level on the request. If the request is unauthenticated, this handler will
// end the request.
var StatusCodes = require('../../statuscodes').StatusCodes,
jsonWebToken = require('../../jsonwebtoken'),
User = require('../user'),
UserService = require('../../users/userservice'),
core = require('../../core'),
_ = require('underscore'),
_str = require('underscore.string');
var StatusCodes = require('../../statuscodes').StatusCodes;
var jsonWebToken = require('../../jsonwebtoken');
var User = require('../user');
var UserService = require('../../users/userservice');
var core = require('../../core');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
function authenticate(logSource, keys, userService) {
return function (req, res, next) {
var requestContext = req._context,
responseCallback = requestContext.responseCallback,
logger = requestContext.logger,
metrics = requestContext.metrics,
parsedRequest = requestContext.parsedRequest;
return (req, res, next) => {
var requestContext = req._context;
var responseCallback = requestContext.responseCallback;
var logger = requestContext.logger;
var metrics = requestContext.metrics;
var parsedRequest = requestContext.parsedRequest;
logger.trace(logSource, 'Authenticating request');
if (parsedRequest.authenticationKey) {
// determine the key to use, based on operation type
var key = (parsedRequest.operation === 'jobs') ? keys.systemKey : keys.masterKey;

Просмотреть файл

@ -6,17 +6,18 @@
// permisison of the request with the current auth level of the request. If
// the request is not authorized, it will be rejected.
var StatusCodes = require('../../statuscodes').StatusCodes,
LoginHandler = require('../loginhandler'),
core = require('../../core'),
_ = require('underscore');
var StatusCodes = require('../../statuscodes').StatusCodes;
var LoginHandler = require('../loginhandler');
var core = require('../../core');
var _ = require('underscore');
exports = module.exports = function authorize(logSource, keys) {
return function (req, res, next) {
var requestContext = req._context,
responseCallback = requestContext.responseCallback,
logger = requestContext.logger,
parsedRequest = requestContext.parsedRequest;
return (req, res, next) => {
var requestContext = req._context;
var responseCallback = requestContext.responseCallback;
var logger = requestContext.logger;
var parsedRequest = requestContext.parsedRequest;
logger.trace(logSource, 'Authorizing request');

Просмотреть файл

@ -8,7 +8,7 @@
// by the default parser.
exports = module.exports = function bodyParser() {
return function (req, res, next) {
return (req, res, next) => {
if (req._body) {
// this flag is set by the default Express body parser
// to indicate the body has already been parsed
@ -21,10 +21,10 @@ exports = module.exports = function bodyParser() {
var buf = '';
req.setEncoding('utf8');
req.on('data', function (chunk) {
req.on('data', chunk => {
buf += chunk;
});
req.on('end', function () {
req.on('end', () => {
try {
// currently this parser just takes the raw string value
// as the body

Просмотреть файл

@ -5,11 +5,12 @@
// This middleware sits at the end of the pipeline to catch errors and create a suitable response
// If the previous middleware gracefully sent the response then errorHandler won't be called.
var core = require('../../core'),
StatusCodes = require('../../statuscodes').StatusCodes,
scriptErrors = require('../../script/scripterror'),
_ = require('underscore'),
_str = require('underscore.string');
var core = require('../../core');
var StatusCodes = require('../../statuscodes').StatusCodes;
var scriptErrors = require('../../script/scripterror');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
@ -20,11 +21,11 @@ function ErrorHandler(logSource) {
}
ErrorHandler.prototype.handle = function (err, req, res, next) {
var context = req._context,
logger = context.logger,
writeResponse = context.responseCallback,
parsedRequest = context.parsedRequest;
var context = req._context;
var logger = context.logger;
var writeResponse = context.responseCallback;
var parsedRequest = context.parsedRequest;
try {
var statusCode = StatusCodes.INTERNAL_SERVER_ERROR;
if (err.timeout && err.status == 503) {

Просмотреть файл

@ -5,18 +5,19 @@
//
// This middleware ensures the request size is under the specified byte limit
var StatusCodes = require('../../statuscodes').StatusCodes,
resources = require('../../resources'),
core = require('../../core');
var StatusCodes = require('../../statuscodes').StatusCodes;
var resources = require('../../resources');
var core = require('../../core');
var logSource = 'RequestLimit';
exports = module.exports = function requestLimit(maxByteLength) {
return function (req, res, next) {
var logger = req._context.logger,
contentLength = req.headers['content-length'] ? parseInt(req.headers['content-length'], 10) : null,
responseCallback = req._context.responseCallback,
receivedByteLength = 0;
return (req, res, next) => {
var logger = req._context.logger;
var contentLength = req.headers['content-length'] ? parseInt(req.headers['content-length'], 10) : null;
var responseCallback = req._context.responseCallback;
var receivedByteLength = 0;
// limit by content-length
if (contentLength && contentLength > maxByteLength) {
@ -27,7 +28,7 @@ exports = module.exports = function requestLimit(maxByteLength) {
// final catch-all limit, in case a content-length
// hasn't been sent
req.on('data', function (chunk) {
req.on('data', chunk => {
receivedByteLength += chunk.length;
if (receivedByteLength > maxByteLength) {
logError(logger);

Просмотреть файл

@ -11,14 +11,12 @@
// The middleware should be registered very early in the pipeline.
module.exports = function () {
return function (req, res, next) {
var secure = req.secure || req.headers['x-arr-ssl'];
module.exports = () => (req, res, next) => {
var secure = req.secure || req.headers['x-arr-ssl'];
if (!secure) {
res.status(403).send('HTTPS connections are required for this service. Please update your endpoint to use the https protocol.').end();
} else {
next();
}
};
if (!secure) {
res.status(403).send('HTTPS connections are required for this service. Please update your endpoint to use the https protocol.').end();
} else {
next();
}
};

Просмотреть файл

@ -7,27 +7,25 @@
//
// The middleware should be registered early in the pipeline.
module.exports = function () {
return function (req, res, next) {
var version;
module.exports = () => (req, res, next) => {
var version;
// Find any casing of zumo-api-version in querystring
for (var param in req.query) {
if (param.toLowerCase() === 'zumo-api-version') {
version = req.query[param];
break;
}
// Find any casing of zumo-api-version in querystring
for (var param in req.query) {
if (param.toLowerCase() === 'zumo-api-version') {
version = req.query[param];
break;
}
}
// Fall back to header if not present in querystring
if (!version) {
version = req.headers['zumo-api-version'];
}
// Fall back to header if not present in querystring
if (!version) {
version = req.headers['zumo-api-version'];
}
if (version) {
res.status(400).send('This version (1.0.0) of the server does not support the use of the zumo-api-version in the request. For more information and supported clients see: http://go.microsoft.com/fwlink/?LinkID=690568#1.0.0').end();
} else {
next();
}
};
if (version) {
res.status(400).send('This version (1.0.0) of the server does not support the use of the zumo-api-version in the request. For more information and supported clients see: http://go.microsoft.com/fwlink/?LinkID=690568#1.0.0').end();
} else {
next();
}
};

Просмотреть файл

@ -4,12 +4,12 @@
//
// This module provides functions to parse a request into a request object used by the runtime.
(function (global) {
((global => {
require('../query/queryparser');
var _ = require('underscore'),
_str = require('underscore.string'),
core = require('../core');
var _ = require('underscore');
var _str = require('underscore.string');
var core = require('../core');
_.mixin(_str.exports());
@ -181,5 +181,4 @@
Request = global;
Request.parse = parse;
Request.validateQuery = validateQuery;
})(typeof exports === "undefined" ? (this.Request = {}) : exports);
}))(typeof exports === "undefined" ? (this.Request = {}) : exports);

Просмотреть файл

@ -5,44 +5,45 @@
// This module is responsible for processing HTTP requests end to end. Delegates to specific
// handler modules to process different request types (e.g. tables, scheduler, api, login, etc.)
var core = require('../core'),
TableHandler = require('./tablehandler'),
LoginHandler = require('./loginhandler'),
SchedulerHandler = require('./schedulerhandler'),
StatusHandler = require('./statushandler'),
DiagnosticsHandler = require('./diagnosticshandler'),
CrossDomainHandler = require('./html/crossdomainhandler'),
ApiBuilder = require('../script/apibuilder'),
util = require('util'),
StatusCodes = require('../statuscodes').StatusCodes,
fileHelpers = require('../filehelpers'),
CorsHelper = require('./html/corshelper'),
UserService = require('../users/userservice'),
_ = require('underscore'),
_str = require('underscore.string'),
Logger = require('../logger'),
uuid = require('request/uuid'),
resources = require('../resources'),
express = require('express'),
allowHandler = require('./middleware/allowhandler'),
bodyParser = require('./middleware/bodyparser'),
requestLimit = require('./middleware/requestlimit'),
errorHandler = require('./middleware/errorhandler'),
authenticate = require('./middleware/authenticate'),
authorize = require('./middleware/authorize'),
versionCheck = require('./middleware/versioncheck'),
requireHttpsMiddleware = require('./middleware/requirehttps'),
EtagHelper = require('./etaghelper.js'),
ErrorHelper = require('./errorhelper.js'),
Request = require('./request.js');
var core = require('../core');
var TableHandler = require('./tablehandler');
var LoginHandler = require('./loginhandler');
var SchedulerHandler = require('./schedulerhandler');
var StatusHandler = require('./statushandler');
var DiagnosticsHandler = require('./diagnosticshandler');
var CrossDomainHandler = require('./html/crossdomainhandler');
var ApiBuilder = require('../script/apibuilder');
var util = require('util');
var StatusCodes = require('../statuscodes').StatusCodes;
var fileHelpers = require('../filehelpers');
var CorsHelper = require('./html/corshelper');
var UserService = require('../users/userservice');
var _ = require('underscore');
var _str = require('underscore.string');
var Logger = require('../logger');
var uuid = require('request/uuid');
var resources = require('../resources');
var express = require('express');
var allowHandler = require('./middleware/allowhandler');
var bodyParser = require('./middleware/bodyparser');
var requestLimit = require('./middleware/requestlimit');
var errorHandler = require('./middleware/errorhandler');
var authenticate = require('./middleware/authenticate');
var authorize = require('./middleware/authorize');
var versionCheck = require('./middleware/versioncheck');
var requireHttpsMiddleware = require('./middleware/requirehttps');
var EtagHelper = require('./etaghelper.js');
var ErrorHelper = require('./errorhelper.js');
var Request = require('./request.js');
_.mixin(_str.exports());
exports = module.exports = RequestHandler;
var logSource = 'RequestHandler',
version = null,
npmPackageVersion = require('../../package.json').version;
var logSource = 'RequestHandler';
var version = null;
var npmPackageVersion = require('../../package.json').version;
function RequestHandler(configPath, masterKey, systemKey, appName, authenticationCredentials, crossDomainWhitelist, applicationKey, runtimeVersion, requestTimeout, storage, scriptManager, logger, metrics, logLevel, logServiceURL, logServiceToken, maxRequestBodySize, newRelicAdapter, userService, pushAdapter, domainSuffix, requireHttps, skipVersionCheck) {
this.requestTimeout = requestTimeout || 30 * 1000;
@ -57,7 +58,7 @@ function RequestHandler(configPath, masterKey, systemKey, appName, authenticatio
this.maxRequestBodySize = maxRequestBodySize;
this.newRelicAdapter = newRelicAdapter;
this.userService = userService || UserService.nullService;
this.corsHelper = new CorsHelper({ crossDomainWhitelist: crossDomainWhitelist });
this.corsHelper = new CorsHelper({ crossDomainWhitelist });
this.domainSuffix = typeof domainSuffix != "undefined" ? domainSuffix : null;
this.requireHttps = typeof(requireHttps) === 'string' && requireHttps.toLowerCase() === 'true';
this.skipVersionCheck = skipVersionCheck;
@ -73,9 +74,9 @@ function RequestHandler(configPath, masterKey, systemKey, appName, authenticatio
this.pushAdapter = pushAdapter;
this.keys = {
masterKey: masterKey,
applicationKey: applicationKey,
systemKey: systemKey
masterKey,
applicationKey,
systemKey
};
}
@ -107,9 +108,9 @@ RequestHandler.prototype.initialize = function (app, extensionManager, done) {
this.apiBuilder = new ApiBuilder(app, apiMiddleware, this.scriptManager, this.logger, this.metrics);
core.async.parallel([
function (done) { self.scriptManager.initialize(done); },
function (done) { self.apiBuilder.build(done); },
function (done) { self.loginHandler.initialize(done); }
done => { self.scriptManager.initialize(done); },
done => { self.apiBuilder.build(done); },
done => { self.loginHandler.initialize(done); }
], done);
};
@ -238,8 +239,8 @@ RequestHandler.prototype._configureRoutes = function (app, sharedMiddleware) {
// perform request initialization common to all handlers
RequestHandler.prototype._beginRequest = function (req, res, next) {
var requestLogger = this._createRequestLogger(),
self = this;
var requestLogger = this._createRequestLogger();
var self = this;
// Create the requestContext and start a request latency timer
req._context = {
@ -289,7 +290,7 @@ RequestHandler.prototype._beginRequest = function (req, res, next) {
RequestHandler.prototype._wrapResponse = function (req, res, logger) {
var self = this;
res.end = _.wrap(res.end, function (oldEnd, data, encoding) {
res.end = _.wrap(res.end, (oldEnd, data, encoding) => {
if (!res.completed) {
// a response was produced, so clear the timeout,
// if a timeout has been applied to the request.
@ -316,9 +317,9 @@ RequestHandler.prototype._createRequestLogger = function () {
};
function validateQuery(req, res, next) {
var requestContext = req._context,
logger = requestContext.logger,
parsedRequest = requestContext.parsedRequest;
var requestContext = req._context;
var logger = requestContext.logger;
var parsedRequest = requestContext.parsedRequest;
try {
Request.validateQuery(parsedRequest);
@ -334,7 +335,7 @@ function validateQuery(req, res, next) {
// Apply this middleware to a route to configure the required authorization
// level for that route. Must be applied BEFORE the authorize middleware.
function requireAuthorization(requiredLevel) {
return function (req, res, next) {
return (req, res, next) => {
// set the required permission, which will be validated by the
// authorize middleware
req._context.parsedRequest.requiredPermission = requiredLevel;
@ -348,10 +349,10 @@ RequestHandler.prototype._setPushPermission = function (req, res, next) {
};
RequestHandler.prototype._validateTable = function (req, res, next, tableName) {
var requestContext = req._context,
responseCallback = requestContext.responseCallback,
parsedRequest = requestContext.parsedRequest,
dataModel = this.scriptManager.getDataModel();
var requestContext = req._context;
var responseCallback = requestContext.responseCallback;
var parsedRequest = requestContext.parsedRequest;
var dataModel = this.scriptManager.getDataModel();
// verify that the table exists
var table = dataModel.getTable(tableName);
@ -375,9 +376,9 @@ RequestHandler.prototype._validateTable = function (req, res, next, tableName) {
};
RequestHandler.prototype._validateJob = function (req, res, next, jobName) {
var requestContext = req._context,
responseCallback = requestContext.responseCallback,
dataModel = this.scriptManager.getDataModel();
var requestContext = req._context;
var responseCallback = requestContext.responseCallback;
var dataModel = this.scriptManager.getDataModel();
// verify that job exists
var job = dataModel.getJob(jobName);
@ -394,7 +395,7 @@ RequestHandler.prototype._validateJob = function (req, res, next, jobName) {
next();
};
RequestHandler.prototype._setRequestId = function (req, res, next, id) {
RequestHandler.prototype._setRequestId = (req, res, next, id) => {
req._context.parsedRequest.id = id;
next();
};
@ -406,9 +407,9 @@ RequestHandler.prototype.redirectConsole = function () {
// simplify the interface of logUser by defaulting the table, operation, etc.
var logUser = function (logType) {
var logArgs = Array.prototype.slice.call(arguments, 1),
message = util.format.apply(null, logArgs),
source = core.getUserScriptSource();
var logArgs = Array.prototype.slice.call(arguments, 1);
var message = util.format.apply(null, logArgs);
var source = core.getUserScriptSource();
if (!source) {
// If not coming from user source, log directly to stdout.
@ -430,8 +431,8 @@ RequestHandler.prototype.redirectConsole = function () {
};
function parseRequest(req, res, next) {
var requestContext = req._context,
logger = requestContext.logger;
var requestContext = req._context;
var logger = requestContext.logger;
var parsedRequest;
try {
@ -468,8 +469,9 @@ function bindHandler(handler) {
RequestHandler.prototype._traceRequest = function (req, res, next) {
// we need to be careful not to log any sensitive request data
// (e.g. actual body contents, authentication key values, etc.)
var parsedRequest = req._context.parsedRequest,
logger = req._context.logger;
var parsedRequest = req._context.parsedRequest;
var logger = req._context.logger;
var traceData = {
verb: parsedRequest.verb,

Просмотреть файл

@ -4,10 +4,11 @@
//
// This module is responsible for scheduler job execution requests
var DataPipeline = require('./datapipeline'),
Storage = require('../storage/storage'),
core = require('../core'),
StatusCodes = require('../statuscodes').StatusCodes;
var DataPipeline = require('./datapipeline');
var Storage = require('../storage/storage');
var core = require('../core');
var StatusCodes = require('../statuscodes').StatusCodes;
exports = module.exports = SchedulerHandler;
@ -21,9 +22,9 @@ function SchedulerHandler(scriptManager, masterKey, appName, metrics) {
}
SchedulerHandler.prototype.handle = function (req, res) {
var logger = req._context.logger,
responseCallback = req._context.responseCallback,
request = req._context.parsedRequest;
var logger = req._context.logger;
var responseCallback = req._context.responseCallback;
var request = req._context.parsedRequest;
request.job = req.params.job;

Просмотреть файл

@ -15,9 +15,9 @@ var logSource = 'StatusHandler';
function StatusHandler() {
}
StatusHandler.prototype.handle = function (req, res) {
var logger = req._context.logger,
responseCallback = req._context.responseCallback;
StatusHandler.prototype.handle = (req, res) => {
var logger = req._context.logger;
var responseCallback = req._context.responseCallback;
logger.trace(logSource, 'Processing request');

Просмотреть файл

@ -4,15 +4,16 @@
//
// This module is responsible for handling table requests end to end (query/insert/update/delete).
var DataPipeline = require('./datapipeline'),
core = require('../core'),
StatusCodes = require('../statuscodes').StatusCodes,
resource = require('../resources'),
ETagHelper = require('./etaghelper'),
_ = require('underscore'),
_str = require('underscore.string');
var DataPipeline = require('./datapipeline');
_.mixin(_str.exports());
var core = require('../core');
var StatusCodes = require('../statuscodes').StatusCodes;
var resource = require('../resources');
var ETagHelper = require('./etaghelper');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
exports = module.exports = TableHandler;
@ -25,10 +26,10 @@ function TableHandler(storage, scriptManager, metrics) {
}
TableHandler.prototype.handle = function (req, res) {
var logger = req._context.logger,
responseCallback = req._context.responseCallback,
request = req._context.parsedRequest,
self = this;
var logger = req._context.logger;
var responseCallback = req._context.responseCallback;
var request = req._context.parsedRequest;
var self = this;
request.table = req.params.table;
request.id = req.params.id;
@ -39,7 +40,7 @@ TableHandler.prototype.handle = function (req, res) {
var dataPipeline = this._createDataPipeline(request, logger);
this.storage.getTableMetadata(request.table, logger, function (err, tableMetadata) {
this.storage.getTableMetadata(request.table, logger, (err, tableMetadata) => {
if (err) {
responseCallback(err);
@ -72,7 +73,7 @@ TableHandler.prototype.handle = function (req, res) {
});
};
TableHandler.prototype._handleRead = function (request, dataPipeline, responseCallback) {
TableHandler.prototype._handleRead = (request, dataPipeline, responseCallback) => {
if (request.id !== undefined) {
request.query.id = request.id;
}
@ -80,7 +81,7 @@ TableHandler.prototype._handleRead = function (request, dataPipeline, responseCa
dataPipeline.read(request.query, responseCallback);
};
TableHandler.prototype._handleUndelete = function (request, tableMetadata, dataPipeline, responseCallback) {
TableHandler.prototype._handleUndelete = (request, tableMetadata, dataPipeline, responseCallback) => {
if (!tableMetadata.supportsSoftDelete) {
responseCallback(new core.MobileServiceError(resource.undeleteNotSupported, core.ErrorCodes.BadInput));
return;
@ -105,7 +106,7 @@ TableHandler.prototype._handleUndelete = function (request, tableMetadata, dataP
dataPipeline.update(item, responseCallback);
};
TableHandler.prototype._handleInsert = function (request, tableMetadata, dataPipeline, responseCallback) {
TableHandler.prototype._handleInsert = (request, tableMetadata, dataPipeline, responseCallback) => {
if (request.id !== undefined) {
responseCallback(new core.MobileServiceError(resource.idInUrlNotAllowedOnInsert, core.ErrorCodes.BadInput));
return;
@ -128,7 +129,7 @@ TableHandler.prototype._handleInsert = function (request, tableMetadata, dataPip
return;
}
responseCallback = _.wrap(responseCallback, function (oldCallback, error, result, statusCode) {
responseCallback = _.wrap(responseCallback, (oldCallback, error, result, statusCode) => {
var additionalHeaders = null;
if (!error && request.body && request.body.id) {
// if the insert was successful, add the Location header
@ -141,7 +142,7 @@ TableHandler.prototype._handleInsert = function (request, tableMetadata, dataPip
dataPipeline.insert(request.body, responseCallback);
};
TableHandler.prototype._handleUpdate = function (request, tableMetadata, dataPipeline, responseCallback) {
TableHandler.prototype._handleUpdate = (request, tableMetadata, dataPipeline, responseCallback) => {
if (!request.id) {
responseCallback(new core.MobileServiceError(resource.idValueRequiredOnUpdate, core.ErrorCodes.BadInput));
return;
@ -178,7 +179,7 @@ TableHandler.prototype._handleUpdate = function (request, tableMetadata, dataPip
dataPipeline.update(item, responseCallback);
};
TableHandler.prototype._handleDelete = function (request, tableMetadata, dataPipeline, responseCallback) {
TableHandler.prototype._handleDelete = (request, tableMetadata, dataPipeline, responseCallback) => {
if (!request.id) {
responseCallback(new core.MobileServiceError(resource.idValueRequiredOnDelete, core.ErrorCodes.BadInput));
return;
@ -257,9 +258,7 @@ function isStringIdValid(request, responseCallback) {
function isIdFieldValid(request, responseCallback) {
// If an object has any id casing other than 'id', return an error.
if (['ID', 'Id', 'iD'].some(function (idFormat) {
return request.body.hasOwnProperty(idFormat);
})) {
if (['ID', 'Id', 'iD'].some(idFormat => request.body.hasOwnProperty(idFormat))) {
responseCallback(new core.MobileServiceError(resource.idPropertyCaseMismatch, core.ErrorCodes.BadInput));
return false;
}

Просмотреть файл

@ -4,10 +4,11 @@
//
// This is a module that has logic related to creating user object and getting its identities
var _ = require('underscore'),
_str = require('underscore.string'),
ZumoCallback = require('../script/zumocallback'),
UserService = require('../users/userservice');
var _ = require('underscore');
var _str = require('underscore.string');
var ZumoCallback = require('../script/zumocallback');
var UserService = require('../users/userservice');
_.mixin(_str.exports());
@ -22,7 +23,7 @@ var logSource = 'User';
// metrics: {}
// logger: {}
// }
exports.create = function (requestContext, keys, userService) {
exports.create = (requestContext, keys, userService) => {
userService = userService || UserService.nullService;
var request = requestContext.parsedRequest;
@ -53,9 +54,9 @@ function GetIdentitiesHelper(requestContext, token, userService) {
}
GetIdentitiesHelper.prototype.invoke = function (callbackOrOptions) {
var script = this.requestContext.script || '',
metrics = this.requestContext.metrics,
logger = this.requestContext.logger;
var script = this.requestContext.script || '';
var metrics = this.requestContext.metrics;
var logger = this.requestContext.logger;
if (!callbackOrOptions) {
metrics.event('api.user.getIdentities');
@ -67,10 +68,10 @@ GetIdentitiesHelper.prototype.invoke = function (callbackOrOptions) {
};
GetIdentitiesHelper.prototype._getIdentitiesAsync = function (script, callbackOrOptions) {
var metrics = this.requestContext.metrics,
logger = this.requestContext.logger,
self = this,
callback;
var metrics = this.requestContext.metrics;
var logger = this.requestContext.logger;
var self = this;
var callback;
if (_.isFunction(callbackOrOptions)) {
metrics.event('api.user.getIdentitiesAync');
@ -82,7 +83,7 @@ GetIdentitiesHelper.prototype._getIdentitiesAsync = function (script, callbackOr
callback = ZumoCallback.create(this.requestContext, logSource, script, 'user', 'getIdentities', callbackOrOptions);
}
this.userService.isEnabled(function (err, isEnabled) {
this.userService.isEnabled((err, isEnabled) => {
if (err) {
callback(err);
return;

Просмотреть файл

@ -2,7 +2,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
(function (exports) {
((exports => {
// storage messages
exports.colNotInSchema = "Could not save item because it contains a column that is not in the table schema.";
@ -47,4 +47,4 @@
exports.newRelicError = 'A New Relic license key was found but the module could not be loaded. For more information on how to enable New Relic see http://go.microsoft.com/fwlink/?LinkID=327542';
exports.itemNotFound = "An item with id '%s' does not exist.";
})(typeof exports === 'undefined' ? (this.resource = {}) : exports);
}))(typeof exports === 'undefined' ? (this.resource = {}) : exports);

Просмотреть файл

@ -4,15 +4,16 @@
//
// This module is responsible for loading and exposing custom apis on the app
var StatusCodes = require('../statuscodes').StatusCodes,
path = require('path'),
core = require('../core'),
Metadata = require('./metadata'),
scriptErrors = require('./scripterror'),
ScriptLoader = require('./scriptloader'),
_ = require('underscore'),
_str = require('underscore.string'),
allowHandler = require('../request/middleware/allowhandler');
var StatusCodes = require('../statuscodes').StatusCodes;
var path = require('path');
var core = require('../core');
var Metadata = require('./metadata');
var scriptErrors = require('./scripterror');
var ScriptLoader = require('./scriptloader');
var _ = require('underscore');
var _str = require('underscore.string');
var allowHandler = require('../request/middleware/allowhandler');
_.mixin(_str.exports());
@ -65,8 +66,9 @@ ApiBuilder.prototype._handleLoadError = function (err, scriptInfo) {
// callback for file load events from script loader
ApiBuilder.prototype._handleFileLoad = function (supportedMethods, scriptInfo) {
// get or create the api entry for this file
var api = this.apis[scriptInfo.name] || createApi(scriptInfo),
isScript = isScriptFile(scriptInfo.scriptFileName);
var api = this.apis[scriptInfo.name] || createApi(scriptInfo);
var isScript = isScriptFile(scriptInfo.scriptFileName);
if (isScript) {
this._loadApi(supportedMethods, api);
@ -82,15 +84,15 @@ ApiBuilder.prototype._handleFileLoad = function (supportedMethods, scriptInfo) {
};
ApiBuilder.prototype._loadApi = function (supportedMethods, api) {
var scriptPath = api.scriptPath,
baseRoute = '/api/' + api.name,
scriptSource = '/api/' + api.scriptFileName,
self = this;
var scriptPath = api.scriptPath;
var baseRoute = '/api/' + api.name;
var scriptSource = '/api/' + api.scriptFileName;
var self = this;
api.baseRoute = baseRoute;
api.reset(); // clear any existing routes
this.apis[api.name] = api;
// clone the base middleware to and add additional to define
// the common set of middleware for this api
var middleware = self.middleware.slice(0) || [];
@ -106,10 +108,10 @@ ApiBuilder.prototype._loadApi = function (supportedMethods, api) {
api.addRoute(route, method);
handler = _.wrap(handler, function (originalHandler, req, res) {
var logger = req._context.logger,
metrics = req._context.metrics,
responseCallback = req._context.responseCallback;
handler = _.wrap(handler, (originalHandler, req, res) => {
var logger = req._context.logger;
var metrics = req._context.metrics;
var responseCallback = req._context.responseCallback;
logger.trace(logSource, 'Invoking user handler');
metrics.event(_.sprintf('api.custom.%s', method));
@ -136,8 +138,8 @@ ApiBuilder.prototype._loadApi = function (supportedMethods, api) {
// define an api wrapper to intercept route registration calls, etc.
var apiWrapper = {};
_.each(supportedMethods, function (method) {
apiWrapper[method] = function (route, handler) {
_.each(supportedMethods, method => {
apiWrapper[method] = (route, handler) => {
if (!_.startsWith(route, '/')) {
route = '/' + route;
}
@ -160,7 +162,7 @@ ApiBuilder.prototype._loadApi = function (supportedMethods, api) {
// since we don't know what routes the register function would have registered
// we configure the api to always error on execution on a public 'all' route
api.error = "'register' method of the api failed.";
addRoute('all', baseRoute, middleware, function (req, res) { });
addRoute('all', baseRoute, middleware, (req, res) => { });
}
}
@ -168,7 +170,7 @@ ApiBuilder.prototype._loadApi = function (supportedMethods, api) {
// next load any implicit routes
// "prescriptive" form of a custom api, with exported functions
// for each http verb
_.each(supportedMethods, function (method) {
_.each(supportedMethods, method => {
var handler = apiModule[method];
if (handler) {
addRoute(method, baseRoute, middleware, handler);
@ -178,7 +180,7 @@ ApiBuilder.prototype._loadApi = function (supportedMethods, api) {
// finally, add an allow handler that will match on all http
// methods, to send back proper 405 Allow responses
_.each(api.routes, function (route, path) {
_.each(api.routes, (route, path) => {
self.app.all(path, allowHandler(route.methods));
});
};
@ -191,9 +193,9 @@ function apiLoadErrorHandler(req, res) {
// middleware used to set the required permission on the request,
// based on the permission configured for the api route
function requirePermission(api, req, res, next) {
var requiredPermission = 'admin',
logger = req._context.logger,
parsedRequest = req._context.parsedRequest;
var requiredPermission = 'admin';
var logger = req._context.logger;
var parsedRequest = req._context.parsedRequest;
// if we faild to register the apis or load the metadata file, we don't know what permissions it would have
// since we're going to return an error from the api, it is safe to make it public
@ -227,19 +229,19 @@ function requirePermission(api, req, res, next) {
// middleware used to set up required state on the request before
// calling into user code
function prepareRequest(api, scriptManager, req, res, next) {
var logger = req._context.logger,
responseCallback = req._context.responseCallback,
source = '/api/' + api.scriptFileName;
var logger = req._context.logger;
var responseCallback = req._context.responseCallback;
var source = '/api/' + api.scriptFileName;
// set the executing script on request context
req._context.script = source;
// add service to the request
req.service = scriptManager.buildScriptService(source, logger, { responseCallback: responseCallback });
req.service = scriptManager.buildScriptService(source, logger, { responseCallback });
// to keep the script apis consistent, we define a 'respond'
// which delegates to send
req.respond = function (statusCode, body) {
req.respond = (statusCode, body) => {
res.send(statusCode, body);
};

Просмотреть файл

@ -4,20 +4,21 @@
//
// This module is responsible for loading and running extension scripts
var path = require('path'),
fs = require('fs'),
core = require('../core'),
_ = require('underscore'),
_str = require('underscore.string');
var path = require('path');
var fs = require('fs');
var core = require('../core');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
exports = module.exports = ExtensionManager;
var logSource = 'ExtensionManager',
extensionsDirectory = 'extensions',
startupFileName = 'startup.js',
pushFileName = 'push.js';
var logSource = 'ExtensionManager';
var extensionsDirectory = 'extensions';
var startupFileName = 'startup.js';
var pushFileName = 'push.js';
ExtensionManager.pushMetadataFileName = 'push.json';
@ -43,7 +44,7 @@ ExtensionManager.prototype.initialize = function (done) {
var options = {
load: this._onScriptLoad.bind(this),
error: function (err) {
error(err) {
self.logger.logUser(logSource, LogType.Error, err.toString());
done();
}
@ -56,7 +57,7 @@ ExtensionManager.prototype.runPushRegistrationScript = function (registration, u
var options = {
swallowError: false,
args: registration,
extraContext: { user: user }
extraContext: { user }
};
this.runExtensionScript(pushFileName, 'register', options, done);
@ -121,8 +122,8 @@ ExtensionManager.prototype._getExtension = function (name) {
};
ExtensionManager.prototype._callExtension = function (name, module, method, options, context, done) {
var self = this,
doneCalled = false;
var self = this;
var doneCalled = false;
var fn = module[method];
if (!core.isFunction(fn)) {
@ -148,7 +149,7 @@ ExtensionManager.prototype._callExtension = function (name, module, method, opti
extensionArgs.push(context);
if (options && _.isNumber(options.scriptTimeout)) {
var callbackWrapper = function (error) {
var callbackWrapper = error => {
if (!doneCalled) {
doneCalled = true;
if (options && !options.swallowError) {
@ -164,7 +165,7 @@ ExtensionManager.prototype._callExtension = function (name, module, method, opti
extensionArgs.push(done);
}
fn.apply(null, extensionArgs);
fn(...extensionArgs);
} catch (e) {
this.logger.logUser(logSource, LogType.Error, _.sprintf('Failed to execute \'%s\' of %s due to error: %s', method, name, e.toString()));
if (options && !options.swallowError) {
@ -174,7 +175,7 @@ ExtensionManager.prototype._callExtension = function (name, module, method, opti
if (options && _.isNumber(options.scriptTimeout)) {
// if module fails to call 'done' with in time limit then we call it ourself to resume execution
setTimeout(function () {
setTimeout(() => {
if (!doneCalled) {
doneCalled = true;
var errorMessage = _.sprintf('\'%s\' of \'%s\' failed to call \'done\' method with in %d ms', method, name, options.scriptTimeout);

Просмотреть файл

@ -4,16 +4,17 @@
//
// Encapsulates script metadata
var core = require('../core'),
_ = require('underscore'),
_str = require('underscore.string');
var core = require('../core');
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
exports = module.exports = Metadata;
var supportedHttpMethods = ['get', 'put', 'post', 'patch', 'delete'],
tableOperations = ['read', 'insert', 'update', 'delete'];
var supportedHttpMethods = ['get', 'put', 'post', 'patch', 'delete'];
var tableOperations = ['read', 'insert', 'update', 'delete'];
function Metadata(metadata, filename) {
this.metadata = metadata;
@ -44,15 +45,13 @@ Metadata.prototype.getRouteMetadata = function (route, method) {
};
Metadata.prototype._matchRoute = function (route) {
var normalizedRoute = _.trim(route, '/'),
routeMetadata = null;
var normalizedRoute = _.trim(route, '/');
var routeMetadata = null;
// Search for a route match by normalizing both values
// by removing any leading/trailing slashes. E.g., we want
// match /a/b with a/b or a/b/, etc.
var matchedRoute = _.chain(this.metadata.routes).keys().find(function (routeKey) {
return normalizedRoute == _.trim(routeKey, '/');
}).value();
var matchedRoute = _.chain(this.metadata.routes).keys().find(routeKey => normalizedRoute == _.trim(routeKey, '/')).value();
if (matchedRoute) {
routeMetadata = this.metadata.routes[matchedRoute];
@ -66,15 +65,15 @@ Metadata.prototype._matchRoute = function (route) {
};
function validateMetadata(metadata, fileName) {
var validMetadataProperties = ['permission'],
validPermissions = ['application', 'user', 'authenticated', 'admin', 'public'];
var validMetadataProperties = ['permission'];
var validPermissions = ['application', 'user', 'authenticated', 'admin', 'public'];
function throwMetadataError(reason) {
throw new Error(_.sprintf("Invalid metadata file '%s': %s", fileName, reason));
}
function validateRouteMetadata(route, routeMetadata) {
_.each(routeMetadata, function (value, key) {
_.each(routeMetadata, (value, key) => {
if (validMetadataProperties.indexOf(key) < 0) {
throwMetadataError(_.sprintf("Invalid route metadata for route '%s'. '%s' is not a valid metadata property.", route, key));
}
@ -94,7 +93,7 @@ function validateMetadata(metadata, fileName) {
throwMetadataError("'routes' must be an object, mapping routes to route metadata.");
}
_.each(routes, function (routeMetadata, route) {
_.each(routes, (routeMetadata, route) => {
// validate the route
if (!route) {
throwMetadataError(_.sprintf("Invalid route path '%s'", route));
@ -104,7 +103,7 @@ function validateMetadata(metadata, fileName) {
}
if (isMethodMap(routeMetadata)) {
_.each(routeMetadata, function (routeMetadataMap, methodOrOp) {
_.each(routeMetadata, (routeMetadataMap, methodOrOp) => {
if (!isHttpMethodOrTableOperation(methodOrOp)) {
throwMetadataError(_.sprintf("Invalid route metadata for route '%s'. '%s' is not a supported http method or table operation.", route, methodOrOp));
}

Просмотреть файл

@ -22,7 +22,5 @@ ScriptCache.prototype.get = function (key) {
return this.cache[key.toLowerCase()];
};
ScriptCache.prototype.getKey = function (scriptType, filename) {
// important to retain the filename extension to ensure uniqueness
return scriptType + '-' + filename;
};
ScriptCache.prototype.getKey = (scriptType, filename) => // important to retain the filename extension to ensure uniqueness
scriptType + '-' + filename;

Просмотреть файл

@ -2,13 +2,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
var _ = require('underscore'),
_str = require('underscore.string'),
core = require('../core');
var _ = require('underscore');
var _str = require('underscore.string');
var core = require('../core');
_.mixin(_str.exports());
exports.handleScriptError = function (error, source, logger, responseCallback, message) {
exports.handleScriptError = (error, source, logger, responseCallback, message) => {
if (error instanceof core.MobileServiceError && !error.loggedToUser && (error.code === core.ErrorCodes.ScriptError || error.code === undefined)) {
if (!message) {
message = _.sprintf("Error in script '%s'.", source);

Просмотреть файл

@ -4,22 +4,23 @@
//
// Wraps a script cache and provides funcionality for loading scripts into the cache
var fs = require('fs'),
path = require('path'),
ScriptCache = require('./scriptcache'),
StatusCodes = require('../statuscodes'),
fileHelpers = require('../filehelpers'),
_ = require('underscore'),
_str = require('underscore.string'),
core = require('../core'),
Metadata = require('./metadata');
var fs = require('fs');
var path = require('path');
var ScriptCache = require('./scriptcache');
var StatusCodes = require('../statuscodes');
var fileHelpers = require('../filehelpers');
var _ = require('underscore');
var _str = require('underscore.string');
var core = require('../core');
var Metadata = require('./metadata');
_.mixin(_str.exports());
exports = module.exports = ScriptLoader;
var logSource = 'ScriptLoader',
dataModelFileName = 'datamodel.json';
var logSource = 'ScriptLoader';
var dataModelFileName = 'datamodel.json';
function ScriptLoader(configPath, cache, logger) {
this.configPath = configPath;
@ -35,13 +36,13 @@ ScriptLoader.prototype.load = function (done) {
// only after we've loaded all directories do we complete
core.async.series([
function (done) { self._loadDataModel(done); },
function (done) {
done => { self._loadDataModel(done); },
done => {
core.async.parallel([
function (done) { self._loadTablesDirectory(done); },
function (done) { self._loadJobsDirectory(done); },
function (done) { self.loadScriptDirectory('shared', null, done); }
], function () {
done => { self._loadTablesDirectory(done); },
done => { self._loadJobsDirectory(done); },
done => { self.loadScriptDirectory('shared', null, done); }
], () => {
if (done) {
done();
}
@ -67,7 +68,7 @@ ScriptLoader.prototype.loadScriptDirectory = function (scriptType, options, done
this.logger.trace(logSource, _.sprintf("Loading scripts directory '%s'", filepath));
fs.readdir(filepath, function (err, files) {
fs.readdir(filepath, (err, files) => {
if (err) {
if (options && core.isFunction(options.error)) {
options.error(err);
@ -77,9 +78,9 @@ ScriptLoader.prototype.loadScriptDirectory = function (scriptType, options, done
throw err;
}
var scriptsLoaded = 0,
numScriptsToLoad = files.length,
loadCallbackCount = 0;
var scriptsLoaded = 0;
var numScriptsToLoad = files.length;
var loadCallbackCount = 0;
function loadComplete() {
self.logger.trace(logSource, _.sprintf("%d %s script(s) loaded", scriptsLoaded, scriptType));
@ -116,7 +117,7 @@ ScriptLoader.prototype.loadScriptDirectory = function (scriptType, options, done
loadComplete();
}
else {
files.forEach(function (file) {
files.forEach(file => {
self._loadScript(scriptType, filepath, file, options, completeLoad);
});
}
@ -124,8 +125,8 @@ ScriptLoader.prototype.loadScriptDirectory = function (scriptType, options, done
};
ScriptLoader.prototype.getDataModel = function () {
var key = this.cache.getKey('config', dataModelFileName),
dataModelEntry = this.cache.get(key);
var key = this.cache.getKey('config', dataModelFileName);
var dataModelEntry = this.cache.get(key);
if (!dataModelEntry) {
// since the datamodel file is loaded on startup, and the
@ -138,9 +139,9 @@ ScriptLoader.prototype.getDataModel = function () {
};
ScriptLoader.prototype.getMetadata = function (scriptType, rootFileName) {
var metadataFileName = rootFileName + '.json',
key = this.cache.getKey(scriptType, metadataFileName),
metadataEntry = this.cache.get(key);
var metadataFileName = rootFileName + '.json';
var key = this.cache.getKey(scriptType, metadataFileName);
var metadataEntry = this.cache.get(key);
if (metadataEntry && metadataEntry.module) {
return metadataEntry.module;
@ -163,10 +164,10 @@ ScriptLoader.prototype._loadScript = function (scriptType, filepath, filename, o
this.logger.trace(logSource, _.sprintf("Loading '%s' into the script cache", filename));
var self = this,
scriptPath = path.join(filepath, filename),
scriptInfo = getScriptInfo(filepath, filename),
key = self.cache.getKey(scriptType, filename);
var self = this;
var scriptPath = path.join(filepath, filename);
var scriptInfo = getScriptInfo(filepath, filename);
var key = self.cache.getKey(scriptType, filename);
function completeLoad(err) {
if (!err) {
@ -181,7 +182,7 @@ ScriptLoader.prototype._loadScript = function (scriptType, filepath, filename, o
if (isModule(scriptType, filepath, filename)) {
// first clear any existing require cache entry then load/reload
delete require.cache[scriptPath];
fileHelpers.requireWithRetries(scriptPath, this.logger, function (err, loadedModule) {
fileHelpers.requireWithRetries(scriptPath, this.logger, (err, loadedModule) => {
if (!err) {
if (isMetadataFile(filename)) {
try {
@ -205,7 +206,7 @@ ScriptLoader.prototype._loadScript = function (scriptType, filepath, filename, o
}, this.maxFileOperationRetries, this.fileOperationRetryIntervalMS);
}
else {
fileHelpers.readFileWithRetries(scriptPath, this.logger, function (err, script) {
fileHelpers.readFileWithRetries(scriptPath, this.logger, (err, script) => {
if (!err) {
scriptInfo.script = script;
completeLoad();
@ -222,7 +223,7 @@ ScriptLoader.prototype._loadScript = function (scriptType, filepath, filename, o
}
};
ScriptLoader.logScriptLoadError = function (logger, err, scriptType, fileName) {
ScriptLoader.logScriptLoadError = (logger, err, scriptType, fileName) => {
var source = _.sprintf('/%s/%s', scriptType, fileName);
logger.logUser(source, LogType.Error, _.sprintf("Failed to load script file '%s': %s", fileName, core.sanitizeUserCallStack(err)));
};
@ -271,7 +272,7 @@ ScriptLoader.prototype._loadTablesDirectory = function (done) {
var dataModelIsValid = dataModel && dataModel.tables && Array.isArray(dataModel.tables);
this.loadScriptDirectory('table', {
load: function (scriptInfo) {
load(scriptInfo) {
if (dataModelIsValid &&
isMetadataFile(scriptInfo.scriptFileName) && // and this is a json file for a table
!dataModel.getTable(scriptInfo.name)) { // and table is not already added
@ -289,7 +290,7 @@ ScriptLoader.prototype._loadJobsDirectory = function (done) {
var dataModelIsValid = dataModel && dataModel.jobs && Array.isArray(dataModel.jobs);
this.loadScriptDirectory('scheduler', {
load: function (scriptInfo) {
load(scriptInfo) {
if (dataModelIsValid &&
path.extname(scriptInfo.scriptFileName).toLowerCase() === '.js' && // and this is a script file for a job
!dataModel.getJob(scriptInfo.name)) { // and job is not already added
@ -304,12 +305,12 @@ ScriptLoader.prototype._loadJobsDirectory = function (done) {
ScriptLoader.prototype._loadDataModel = function (done) {
var options = {
filter: function (filename) {
filter(filename) {
// in the root config dir, we only load the single
// datamodel.json file
return filename.toLowerCase() === dataModelFileName;
},
load: function (scriptInfo) {
load(scriptInfo) {
configureDataModel(scriptInfo.module);
}
};
@ -319,8 +320,8 @@ ScriptLoader.prototype._loadDataModel = function (done) {
// extend the raw dataModel module by adding helper functions
function configureDataModel(dataModel) {
var tableMap = dataModel._tableMap = {},
jobMap = dataModel._jobMap = {};
var tableMap = dataModel._tableMap = {};
var jobMap = dataModel._jobMap = {};
function nameSelector(item) {
return item.name.toLowerCase();
@ -334,13 +335,9 @@ function configureDataModel(dataModel) {
core.toLookup(dataModel.jobs, jobMap, nameSelector);
}
dataModel.getTable = function (tableName) {
return tableMap[tableName.toLowerCase()];
};
dataModel.getTable = tableName => tableMap[tableName.toLowerCase()];
dataModel.getJob = function (jobName) {
return jobMap[jobName.toLowerCase()];
};
dataModel.getJob = jobName => jobMap[jobName.toLowerCase()];
}
// returns true if the specified file is a js or json file

Просмотреть файл

@ -5,19 +5,20 @@
// This module is responsible for execution of a script including exposing capabilities to scripts via globals
// and any arguments that need to be passed to user-defined functions.
var vm = require('vm'),
core = require('../core'),
util = require('util'),
scriptErrors = require('./scripterror'),
StatusCodes = require('../statuscodes').StatusCodes,
sqlAdapter = require('./sqladapter'),
tripwire = require('tripwire'),
Table = require('./table'),
ScriptLoader = require('./scriptloader'),
path = require('path'),
_ = require('underscore'),
_str = require('underscore.string'),
config = require('mobileservice-config');
var vm = require('vm');
var core = require('../core');
var util = require('util');
var scriptErrors = require('./scripterror');
var StatusCodes = require('../statuscodes').StatusCodes;
var sqlAdapter = require('./sqladapter');
var tripwire = require('tripwire');
var Table = require('./table');
var ScriptLoader = require('./scriptloader');
var path = require('path');
var _ = require('underscore');
var _str = require('underscore.string');
var config = require('mobileservice-config');
_.mixin(_str.exports());
@ -54,8 +55,9 @@ ScriptManager.prototype.getTablePermission = function (tableName, operation) {
}
// otherwise default to the datamodel permissions
var dataModel = this.getDataModel(),
table = dataModel.getTable(tableName);
var dataModel = this.getDataModel();
var table = dataModel.getTable(tableName);
if (table && table.permissions) {
permission = table.permissions[operation];
@ -87,7 +89,7 @@ ScriptManager.prototype.hasTableScript = function (table, operation) {
return this.scriptLoader.getTableScript(table, scriptErrors.normalizeOperationName(operation)) !== null;
};
ScriptManager.prototype.getLogSourceName = function (table, operation) {
ScriptManager.prototype.getLogSourceName = (table, operation) => {
var normalizedOperationName = scriptErrors.normalizeOperationName(operation);
var source = scriptErrors.getTableScriptSource(table, normalizedOperationName);
return source;
@ -108,7 +110,7 @@ ScriptManager.prototype.runFeedbackScript = function (interval) {
var self = this;
// Set the feedback script to run every interval ms
this.feedbackInterval = setInterval(function () {
this.feedbackInterval = setInterval(() => {
self._runFeedbackScript();
}, interval);
@ -155,13 +157,13 @@ ScriptManager.prototype._run = function (script, scriptFileName, scriptDirectory
// create or less often used is defined below as create on-demand property getters.
var sandbox = {
_args: scriptArgs,
Buffer: Buffer,
setTimeout: setTimeout,
clearTimeout: clearTimeout,
setInterval: setInterval,
clearInterval: clearInterval,
Buffer,
setTimeout,
clearTimeout,
setInterval,
clearInterval,
statusCodes: StatusCodes,
process: process
process
};
sandbox.require = this._createRequire(scriptDirectoryName);
@ -181,7 +183,7 @@ ScriptManager.prototype._run = function (script, scriptFileName, scriptDirectory
// Go async before executing the user script to create a new call stack; this ensures
// we don't have to check for and re-throw tripwire exceptions.
process.nextTick(function () {
process.nextTick(() => {
try {
// first run the user script to define the operation in the context
var context = vm.createContext(sandbox);
@ -223,10 +225,10 @@ ScriptManager.prototype._createServicesForSandbox = function (services, source,
// if no response callback has been specified, use an empty function
// to ignore any responses. For example, cron and apnsfeedback scripts
// don't pass a response callback.
var responseCallback = options && options.responseCallback ? options.responseCallback : function () { };
var responseCallback = options && options.responseCallback ? options.responseCallback : () => { };
services.tables = {
getTable: function (tableName) {
getTable(tableName) {
if (!core.isString(tableName)) {
throw new core.MobileServiceError("Table name cannot be null or empty.", core.ErrorCodes.ScriptError);
}
@ -237,9 +239,7 @@ ScriptManager.prototype._createServicesForSandbox = function (services, source,
// expose the current table name programmatically in server scripts as tables.current.
if (options.currentTableName !== undefined) {
core.createLazyProperty(services.tables, 'current', function () {
return new Table(self.storage, options.currentTableName, source, logger, self.metrics, responseCallback);
});
core.createLazyProperty(services.tables, 'current', () => new Table(self.storage, options.currentTableName, source, logger, self.metrics, responseCallback));
}
services.console = this._createConsoleObject(source, logger);
@ -247,15 +247,13 @@ ScriptManager.prototype._createServicesForSandbox = function (services, source,
services.push = this.pushAdapter.createPushForScripts(source, logger, this.metrics, responseCallback);
// define lazy property for mssql wrapper
core.createLazyProperty(services, 'mssql', function () {
return sqlAdapter.create(self.storage.connection, logger, self.metrics, source, responseCallback);
});
core.createLazyProperty(services, 'mssql', () => sqlAdapter.create(self.storage.connection, logger, self.metrics, source, responseCallback));
};
ScriptManager.prototype._createRequire = function (scriptDirectoryName) {
var self = this;
return function (moduleOrPath) {
return moduleOrPath => {
var fxUtil;
try {
// we need to use fxUtil.require to simulate origin of script to be inside scripts directory

Просмотреть файл

@ -4,12 +4,13 @@
//
// State machine for orchestrating script callback execution
var core = require('../core'),
resources = require('../resources'),
scriptErrors = require('./scripterror'),
StatusCodes = require('../statuscodes').StatusCodes,
_ = require('underscore'),
_str = require('underscore.string');
var core = require('../core');
var resources = require('../resources');
var scriptErrors = require('./scripterror');
var StatusCodes = require('../statuscodes').StatusCodes;
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
@ -26,7 +27,7 @@ function ScriptState(operation, scriptArg, tableMetadata, responseCallback, logg
// Define an interceptor response callback which will allow us to
// capture and save results until respond has been called
this.responseCallback = _.wrap(responseCallback, function (oldCallback, err, results, statusCode, byUser) {
this.responseCallback = _.wrap(responseCallback, (oldCallback, err, results, statusCode, byUser) => {
if (self.responseComplete) {
if (byUser) {
var stack = new core.MobileServiceError(resources.responseAlreadySent, core.ErrorCodes.ScriptError).stack;
@ -77,7 +78,7 @@ ScriptState.prototype.execute = function (callbackOptions) {
// runtime, which we then dispatch to any callback functions
// provided by the script.
var self = this;
var scriptCallback = function (err, results) {
var scriptCallback = (err, results) => {
// Because the conflict handler can call back into context.execute()
// we need to update the saved data (from the original conflict). Also,
@ -144,7 +145,7 @@ ScriptState.prototype._executeCallbackOption = function (callback, args) {
this.delayResponse = true;
try {
callback.apply(null, args);
callback(...args);
}
catch (err) {
// If an exception occurred in the handler, we need to unblock the response,
@ -206,7 +207,7 @@ ScriptState.validateRespondParameters = function (statusOrError, body) {
ScriptState.prototype._saveResponseData = function (error, results, statusCode) {
this.responseData = {
err: error,
results: results,
results,
statusCode: statusCode || null
};
};

Просмотреть файл

@ -4,12 +4,13 @@
//
// Adapts the sqlserver module for direct use from ZUMO scripts
var core = require('../core'),
sqlserver = require('sqlserver'),
scriptErrors = require('./scripterror'),
util = require('util');
var core = require('../core');
module.exports.create = function(connectionString, logger, metrics, source, responseCallback) {
var sqlserver = require('sqlserver');
var scriptErrors = require('./scripterror');
var util = require('util');
module.exports.create = (connectionString, logger, metrics, source, responseCallback) => {
var adapter = new SqlAdapter(connectionString, logger, metrics, source, responseCallback);
return adapter.createMSSQLModule();
};
@ -29,28 +30,22 @@ SqlAdapter.prototype.createMSSQLModule = function () {
self.logger.trace(logSource, 'Creating MSSQL Module', self.getTraceDetails());
return {
open: function (callbackOptions) {
open(callbackOptions) {
var traceDetails = self.getTraceDetails("open");
var args = self.prepareArgs('open', null, callbackOptions, traceDetails, "Unable to open connection: ");
self.executeSqlServerFunction(traceDetails, function () {
return sqlserver.open(self.connectionString, args.callback);
});
self.executeSqlServerFunction(traceDetails, () => sqlserver.open(self.connectionString, args.callback));
},
query: function (query, paramsOrCallback, callbackOptions) {
query(query, paramsOrCallback, callbackOptions) {
var traceDetails = self.getTraceDetails("query", query);
var args = self.prepareArgs('query', paramsOrCallback, callbackOptions, traceDetails, "Error occurred executing query: ");
self.executeSqlServerFunction(traceDetails, function () {
return sqlserver.query(self.connectionString, query, args.params, args.callback);
});
self.executeSqlServerFunction(traceDetails, () => sqlserver.query(self.connectionString, query, args.params, args.callback));
},
queryRaw: function (query, paramsOrCallback, callbackOptions) {
queryRaw(query, paramsOrCallback, callbackOptions) {
var traceDetails = self.getTraceDetails("queryRaw", query);
var args = self.prepareArgs('queryRaw', paramsOrCallback, callbackOptions, traceDetails, "Error occurred executing query: ");
self.executeSqlServerFunction(traceDetails, function () {
return sqlserver.queryRaw(self.connectionString, query, args.params, args.callback);
});
self.executeSqlServerFunction(traceDetails, () => sqlserver.queryRaw(self.connectionString, query, args.params, args.callback));
}
};
};
@ -92,7 +87,7 @@ SqlAdapter.prototype.prepareArgs = function (method, paramsOrCallbackOptions, ca
params = [params];
}
return { params: params, callback: this.constructCallback(callbackOptions, traceDetails, errormsg) };
return { params, callback: this.constructCallback(callbackOptions, traceDetails, errormsg) };
};
SqlAdapter.prototype.executeSqlServerFunction = function (traceDetails, sqlServerFunction) {
@ -118,7 +113,7 @@ SqlAdapter.prototype.constructCallback = function (callbackOptions, traceDetails
traceDetails.error = err.toString();
if (callbackOptions && callbackOptions.error) {
self.logger.trace(logSource, 'Call into MSSQL Module failed - Calling user error callback', traceDetails);
self.executeUserCallback(traceDetails, function () {
self.executeUserCallback(traceDetails, () => {
callbackOptions.error(scriptErrors.prepareUserError(err));
});
} else {
@ -131,7 +126,7 @@ SqlAdapter.prototype.constructCallback = function (callbackOptions, traceDetails
// Skip the error argument, pass the rest.
var args = Array.prototype.slice.call(arguments).slice(1);
self.executeUserCallback(traceDetails, function () {
self.executeUserCallback(traceDetails, () => {
callbackOptions.success.apply(null, args);
});
}
@ -156,7 +151,7 @@ SqlAdapter.prototype.getTraceDetails = function (sqlFunction, query) {
// for example connection string, etc.
var traceDetails = {
source: this.source,
sqlFunction: sqlFunction
sqlFunction
};
if (query) {

Просмотреть файл

@ -6,20 +6,21 @@
// user's server side scripts. A table object is returned when a user
// runs tables.getTable passing in the name of a table.
var DataOperation = require('../request/dataoperation'),
core = require('../core'),
scriptErrors = require('./scripterror'),
Query = require('../Zumo.Node').Query,
_ = require('underscore'),
_str = require('underscore.string');
var DataOperation = require('../request/dataoperation');
_.mixin(_str.exports());
var core = require('../core');
var scriptErrors = require('./scripterror');
var Query = require('../Zumo.Node').Query;
var _ = require('underscore');
var _str = require('underscore.string');
_.mixin(_str.exports());
exports = module.exports = Table;
function Table(storage, table, source, logger, metrics, responseCallback) {
var validateItemForTableOperation = function (item, operation, mustHaveId) {
var validateItemForTableOperation = (item, operation, mustHaveId) => {
if (!core.isObject(item)) {
throw new core.MobileServiceError(_.sprintf("Operation '%s' on table '%s' failed. The parameter 'item' must be an object.", scriptErrors.normalizeOperationName(operation), table), core.ErrorCodes.ScriptError);
}
@ -28,7 +29,7 @@ function Table(storage, table, source, logger, metrics, responseCallback) {
}
};
var handleError = function (error, callback, callbackOptions) {
var handleError = (error, callback, callbackOptions) => {
if (error.loggedToUser) {
callback(error);
} else if (!callbackOptions || !callbackOptions.error) {
@ -42,11 +43,9 @@ function Table(storage, table, source, logger, metrics, responseCallback) {
}
};
this.getTableName = function () {
return table;
};
this.getTableName = () => table;
this.read = function (queryOrCallbackOptions, callbackOptions) {
this.read = (queryOrCallbackOptions, callbackOptions) => {
var query = null;
if (queryOrCallbackOptions && queryOrCallbackOptions.constructor == Query) {
@ -64,31 +63,31 @@ function Table(storage, table, source, logger, metrics, responseCallback) {
_executeTableOperation('read', table, query, callbackOptions);
};
this.insert = function (item, callbackOptions) {
this.insert = (item, callbackOptions) => {
validateItemForTableOperation(item, 'insert', false);
_executeTableOperation('insert', table, item, callbackOptions);
};
this.update = function (item, callbackOptions) {
this.update = (item, callbackOptions) => {
validateItemForTableOperation(item, 'update', true);
_executeTableOperation('update', table, item, callbackOptions);
};
this.del = function (itemOrId, callbackOptions) {
this.del = (itemOrId, callbackOptions) => {
if (core.isObject(itemOrId)) {
validateItemForTableOperation(itemOrId, 'del', true);
}
_executeTableOperation('del', table, itemOrId, callbackOptions);
};
this.lookup = function (id, callbackOptions) {
this.lookup = (id, callbackOptions) => {
if (!id) {
throw new core.MobileServiceError(_.sprintf("Operation 'lookup' on table '%s' failed. The id argument is invalid.", table), core.ErrorCodes.ScriptError);
}
var query = { id: id };
var query = { id };
var newCallbackOptions = _.clone(callbackOptions);
if (callbackOptions && callbackOptions.success) {
newCallbackOptions.success = function (results) {
newCallbackOptions.success = results => {
callbackOptions.success(results[0]);
};
}
@ -104,21 +103,21 @@ function Table(storage, table, source, logger, metrics, responseCallback) {
throw new core.MobileServiceError(_.sprintf("Operation '%s' on table '%s' failed. Arguments to table operations cannot be null or undefined.", scriptErrors.normalizeOperationName(operationName), table), core.ErrorCodes.ScriptError);
}
storage.getTableMetadata(table, logger, function (error, tableMetadata) {
storage.getTableMetadata(table, logger, (error, tableMetadata) => {
if (error) {
handleError(error, responseCallback, callbackOptions);
return;
}
var systemProperties = [],
validateOptions = {
supportsConflict: (operationName === 'update' || operationName === 'del') &&
tableMetadata.supportsConflict,
supportsIncludeDeleted: (operationName == 'read' &&
tableMetadata.supportsSoftDelete)
};
var systemProperties = [];
var validateOptions = {
supportsConflict: (operationName === 'update' || operationName === 'del') &&
tableMetadata.supportsConflict,
supportsIncludeDeleted: (operationName == 'read' &&
tableMetadata.supportsSoftDelete)
};
try {
// callback options aren't required for a table operation, but if specified, must
@ -135,12 +134,12 @@ function Table(storage, table, source, logger, metrics, responseCallback) {
}
var includeDeleted = callbackOptions && callbackOptions.includeDeleted;
// Define the callback that the data operation will call back
// when it completes. We'll receive the error/result data from the
// runtime, which we then dispatch to any callback functions
// provided by the script.
var scriptCallback = function (error, results) {
var scriptCallback = (error, results) => {
if (callbackOptions) {
if (!error) {
if (callbackOptions.success) {
@ -160,7 +159,7 @@ function Table(storage, table, source, logger, metrics, responseCallback) {
};
// Take over the existing response callback to facilitate with error handling
responseCallback = _.wrap(responseCallback, function (oldCallback, error) {
responseCallback = _.wrap(responseCallback, (oldCallback, error) => {
// If there is not an error or there is an error and callbackOptions.error exists, don't do anything because it has already been handled by the user.
if (error) {
handleError(error, oldCallback, callbackOptions);
@ -168,7 +167,7 @@ function Table(storage, table, source, logger, metrics, responseCallback) {
});
var dataOperation = new DataOperation(storage, source, logger);
var options = { systemProperties: systemProperties, includeDeleted: includeDeleted };
var options = { systemProperties, includeDeleted };
dataOperation[operationName](table, operationArg, options, responseCallback, scriptCallback);
});
}
@ -179,18 +178,18 @@ function Table(storage, table, source, logger, metrics, responseCallback) {
// forward on directly to a new Query instance.
var queryOperators = ['where', 'select', 'orderBy', 'orderByDescending', 'skip', 'take', 'includeTotalCount'];
var copyOperator = function (operator) {
Table.prototype[operator] = function () {
var copyOperator = operator => {
Table.prototype[operator] = function(...args) {
var self = this;
// Creates a new query.
var query = new Query(self.getTableName());
query.read = function (callbackOptions) {
query.read = callbackOptions => {
self.read(query, callbackOptions);
};
return query[operator].apply(query, arguments);
return query[operator](...args);
};
};
var i = 0;

Просмотреть файл

@ -4,9 +4,10 @@
//
// This module contains helper method for converting zumo style success/error option object into node style async callback.
var _ = require('underscore'),
_str = require('underscore.string'),
scriptErrors = require('./scripterror');
var _ = require('underscore');
var _str = require('underscore.string');
var scriptErrors = require('./scripterror');
_.mixin(_str.exports());
@ -30,7 +31,16 @@ ZumoCallback.moduleFailFormat = "Call into %s Module failed - %s";
// options is the options object that needs to be transformed into node style callback
// visitError is a function(error){...} that will be called before error callback is called
// visitResult is a function(result){...} that will be called before success callback is called
ZumoCallback.create = function (context, logSource, source, moduleName, method, options, visitError, visitResult) {
ZumoCallback.create = (
context,
logSource,
source,
moduleName,
method,
options,
visitError,
visitResult
) => {
if (typeof options.success !== 'undefined' && !_.isFunction(options.success)) {
context.logger.trace(logSource, _.sprintf(ZumoCallback.moduleFailFormat, moduleName, "Invalid success callback option"), ZumoCallback.getTraceDetails(source, method));
throw new core.MobileServiceError('The options.success callback, if specified, must be a function.', core.ErrorCodes.ScriptError);
@ -41,7 +51,7 @@ ZumoCallback.create = function (context, logSource, source, moduleName, method,
throw new core.MobileServiceError('The options.error callback, if specified, must be a function.', core.ErrorCodes.ScriptError);
}
return function (error, result) {
return (error, result) => {
// visit error and result
if (error && visitError) {
error = visitError(error);
@ -74,9 +84,9 @@ ZumoCallback.create = function (context, logSource, source, moduleName, method,
};
};
ZumoCallback.getTraceDetails = function (source, method, error) {
ZumoCallback.getTraceDetails = (source, method, error) => {
var details = {
source: source
source
};
if (method) {
@ -101,7 +111,17 @@ ZumoCallback.getTraceDetails = function (source, method, error) {
// - allowedMethodPrefix -- Which method prefixes will be wrapped. (Example: ['send', 'receive']
// - disallowedMethodPrefix -- Which methods that match allowed will be excluded because they have no callback (Example: ['sendNull'])
// - responseCallback, -- is the request's default responseCallback in case user does not provice a callback
ZumoCallback.wrapObject = function (objectToWrap, moduleNamePrefix, logSource, source, logger, metrics, allowedMethodPrefixes, disallowedMethodPrefixes, responseCallback) {
ZumoCallback.wrapObject = (
objectToWrap,
moduleNamePrefix,
logSource,
source,
logger,
metrics,
allowedMethodPrefixes,
disallowedMethodPrefixes,
responseCallback
) => {
var wrapperObject = {};
for (var prop in objectToWrap) {
// if this is a method that should be wrapped, wrap it
@ -165,7 +185,7 @@ function wrapperMethod(logSource, source, logger, metrics, responseCallback, mod
}
// create callback
var callback = ZumoCallback.create({ metrics: metrics, logger: logger, responseCallback: responseCallback }, logSource, source, moduleName, methodName, options);
var callback = ZumoCallback.create({ metrics, logger, responseCallback }, logSource, source, moduleName, methodName, options);
args.push(callback);
try {
@ -188,7 +208,5 @@ function shouldWrapMethod(methodName, methodObject, allowedMethodPrefixes, disal
// returns true if if the methodName starts with any string in methodPrefixList and false otherwise
function methodNamePrefixInList(methodName, methodPrefixList) {
return _.find(methodPrefixList,
function (methodPrefix) {
return _str.startsWith(methodName, methodPrefix);
});
methodPrefix => _str.startsWith(methodName, methodPrefix));
}

Просмотреть файл

@ -4,34 +4,35 @@
//
// This module creates and initializes the HTTP server
var path = require('path'),
NewRelicAdapter = require('./newrelicadapter'),
core = require('./core');
var path = require('path');
var NewRelicAdapter = require('./newrelicadapter');
var core = require('./core');
// If the customer has turned on New Relic we need to load this before anything else
// so it can hook itself into the appropriate modules
var newRelicAdapter = new NewRelicAdapter();
newRelicAdapter.initialize(resolveConfigPath(process.env, __dirname));
var RequestHandler = require('./request/requesthandler'),
FileWatcher = require('./filewatcher'),
net = require('net'),
Request = require('./request/request'),
Logger = require('./logger'),
StatusCodes = require('./statuscodes').StatusCodes,
core = require('./core'),
tripwire = require('tripwire'),
Metrics = require('./metrics'),
ScriptManager = require('./script/scriptmanager'),
ExtensionManager = require('./script/extensionmanager'),
Storage = require('./storage/Storage'),
UserService = require('./users/userservice'),
resource = require('./resources'),
_ = require('underscore'),
_str = require('underscore.string'),
express = require('express'),
PushAdapter = require('./push/pushadapter'),
util = require('util');
var RequestHandler = require('./request/requesthandler');
var FileWatcher = require('./filewatcher');
var net = require('net');
var Request = require('./request/request');
var Logger = require('./logger');
var StatusCodes = require('./statuscodes').StatusCodes;
var core = require('./core');
var tripwire = require('tripwire');
var Metrics = require('./metrics');
var ScriptManager = require('./script/scriptmanager');
var ExtensionManager = require('./script/extensionmanager');
var Storage = require('./storage/Storage');
var UserService = require('./users/userservice');
var resource = require('./resources');
var _ = require('underscore');
var _str = require('underscore.string');
var express = require('express');
var PushAdapter = require('./push/pushadapter');
var util = require('util');
_.mixin(_str.exports());
@ -74,8 +75,8 @@ Server.resolveConfigPath = resolveConfigPath;
Server.newRelicAdapter = newRelicAdapter;
Server.getAuthenticationCredentials = getAuthenticationCredentials;
Server.prototype.listen = function () {
this._server.listen.apply(this._server, arguments);
Server.prototype.listen = function(...args) {
this._server.listen(...args);
};
Server.prototype._initializeLogging = function (env, options) {
@ -85,7 +86,7 @@ Server.prototype._initializeLogging = function (env, options) {
this._globalLogger = options.logger || new Logger(LogLevel[env.MS_LogLevel]);
Logger.writer.on('error', function (err) {
Logger.writer.on('error', err => {
// we need this handler here to prevent errors
// from bubbling up to the global exception handler, which would
// cause the process to be killed
@ -98,11 +99,11 @@ Server.prototype._initializeLogging = function (env, options) {
};
Server.prototype._createAndInitializeServices = function (env) {
var maxRequestBodySize = (env.MS_MaxRequestBodySizeKB || 1024) * 1024,
authenticationCredentials = getAuthenticationCredentials(env),
crossDomainWhitelist = parseJsonSetting(env.MS_CrossDomainWhitelist, this._globalLogger),
previewFeatures = parseJsonSetting(env.MS_PreviewFeatures, this._globalLogger),
configPath = resolveConfigPath(env, __dirname);
var maxRequestBodySize = (env.MS_MaxRequestBodySizeKB || 1024) * 1024;
var authenticationCredentials = getAuthenticationCredentials(env);
var crossDomainWhitelist = parseJsonSetting(env.MS_CrossDomainWhitelist, this._globalLogger);
var previewFeatures = parseJsonSetting(env.MS_PreviewFeatures, this._globalLogger);
var configPath = resolveConfigPath(env, __dirname);
this._metrics = new Metrics(this._globalLogger, this._metricsFlushTimeout); // Five minutes default
@ -120,8 +121,8 @@ Server.prototype._createAndInitializeServices = function (env) {
};
Server.prototype._createHttpServer = function (env) {
var server,
self = this;
var server;
var self = this;
if (env.pfx) {
server = require('https').createServer({ pfx: env.pfx, passphrase: env.passphrase }, this._app);
@ -133,24 +134,24 @@ Server.prototype._createHttpServer = function (env) {
// override the listen function so the server only starts listening
// once all async initialization is complete
var originalListen = server.listen;
server.listen = function () {
var listenArgs = arguments;
server.listen = function(...args) {
var listenArgs = args;
var asyncStartupFunctions = [
function (done) { self._extensionManager.initialize(done); },
function (done) { self._requestHandler.initialize(self._app, self._extensionManager, done); }
done => { self._extensionManager.initialize(done); },
done => { self._requestHandler.initialize(self._app, self._extensionManager, done); }
];
if (!self._pushAdapter.notificationHubPush) {
asyncStartupFunctions.push(function (done) {
asyncStartupFunctions.push(done => {
self._scriptManager.runFeedbackScript(3600000);
done();
});
}
asyncStartupFunctions.push(function (done) { self._extensionManager.runStartupScript(done); });
asyncStartupFunctions.push(done => { self._extensionManager.runStartupScript(done); });
core.async.series(asyncStartupFunctions, function () {
core.async.series(asyncStartupFunctions, () => {
originalListen.apply(server, listenArgs);
self._setupFileWatcher();
self._globalLogger.log(LogLevel.Verbose, LogType.Information, logSource, "Server started and listening.");
@ -165,12 +166,12 @@ Server.prototype._setupFileWatcher = function () {
var self = this;
var sentinelFilePath = path.join(this._homePath, 'site/wwwroot/sentinel');
this._fileWatcher = new FileWatcher(sentinelFilePath, self._globalLogger, this._sentinelFilePollInterval, function () {
this._fileWatcher = new FileWatcher(sentinelFilePath, self._globalLogger, this._sentinelFilePollInterval, () => {
self._fileWatcher.stop();
self._triggerRecycle();
});
this._server.on('listening', function () {
this._server.on('listening', () => {
self._fileWatcher.start();
});
};
@ -187,7 +188,7 @@ Server.prototype._triggerRecycle = function () {
// to process any outstanding requests, but new requests will
// be routed by IIS Node to new instances.
var stream = this.net.connect(this._iisNodeControlPipe);
stream.on('error', function (err) {
stream.on('error', err => {
// if we get a stream error, we fall back to a
// "hard shutdown" after logging the error
self._shutdownProcess(0);
@ -204,12 +205,12 @@ Server.prototype._triggerRecycle = function () {
};
Server.prototype._registerUncaughtExceptionListenerAndCreateHttpServer = function (env, logger) {
var tripwireContext = {},
tripwireKeepalive = parseInt(env.MS_TripwireKeepalive, 10) || 5000,
self = this;
var tripwireContext = {};
var tripwireKeepalive = parseInt(env.MS_TripwireKeepalive, 10) || 5000;
var self = this;
// 99.9% of the time async errors will end up here and we assume all async errors belong to user code
this._onUncaughtException = function (e) {
this._onUncaughtException = e => {
process.removeAllListeners('uncaughtException');
var exitCode;
@ -256,12 +257,12 @@ Server.prototype._shutdownProcess = function (exitCode, timeout) {
// Wait a short period of time to allow any other logger instances a chance
// to flush themselves (based on their flush timeouts).
setTimeout(function () {
setTimeout(() => {
process.exit(exitCode);
}, timeout);
};
Server.prototype._logGlobalException = function (e, isTripWireError, logger) {
Server.prototype._logGlobalException = (e, isTripWireError, logger) => {
if (e.loggedToSystem || e.loggedToUser) {
// we've already logged this error
return;

Просмотреть файл

@ -4,7 +4,7 @@
//
// Module containing 'enum' definitions for http status codes
(function (exports) {
((exports => {
var core = require('./core');
@ -32,4 +32,4 @@
exports.StatusCodes = StatusCodes;
})(typeof exports === 'undefined' ? (this.StatusCodes = {}) : exports);
}))(typeof exports === 'undefined' ? (this.StatusCodes = {}) : exports);

Просмотреть файл

@ -2,7 +2,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
(function (global) {
((global => {
var core = require('../core');
@ -13,7 +13,7 @@
var instanceMembers = {
visitUnary: function (expr) {
visitUnary(expr) {
var operand = this.visit(expr.operand);
if (operand && expr.expressionType == ExpressionType.Not) {
@ -29,7 +29,7 @@
return expr;
},
visitBinary: function (expr) {
visitBinary(expr) {
var left = null;
var right = null;
@ -128,7 +128,7 @@
SqlBooleanizer = core.deriveClass(ExpressionVisitor, null, instanceMembers);
SqlBooleanizer.booleanize = function (expr) {
SqlBooleanizer.booleanize = expr => {
var booleanizer = new SqlBooleanizer();
expr = booleanizer.visit(expr);
@ -137,4 +137,4 @@
return expr;
};
})(typeof exports === "undefined" ? this : exports);
}))(typeof exports === "undefined" ? this : exports);

Просмотреть файл

@ -2,18 +2,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
(function (global) {
((global => {
var core = require('../core');
var _ = require('underscore');
var _str = require('underscore.string');
var core = require('../core'),
_ = require('underscore'),
_str = require('underscore.string');
require('../query/expressions');
require('../query/expressionvisitor');
require('../query/queryparser');
require('./sqlbooleanizer');
require('./typeconverter');
require('./sqlhelpers');
require('../query/expressions');
require('../query/expressionvisitor');
require('../query/queryparser');
require('./sqlbooleanizer');
require('./typeconverter');
require('./sqlhelpers');
_.mixin(_str.exports());
@ -24,7 +23,7 @@
var instanceMembers = {
format: function (query) {
format(query) {
this.sql = '';
this.paramNumber = 0;
this.parameters = [];
@ -47,7 +46,7 @@
this.sql = this.sql.trim();
},
_formatQuery: function (query) {
_formatQuery(query) {
var formattedSql;
var selection = query.select ? this._formatSelection(query.select, query.systemProperties) : '*';
@ -86,9 +85,10 @@
return formattedSql;
},
_formatPagedQuery: function (query) {
var formattedSql, selection = '',
aliasedSelection = '';
_formatPagedQuery(query) {
var formattedSql;
var selection = '';
var aliasedSelection = '';
if (query.select) {
selection = this._formatSelection(query.select, query.systemProperties);
@ -117,7 +117,7 @@
return formattedSql;
},
_formatCountQuery: function (table, query) {
_formatCountQuery(table, query) {
var filter;
if (query.filter || query.id !== undefined || this.tableMetadata.supportsSoftDelete) {
@ -132,7 +132,7 @@
return sql;
},
_formatOrderBy: function (query, defaultOrder) {
_formatOrderBy(query, defaultOrder) {
var orderBy = query.orderBy;
if (!orderBy) {
@ -151,7 +151,7 @@
var order = '';
var self = this;
orderings.forEach(function (ordering) {
orderings.forEach(ordering => {
if (order.length > 0) {
order += ', ';
}
@ -166,24 +166,24 @@
return order;
},
_formatSelection: function (selection, systemProperties, prefix) {
_formatSelection(selection, systemProperties, prefix) {
systemProperties = (systemProperties || []).map(core.systemPropertyToColumnName);
var formattedSelection = '',
columns = selection.split(',').concat(systemProperties);
var formattedSelection = '';
var columns = selection.split(',').concat(systemProperties);
columns.forEach(function (column) {
columns.forEach(column => {
var member = column.trim();
if (formattedSelection.length > 0) {
formattedSelection += ', ';
}
formattedSelection += (prefix || '') + SqlHelpers.formatMember(member);
});
});
return formattedSelection;
},
_formatFilter: function (query, defaultFilter) {
_formatFilter(query, defaultFilter) {
// if we already have a parsed filter use it,
// otherwise parse the filter
var filterExpr;
@ -231,13 +231,13 @@
// run the final query translation pipeline on the specified
// expression, modifying the expression tree as needed
_finalizeExpression: function (expr) {
_finalizeExpression(expr) {
expr = SqlBooleanizer.booleanize(expr);
expr = TypeConverter.convertTypes(expr, this.tableMetadata);
return expr;
},
visitBinary: function (expr) {
visitBinary(expr) {
this.sql += '(';
var left = null;
@ -322,7 +322,7 @@
return expr;
},
visitConstant: function (expr) {
visitConstant(expr) {
if (expr.value === null) {
this.sql += 'NULL';
return expr;
@ -333,11 +333,11 @@
return expr;
},
_createParameter: function (value) {
_createParameter(value) {
var parameter = {
name: '@p' + (this.paramNumber++).toString(),
pos: this.paramNumber,
value: value
value
};
this.parameters.push(parameter);
@ -347,7 +347,7 @@
return '?';
},
visitMember: function (expr) {
visitMember(expr) {
if (typeof expr.member === 'string') {
this.sql += SqlHelpers.formatMember(expr.member);
}
@ -358,7 +358,7 @@
return expr;
},
visitUnary: function (expr) {
visitUnary(expr) {
if (expr.expressionType == ExpressionType.Not) {
this.sql += 'NOT ';
this.visit(expr.operand);
@ -372,14 +372,14 @@
return expr;
},
visitFunction: function (expr) {
visitFunction(expr) {
if (expr.memberInfo) {
this._formatMappedFunction(expr);
}
return expr;
},
_formatMappedFunction: function (expr) {
_formatMappedFunction(expr) {
if (expr.memberInfo.type == 'string') {
this._formatMappedStringMember(expr.instance, expr.memberInfo, expr.args);
}
@ -391,13 +391,13 @@
}
},
_formatMappedMember: function (expr) {
_formatMappedMember(expr) {
if (expr.member.type == 'string') {
this._formatMappedStringMember(expr.instance, expr.member, null);
}
},
_formatMappedDateMember: function (instance, mappedMemberInfo, args) {
_formatMappedDateMember(instance, mappedMemberInfo, args) {
var functionName = mappedMemberInfo.memberName;
if (functionName == 'day') {
@ -432,7 +432,7 @@
}
},
_formatMappedMathMember: function (instance, mappedMemberInfo, args) {
_formatMappedMathMember(instance, mappedMemberInfo, args) {
var functionName = mappedMemberInfo.memberName;
if (functionName == 'floor') {
@ -455,7 +455,7 @@
}
},
_formatMappedStringMember: function (instance, mappedMemberInfo, args) {
_formatMappedStringMember(instance, mappedMemberInfo, args) {
var functionName = mappedMemberInfo.memberName;
if (functionName == 'substringof') {
@ -579,5 +579,4 @@
}
SqlFormatter = core.deriveClass(ExpressionVisitor, ctor, instanceMembers);
})(typeof exports === "undefined" ? this : exports);
}))(typeof exports === "undefined" ? this : exports);

Просмотреть файл

@ -2,12 +2,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
(function (global) {
var _ = require('underscore'),
_str = require('underscore.string'),
resource = require('../resources'),
core = require('../core');
((global => {
var _ = require('underscore');
var _str = require('underscore.string');
var resource = require('../resources');
var core = require('../core');
_.mixin(_str.exports());
@ -56,18 +55,18 @@
var classMembers = {
// inspects the specified error (including innerError) and returns
// the sqlstate if it exists
getSqlErrorCode: function (err) {
getSqlErrorCode(err) {
if (err) {
return err.innerError ? err.innerError.sqlstate : err.sqlstate;
}
},
// determines whether the specified error is a sql error
isSqlError: function (err) {
isSqlError(err) {
return err && !!this.getSqlErrorCode(err);
},
isThrottleError: function (err) {
isThrottleError(err) {
// There are a set of SqlAzure specific throttle errors that we must identify by
// error number, in addition to the general HY000 sql state they return. These are:
// http://social.technet.microsoft.com/wiki/contents/articles/1541.windows-azure-sql-database-connection-management.aspx
@ -81,7 +80,7 @@
// has an error code that matches one of our
// 'retry' codes, indicating that the failed sql
// operation should be reattempted.
isTemporaryError: function (err) {
isTemporaryError(err) {
var errCode = err.sqlstate;
if (errCode) {
for (var idx in SqlTemporaryErrorCodes) {
@ -100,12 +99,10 @@
// Returns true if the specified sql error is considered to be
// an application controlled issue. Returns false if the error is
// likely due to bad input data (e.g. wrong data type, null constraint, etc)
isApplicationError: function (err) {
isApplicationError(err) {
var sqlErrorCode = this.getSqlErrorCode(err);
if (sqlErrorCode) {
return _.any(SqlApplicationErrorCodes, function (code) {
return sqlErrorCode == code;
});
return _.any(SqlApplicationErrorCodes, code => sqlErrorCode == code);
}
return false;
},
@ -113,7 +110,7 @@
// Returns true if the specified sql error should be considered
// a "system" sql error that we should log to our system log.
// See here for more info on ODBC status codes: http://msdn.microsoft.com/en-us/library/ms714687.aspx
isSystemSqlError: function (err) {
isSystemSqlError(err) {
var sqlErrorCode = this.getSqlErrorCode(err);
if (!sqlErrorCode) {
return false;
@ -135,7 +132,7 @@
//
// When used with proper sql parameterization techniques, this
// mitigates SQL INJECTION attacks.
isValidIdentifier: function (identifier) {
isValidIdentifier(identifier) {
if (!identifier || !core.isString(identifier) || identifier.length > 128) {
return false;
}
@ -157,7 +154,7 @@
return true;
},
validateIdentifier: function (identifier) {
validateIdentifier(identifier) {
if (!this.isValidIdentifier(identifier)) {
throw new core.MobileServiceError(_.sprintf(resource.invalidIdentifier, identifier), core.ErrorCodes.BadInput);
}
@ -166,24 +163,24 @@
// SECURITY - sql generation relies on these format functions to
// validate identifiers to mitigate sql injection attacks
// in the dynamic sql we generate
formatTableName: function (schemaName, tableName) {
formatTableName(schemaName, tableName) {
this.validateIdentifier(schemaName);
this.validateIdentifier(tableName);
return _.sprintf('[%s].[%s]', schemaName, tableName);
},
formatSchemaName: function (appName) {
formatSchemaName(appName) {
// Hyphens are not supported in schema names
return appName.replace(/-/g, '_');
},
formatMember: function (memberName) {
formatMember(memberName) {
this.validateIdentifier(memberName);
return _.sprintf('[%s]', memberName);
},
// map json datatypes to SqlTypes
getSqlType: function (value) {
getSqlType(value) {
var type = core.classof(value);
switch (type) {
case 'string':
@ -201,5 +198,4 @@
};
SqlHelpers = core.defineClass(null, null, classMembers);
})(typeof exports === "undefined" ? this : exports);
}))(typeof exports === "undefined" ? this : exports);

Просмотреть файл

@ -2,12 +2,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
var sql = require('sqlserver'),
_ = require('underscore'),
_str = require('underscore.string'),
resource = require('../resources'),
core = require('../core'),
TableMetadata = require('./tablemetadata');
var sql = require('sqlserver');
var _ = require('underscore');
var _str = require('underscore.string');
var resource = require('../resources');
var core = require('../core');
var TableMetadata = require('./tablemetadata');
_.mixin(_str.exports());
@ -43,7 +44,7 @@ Storage.prototype.getTableMetadata = function (table, logger, callback) {
}
var self = this;
this._getTableColumns(table, logger, function (error, columns) {
this._getTableColumns(table, logger, (error, columns) => {
if (error) {
callback(error);
return;
@ -70,9 +71,9 @@ Storage.prototype.insert = function (table, item, logger, options, callback) {
// item can either be a singleton or a homogeneous array
// of items to insert in a single batch
var insertOptions = {
table: table,
item: item,
logger: logger,
table,
item,
logger,
retry: this.dynamicSchemaEnabled,
systemProperties: this._getSystemPropertiesFromOptions(options)
};
@ -82,7 +83,7 @@ Storage.prototype.insert = function (table, item, logger, options, callback) {
Storage.prototype.update = function (table, id, item, logger, options, callback) {
var self = this;
this._validateId(table, id, logger, function (error) {
this._validateId(table, id, logger, error => {
if (error) {
callback(error);
return;
@ -99,10 +100,10 @@ Storage.prototype.update = function (table, id, item, logger, options, callback)
}
var updateOptions = {
table: table,
id: id,
item: item,
logger: logger,
table,
id,
item,
logger,
retry: self.dynamicSchemaEnabled,
systemProperties: self._getSystemPropertiesFromOptions(options)
};
@ -113,7 +114,7 @@ Storage.prototype.update = function (table, id, item, logger, options, callback)
Storage.prototype.del = function (table, id, version, logger, options, callback) {
var self = this;
this._validateId(table, id, logger, function (error) {
this._validateId(table, id, logger, error => {
if (error) {
callback(error);
return;
@ -136,7 +137,7 @@ Storage.prototype._getTableMetadataAndSupportedSystemProperties = function (tabl
// get the table metadata
var self = this;
this.getTableMetadata(table, logger, function (error, tableMetadata) {
this.getTableMetadata(table, logger, (error, tableMetadata) => {
if (error) {
callback(error);
return;
@ -145,7 +146,7 @@ Storage.prototype._getTableMetadataAndSupportedSystemProperties = function (tabl
// check that only supported system properties are being requested
var supportedSystemProperties = [];
if (tableMetadata && tableMetadata.hasStringId) {
systemProperties.forEach(function (property) {
systemProperties.forEach(property => {
if (_.contains(tableMetadata.systemProperties, property)) {
supportedSystemProperties.push(property);
}
@ -163,17 +164,17 @@ Storage.prototype._clearTableMetadata = function (table) {
this.metadata[table] = null;
};
Storage.prototype._getSystemPropertiesFromOptions = function (options) {
Storage.prototype._getSystemPropertiesFromOptions = options => {
var systemProperties = options ? options.systemProperties || [] : [];
return systemProperties;
};
Storage.prototype._validateProperty = function (propertyName, value) {
Storage.prototype._validateProperty = (propertyName, value) => {
// property name must be a valid identifier
SqlHelpers.validateIdentifier(propertyName);
// if there is a system property, make sure it is cased correctly
var systemColumnName = _.find(core.supportedSystemColumns, function (c) { return c.toLowerCase() === propertyName; });
var systemColumnName = _.find(core.supportedSystemColumns, c => c.toLowerCase() === propertyName);
if (systemColumnName && propertyName !== systemColumnName) {
throw new core.MobileServiceError(_.sprintf("If a value for the property '%s' is specified, the property name must be cased correctly.", systemColumn), core.ErrorCodes.BadInput);
}
@ -189,7 +190,7 @@ Storage.prototype._updateSchema = function (table, item, logger, callback) {
var retryCount = 0;
function tryUpdateSchema() {
self._getColumnsToAdd(table, item, logger, function (err, cols) {
self._getColumnsToAdd(table, item, logger, (err, cols) => {
if (err) {
callback(err);
return;
@ -207,7 +208,7 @@ Storage.prototype._updateSchema = function (table, item, logger, callback) {
// so we don't need to do so again here
var addColumnsSql = '';
var columnsToAddError = null;
cols.forEach(function (col) {
cols.forEach(col => {
if (core.isSystemColumnName(col) &&
self.metadata[table].hasStringId) {
columnsToAddError = new core.MobileServiceError(_.sprintf("The column '%s' can not be dynamically added. Columns that begin with a '__' are considered system columns.", col), core.ErrorCodes.BadInput);
@ -228,7 +229,7 @@ Storage.prototype._updateSchema = function (table, item, logger, callback) {
var cmdText = _.sprintf("ALTER TABLE %s ADD %s;", tableName, addColumnsSql);
logger.trace(logSource, 'Updating schema', 'SQL: ' + cmdText);
self._executeSql('ALTER', cmdText, null, logger, null, callback, function (err) {
self._executeSql('ALTER', cmdText, null, logger, null, callback, err => {
if (!err) {
logger.trace(logSource, 'Schema update succeeded.');
callback(null);
@ -258,7 +259,7 @@ Storage.prototype._getTableColumns = function (table, logger, callback) {
var statement = _.sprintf("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '%s' AND TABLE_SCHEMA = '%s'", table, this.schemaName);
var self = this;
this._executeSql('SELECT', statement, null, logger, null, callback, function (error, results) {
this._executeSql('SELECT', statement, null, logger, null, callback, (error, results) => {
if (error) {
callback(error);
return;
@ -279,7 +280,7 @@ Storage.prototype._getTableColumns = function (table, logger, callback) {
Storage.prototype._getColumnsToAdd = function (table, item, logger, callback) {
var self = this;
this._getTableColumns(table, logger, function (error, results) {
this._getTableColumns(table, logger, (error, results) => {
if (error) {
callback(error);
return;
@ -315,19 +316,19 @@ Storage.prototype._getColumnsToAdd = function (table, item, logger, callback) {
};
Storage.prototype._update = function (options, callback) {
var table = options.table,
systemProperties = options.systemProperties,
logger = options.logger,
item = options.item,
updateStatement = options.updateStatement,
parameters = options.parameters,
self = this;
var table = options.table;
var systemProperties = options.systemProperties;
var logger = options.logger;
var item = options.item;
var updateStatement = options.updateStatement;
var parameters = options.parameters;
var self = this;
if (item.__version) {
item.__version = core.normalizeVersion(item.__version);
}
this._getTableMetadataAndSupportedSystemProperties(table, systemProperties, logger, function (error, systemProperties, tableMetadata) {
this._getTableMetadataAndSupportedSystemProperties(table, systemProperties, logger, (error, systemProperties, tableMetadata) => {
if (error) {
callback(error);
return;
@ -339,7 +340,7 @@ Storage.prototype._update = function (options, callback) {
}
else {
// we are building the update statement for the first time
self._buildSqlUpdate(options, tableMetadata, systemProperties, function (error, updateStatement, parameters, version) {
self._buildSqlUpdate(options, tableMetadata, systemProperties, (error, updateStatement, parameters, version) => {
if (error) {
callback(error);
return;
@ -360,21 +361,21 @@ Storage.prototype._update = function (options, callback) {
};
Storage.prototype._executeSqlUpdate = function (options, callback) {
var self = this,
table = options.table,
id = options.id,
systemProperties = options.systemProperties,
logger = options.logger,
item = options.item,
version = options.version,
updateRowCount = 0,
updateStatement = options.updateStatement,
parameters = options.parameters,
lastResult = null;
var self = this;
var table = options.table;
var id = options.id;
var systemProperties = options.systemProperties;
var logger = options.logger;
var item = options.item;
var version = options.version;
var updateRowCount = 0;
var updateStatement = options.updateStatement;
var parameters = options.parameters;
var lastResult = null;
logger.trace(logSource, 'Executing update', 'SQL: ' + updateStatement);
this._executeSql('UPDATE', updateStatement, parameters, logger, null, callback, function (error, results, more, rowCount) {
this._executeSql('UPDATE', updateStatement, parameters, logger, null, callback, (error, results, more, rowCount) => {
if (error) {
self._handleUpdateError(error, options, logger, callback);
return;
@ -410,7 +411,7 @@ Storage.prototype._executeSqlUpdate = function (options, callback) {
// when update or delete statement affects 0 records this method checks to see if the version check failed or the record does not exist
Storage.prototype._handleUpdateOrDeleteFailure = function (logger, table, item, callback, forOperation) {
this._readItemForError(logger, table, item.id, function (error, result) {
this._readItemForError(logger, table, item.id, (error, result) => {
if (error || !result) {
callback(error, result);
return;
@ -431,13 +432,13 @@ Storage.prototype._handleUpdateOrDeleteFailure = function (logger, table, item,
Storage.prototype._readItemForError = function (logger, table, id, callback, readErrorFormat) {
var query = {
table: table,
id: id
table,
id
};
var queryOptions = { systemProperties: ['*'], includeDeleted: true };
this.query(query, logger, queryOptions, function (error, results) {
this.query(query, logger, queryOptions, (error, results) => {
if (error) {
logger.trace(logSource, _.sprintf(readErrorFormat, error.toString()));
if (callback) {
@ -458,19 +459,18 @@ Storage.prototype._readItemForError = function (logger, table, id, callback, rea
};
Storage.prototype._buildSqlUpdate = function (options, tableMetadata, systemProperties, callback) {
var table = options.table,
item = options.item,
logger = options.logger,
id = options.id;
var tableName = SqlHelpers.formatTableName(this.schemaName, table),
setStatements = '',
selectItemProperties = '',
versionValue = '',
hasStringId = tableMetadata.hasStringId,
updateStmt = '',
binaryColumns = tableMetadata.binaryColumns,
parameters = [];
var table = options.table;
var item = options.item;
var logger = options.logger;
var id = options.id;
var tableName = SqlHelpers.formatTableName(this.schemaName, table);
var setStatements = '';
var selectItemProperties = '';
var versionValue = '';
var hasStringId = tableMetadata.hasStringId;
var updateStmt = '';
var binaryColumns = tableMetadata.binaryColumns;
var parameters = [];
for (var prop in item) {
var value = item[prop];
@ -541,7 +541,7 @@ Storage.prototype._buildSqlUpdate = function (options, tableMetadata, systemProp
// Add the SELECT clause if the id is a string
if (hasStringId) {
if (systemProperties) {
_.each(systemProperties, function (systemProperty) {
_.each(systemProperties, systemProperty => {
if (!versionValue || systemProperty !== 'version') {
if (selectItemProperties.length > 0) {
selectItemProperties += ', ';
@ -554,12 +554,12 @@ Storage.prototype._buildSqlUpdate = function (options, tableMetadata, systemProp
updateStmt += _.sprintf("; SELECT %s FROM %s WHERE [id] = ?", selectItemProperties, tableName);
parameters.push(id);
}
}
}
callback(null, updateStmt, parameters, versionValue);
};
Storage.prototype._trySetVersionParameter = function (version, parameters, callback) {
Storage.prototype._trySetVersionParameter = (version, parameters, callback) => {
var versionBuffer = null;
try {
versionBuffer = new Buffer(version, 'base64');
@ -572,7 +572,7 @@ Storage.prototype._trySetVersionParameter = function (version, parameters, callb
return true;
};
Storage.prototype._handleUpdateSuccess = function (updateRowCount, item, results, logger, callback) {
Storage.prototype._handleUpdateSuccess = (updateRowCount, item, results, logger, callback) => {
logger.trace(logSource, 'Update completed successfully. Rows affected: ' + updateRowCount);
if (callback) {
@ -606,7 +606,7 @@ Storage.prototype._handleUpdateError = function (error, options, logger, callbac
Storage.prototype._retryUpdate = function (options, callback) {
var self = this;
this._updateSchema(options.table, options.item, options.logger, function (error) {
this._updateSchema(options.table, options.item, options.logger, error => {
if (error) {
callback(error);
return;
@ -619,17 +619,17 @@ Storage.prototype._retryUpdate = function (options, callback) {
};
Storage.prototype._del = function (table, id, version, logger, callback) {
var parameters = [],
item = { id: id, __version: version },
tableName = SqlHelpers.formatTableName(this.schemaName, table),
deleteStmt = _.sprintf("DELETE FROM %s WHERE [id] = ?", tableName),
sqlEventName = 'DELETE',
forOperation = 'delete',
errorPrefix = 'Delete',
self = this;
var parameters = [];
var item = { id, __version: version };
var tableName = SqlHelpers.formatTableName(this.schemaName, table);
var deleteStmt = _.sprintf("DELETE FROM %s WHERE [id] = ?", tableName);
var sqlEventName = 'DELETE';
var forOperation = 'delete';
var errorPrefix = 'Delete';
var self = this;
parameters.push(id);
this.getTableMetadata(table, logger, function (error, tableMetadata) {
this.getTableMetadata(table, logger, (error, tableMetadata) => {
if (error) {
callback(error);
return;
@ -653,7 +653,7 @@ Storage.prototype._del = function (table, id, version, logger, callback) {
logger.trace(logSource, 'Executing delete', 'SQL: ' + deleteStmt);
var deleteRowCount = 0;
self._executeSql(sqlEventName, deleteStmt, parameters, logger, null, callback, function (err, results, more, rowCount) {
self._executeSql(sqlEventName, deleteStmt, parameters, logger, null, callback, (err, results, more, rowCount) => {
if (!err) {
// The row count should always be 1 since the delete is based on the primary key
// but this callback mught be invoked multiple times, and the rowCount might be set on
@ -685,15 +685,15 @@ Storage.prototype._del = function (table, id, version, logger, callback) {
};
Storage.prototype._insert = function (options, callback) {
var table = options.table,
systemProperties = options.systemProperties,
logger = options.logger,
item = options.item,
insertStatement = options.insertStatement,
parameters = options.parameters,
self = this;
var table = options.table;
var systemProperties = options.systemProperties;
var logger = options.logger;
var item = options.item;
var insertStatement = options.insertStatement;
var parameters = options.parameters;
var self = this;
this._getTableMetadataAndSupportedSystemProperties(table, systemProperties, logger, function (error, systemProperties, tableMetadata) {
this._getTableMetadataAndSupportedSystemProperties(table, systemProperties, logger, (error, systemProperties, tableMetadata) => {
if (error) {
callback(error);
return;
@ -705,7 +705,7 @@ Storage.prototype._insert = function (options, callback) {
}
else {
// we are building the insert statement for the first time
self._buildSqlInsert(table, item, tableMetadata, systemProperties, logger, function (error, insertStatement, parameters) {
self._buildSqlInsert(table, item, tableMetadata, systemProperties, logger, (error, insertStatement, parameters) => {
if (error) {
callback(error);
return;
@ -722,15 +722,15 @@ Storage.prototype._insert = function (options, callback) {
};
Storage.prototype._executeSqlInsert = function (options, callback) {
var self = this,
logger = options.logger,
item = options.item,
insertStatement = options.insertStatement,
parameters = options.parameters;
var self = this;
var logger = options.logger;
var item = options.item;
var insertStatement = options.insertStatement;
var parameters = options.parameters;
logger.trace(logSource, 'Executing insert', 'SQL: ' + insertStatement);
this._executeSql('INSERT', insertStatement, parameters, logger, null, callback, function (error, results, more) {
this._executeSql('INSERT', insertStatement, parameters, logger, null, callback, (error, results, more) => {
if (error) {
self._handleInsertError(error, options, logger, callback);
return;
@ -743,16 +743,16 @@ Storage.prototype._executeSqlInsert = function (options, callback) {
};
Storage.prototype._buildSqlInsert = function (table, item, tableMetadata, systemProperties, logger, callback) {
var parameters = [],
hasStringId = tableMetadata.hasStringId,
binaryColumns = tableMetadata.binaryColumns,
tableName = SqlHelpers.formatTableName(this.schemaName, table),
self = this,
invalidIdError = null,
columnNames = '',
valueParams = '';
var parameters = [];
var hasStringId = tableMetadata.hasStringId;
var binaryColumns = tableMetadata.binaryColumns;
var tableName = SqlHelpers.formatTableName(this.schemaName, table);
var self = this;
var invalidIdError = null;
var columnNames = '';
var valueParams = '';
_.each(item, function (value, prop) {
_.each(item, (value, prop) => {
if (!invalidIdError) {
// validate the property
try {
@ -826,7 +826,7 @@ Storage.prototype._buildSqlInsert = function (table, item, tableMetadata, system
if (hasStringId) {
var selectItemProperties = '[appTable].[id] AS [id]';
if (systemProperties) {
systemProperties.forEach(function (systemProperty) {
systemProperties.forEach(systemProperty => {
selectItemProperties += _.sprintf(', [appTable].[__%1$s] AS [__%1$s]', systemProperty);
});
}
@ -840,7 +840,7 @@ Storage.prototype._buildSqlInsert = function (table, item, tableMetadata, system
callback(null, insertStmt, parameters);
};
Storage.prototype._handleInsertSuccess = function (item, results, logger, callback) {
Storage.prototype._handleInsertSuccess = (item, results, logger, callback) => {
logger.trace(logSource, 'Insert completed successfully.');
if (callback) {
@ -878,7 +878,7 @@ Storage.prototype._retryInsert = function (options, callback) {
// this of course assumes homogenous arrays
var item = core.isArray(options.item) ? options.item[0] : options.item;
this._updateSchema(options.table, item, options.logger, function (err) {
this._updateSchema(options.table, item, options.logger, err => {
if (!err) {
// the schema update succeeded, so retry the insert
options.retry = false;
@ -893,7 +893,7 @@ Storage.prototype._retryInsert = function (options, callback) {
Storage.prototype._query = function (query, logger, callback) {
// ensure only supported system properties are being requested
var self = this;
this._getTableMetadataAndSupportedSystemProperties(query.table, query.systemProperties, logger, function (error, systemProperties, tableMetadata) {
this._getTableMetadataAndSupportedSystemProperties(query.table, query.systemProperties, logger, (error, systemProperties, tableMetadata) => {
if (error) {
callback(error);
return;
@ -901,7 +901,7 @@ Storage.prototype._query = function (query, logger, callback) {
query.systemProperties = systemProperties;
self._buildSqlQuery(query, tableMetadata, function (error, sqlStatement, parameters) {
self._buildSqlQuery(query, tableMetadata, (error, sqlStatement, parameters) => {
if (error) {
callback(error);
return;
@ -910,7 +910,7 @@ Storage.prototype._query = function (query, logger, callback) {
logger.trace(logSource, 'Executing query', 'SQL: ' + sqlStatement);
var allResults = [];
self._executeSql('SELECT', sqlStatement, parameters, logger, null, callback, function (error, results, more) {
self._executeSql('SELECT', sqlStatement, parameters, logger, null, callback, (error, results, more) => {
if (error) {
self._handleQueryError(query, error, logger, callback);
}
@ -939,7 +939,7 @@ Storage.prototype._buildSqlQuery = function (query, tableMetadata, callback) {
// build the parameter values array
var parameters = [];
_.each(formatter.parameters, function (parameter) {
_.each(formatter.parameters, parameter => {
parameters.push(parameter.value);
});
@ -966,11 +966,11 @@ Storage.prototype._handleQueryError = function (query, error, logger, callback)
}
};
Storage.prototype._getSystemPropertiesToDeleteFromQueryResults = function (query, tableMetadata) {
Storage.prototype._getSystemPropertiesToDeleteFromQueryResults = (query, tableMetadata) => {
// get a normalized (trimmed, all lowercase) list of the select properties
var selectedProperties = [];
if (query.select) {
query.select.split(',').forEach(function (selectedProperty) {
query.select.split(',').forEach(selectedProperty => {
selectedProperty = selectedProperty.trim();
if (selectedProperty.length > 0) {
selectedProperty = selectedProperty.toLowerCase();
@ -980,7 +980,7 @@ Storage.prototype._getSystemPropertiesToDeleteFromQueryResults = function (query
}
var systemPropertiesToDelete = [];
tableMetadata.systemProperties.forEach(function (systemProperty) {
tableMetadata.systemProperties.forEach(systemProperty => {
// don't delete any requested system properties
if (!_.contains(query.systemProperties, systemProperty)) {
var columnName = core.systemPropertyToColumnName(systemProperty.toLowerCase());
@ -1009,14 +1009,14 @@ Storage.prototype._handleQuerySuccess = function (query, results, tableMetadata,
// iterate through the results to remove row numbers or system properties
// that were not requested
if (pagedQuery || systemPropertiesToDelete.length > 0) {
_.each(queryResult, function (result) {
_.each(queryResult, result => {
// delete the row numbers if the query was paged
if (pagedQuery) {
delete result.ROW_NUMBER;
}
// delete the system property if it wasn't requested
_.each(_.keys(result), function (property) {
_.each(_.keys(result), property => {
if (_.contains(systemPropertiesToDelete, property.toLowerCase())) {
delete result[property];
}
@ -1040,7 +1040,7 @@ Storage.prototype._handleQuerySuccess = function (query, results, tableMetadata,
};
// Intended to only be called for unhandled errors that have been caught
Storage.prototype._handleSystemError = function (error, logger, callback) {
Storage.prototype._handleSystemError = (error, logger, callback) => {
if (core.isRuntimeError(error)) {
logger.error(logSource, error);
}
@ -1054,7 +1054,7 @@ Storage.prototype._handleSystemError = function (error, logger, callback) {
};
Storage.prototype._validateId = function (table, id, logger, callback) {
this.getTableMetadata(table, logger, function (error, tableMetadata) {
this.getTableMetadata(table, logger, (error, tableMetadata) => {
var idType = tableMetadata.idType;
error = null;
if (!id ||
@ -1074,7 +1074,7 @@ Storage.prototype._validateId = function (table, id, logger, callback) {
// }
Storage.prototype.executeSql = function (sqlEventName, sqlStmt, parameters, logger, options, callback) {
try {
this._executeSql(sqlEventName, sqlStmt, parameters, logger, options, function (err) {
this._executeSql(sqlEventName, sqlStmt, parameters, logger, options, err => {
callback(err);
}, callback);
}
@ -1088,16 +1088,16 @@ Storage.prototype.executeSql = function (sqlEventName, sqlStmt, parameters, logg
Storage.prototype._executeSql = function (sqlEventName, sqlStmt, parameters, logger, options, callback, sqlCallback) {
options = options || {};
var self = this,
rowCount,
retryCount = 0,
disableUserLog = options.disableUserLog || false;
var self = this;
var rowCount;
var retryCount = 0;
var disableUserLog = options.disableUserLog || false;
// to facilitate retries, define a function that will actually execute the sql
function executeSql() {
try {
var event = self.metrics.startEvent('sql.command.' + sqlEventName);
var stmt = self.sql.query(self.connection, sqlStmt, parameters, function (err, results, more) {
var stmt = self.sql.query(self.connection, sqlStmt, parameters, (err, results, more) => {
self.metrics.endEvent(event);
if (err) {
@ -1142,7 +1142,7 @@ Storage.prototype._executeSql = function (sqlEventName, sqlStmt, parameters, log
});
if (stmt) {
stmt.on('rowcount', function (result) {
stmt.on('rowcount', result => {
rowCount = result;
});
}

Просмотреть файл

@ -4,9 +4,10 @@
//
// This class captures the metadata about a table in user database.
var _ = require('underscore'),
_str = require('underscore.string');
core = require('../core');
var _ = require('underscore');
var _str = require('underscore.string');
core = require('../core');
_.mixin(_str.exports());
@ -18,7 +19,7 @@ function TableMetadata () {
this.binaryColumns = [];
Object.defineProperty(this, 'hasStringId', {
get: function () { return this.idType === 'string'; }
get() { return this.idType === 'string'; }
});
}
@ -59,7 +60,7 @@ TableMetadata.prototype._addSystemColumn = function (column) {
}
};
TableMetadata.prototype._getTableIdType = function (type) {
TableMetadata.prototype._getTableIdType = type => {
if (type.indexOf('int') >= 0) {
return 'number';
}
@ -69,12 +70,12 @@ TableMetadata.prototype._getTableIdType = function (type) {
return 'unknown';
};
TableMetadata.fromColumns = function (columns) {
TableMetadata.fromColumns = columns => {
// the default table metadata
var metadata = new TableMetadata();
// iterate over the columns
_.each(columns, function (column) {
_.each(columns, column => {
metadata._addColumn(column);
});

Просмотреть файл

@ -2,10 +2,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// ----------------------------------------------------------------------------
(function (global) {
var core = require('../core'),
_ = require('underscore');
((global => {
var core = require('../core');
var _ = require('underscore');
require('../query/expressions');
require('../query/expressionvisitor');
@ -18,7 +17,7 @@
var instanceMembers = {
visitBinary: function (expr) {
visitBinary(expr) {
var left = expr.left ? this.visit(expr.left) : null;
var right = expr.right ? this.visit(expr.right) : null;
@ -36,13 +35,13 @@
return expr;
},
_isStringConstant: function(expr) {
_isStringConstant(expr) {
return expr &&
expr.expressionType === ExpressionType.Constant &&
core.isString(expr.value);
},
_isBinaryMemberAccess: function (expr) {
_isBinaryMemberAccess(expr) {
return expr &&
expr.expressionType === ExpressionType.MemberAccess &&
core.isString(expr.member) &&
@ -52,12 +51,11 @@
TypeConverter = core.deriveClass(ExpressionVisitor, ctor, instanceMembers);
TypeConverter.convertTypes = function (expr, tableMetadata) {
TypeConverter.convertTypes = (expr, tableMetadata) => {
var converter = new TypeConverter(tableMetadata);
expr = converter.visit(expr);
return expr;
};
})(typeof exports === "undefined" ? this : exports);
}))(typeof exports === "undefined" ? this : exports);

Просмотреть файл

@ -7,10 +7,13 @@
// { secrets: { ... }, claims: {... } }
// where secrets and claims are key value pairs of data about user
var Encryptor = require('../encryptor'),
VERSION = 1, // version of encryption algorithm
KEYID = 0; // in future when we support key rollover, we will increment this every time key changes
// we will keep at least two master keys (with their key ids) at all times i.e. current and previous
var Encryptor = require('../encryptor'); // in future when we support key rollover, we will increment this every time key changes
// we will keep at least two master keys (with their key ids) at all times i.e. current and previous
var // version of encryption algorithm
VERSION = 1;
var KEYID = 0;
function UserProperties(masterKey) {
this.encryptionKey = masterKey + 'USR';

Просмотреть файл

@ -4,13 +4,14 @@
//
// This class encapsulates the business logic for promoting anonymous user to registered user and adding identity of an existing user
var _ = require('underscore'),
_str = require('underscore.string'),
core = require('../core.js'),
Storage = require('../storage/storage.js'),
UserStore = require('./userstore.js'),
UserProperties = require('./userproperties'),
logSource = 'UserService';
var _ = require('underscore');
var _str = require('underscore.string');
var core = require('../core.js');
var Storage = require('../storage/storage.js');
var UserStore = require('./userstore.js');
var UserProperties = require('./userproperties');
var logSource = 'UserService';
_.mixin(_str.exports());
@ -25,7 +26,7 @@ function UserService(logger, userStore, userProperties, encryptClaims) {
UserService.prototype.isEnabled = function (callback) {
var self = this;
this.userStore.isEnabled(function (err, isEnabled) {
this.userStore.isEnabled((err, isEnabled) => {
if (err) {
return self._handleStorageError(err, callback);
}
@ -38,7 +39,7 @@ UserService.prototype.isEnabled = function (callback) {
UserService.prototype.getUserIdentities = function (id, callback) {
var self = this;
this.getUserById(id, function (err, user) {
this.getUserById(id, (err, user) => {
if (err) {
callback(err);
return;
@ -51,7 +52,7 @@ UserService.prototype.getUserIdentities = function (id, callback) {
// { microsoft: { userId: 1234, email: 'someone@example.com'},
// facebook: { userId: 345, name: 'john' } }
self._getAllProviderProperties(user)
.forEach(function (item) {
.forEach(item => {
if (item.properties) {
var identity = self._userPropertiesToIdentity(item.provider, item.providerId, item.properties);
identities[item.provider] = identity;
@ -67,7 +68,7 @@ UserService.prototype.getUserIdentities = function (id, callback) {
UserService.prototype.getUserById = function (id, callback) {
var self = this;
this.userStore.getUserById(id, function (err, user) {
this.userStore.getUserById(id, (err, user) => {
if (err) {
return self._handleStorageError(err, callback);
}
@ -75,7 +76,7 @@ UserService.prototype.getUserById = function (id, callback) {
if (user) {
// provider properties are packed in storage and need to be unpacked
self._getAllProviderProperties(user)
.forEach(function (item) {
.forEach(item => {
user[item.key] = self.userProperties.unpack(item.properties);
});
}
@ -99,7 +100,7 @@ UserService.prototype.addUserIdentity = function (provider, providerId, properti
properties = this.userProperties.pack(properties);
this.userStore.getUserByProviderId(provider, providerId, function (err, user) {
this.userStore.getUserByProviderId(provider, providerId, (err, user) => {
if (err) {
return self._handleStorageError(err, callback);
}
@ -114,14 +115,14 @@ UserService.prototype.addUserIdentity = function (provider, providerId, properti
};
// returns all providers on user object
UserService.prototype._getAllProviderProperties = function (user) {
UserService.prototype._getAllProviderProperties = user => {
// user table in database has columns for each provider, prefixed by provider name
var allProperties = _.filter(Object.keys(user), function (propName) { return _.endsWith(propName, 'Properties'); })
.map(function (propName) {
var allProperties = _.filter(Object.keys(user), propName => _.endsWith(propName, 'Properties'))
.map(propName => {
var provider = _.strLeft(propName, 'Properties');
return {
key: propName,
provider: provider,
provider,
providerId: user[provider + 'Id'],
properties: user[propName]
};
@ -131,7 +132,7 @@ UserService.prototype._getAllProviderProperties = function (user) {
};
// converts the properties object into user identity object returned from user.getIdentities()
UserService.prototype._userPropertiesToIdentity = function (provider, providerId, properties) {
UserService.prototype._userPropertiesToIdentity = (provider, providerId, properties) => {
var claims = properties.claims || {};
var identity = _.extend(claims, properties.secrets);
if (providerId) {
@ -144,7 +145,7 @@ UserService.prototype._userPropertiesToIdentity = function (provider, providerId
UserService.prototype._createUser = function (provider, providerId, properties, callback) {
var self = this;
this.userStore.createUser(provider, providerId, properties, function (err, user) {
this.userStore.createUser(provider, providerId, properties, (err, user) => {
if (err) {
return self._handleStorageError(err, callback);
}
@ -154,9 +155,9 @@ UserService.prototype._createUser = function (provider, providerId, properties,
};
UserService.prototype._addIdentityToUser = function (user, provider, providerId, properties, callback) {
var self = this,
idKey = provider + 'Id',
propertiesKey = provider + 'Properties';
var self = this;
var idKey = provider + 'Id';
var propertiesKey = provider + 'Properties';
var modified = user[idKey] !== providerId || user[propertiesKey] !== properties;
if (!modified) {
@ -167,7 +168,7 @@ UserService.prototype._addIdentityToUser = function (user, provider, providerId,
user[idKey] = providerId.toString();
user[propertiesKey] = properties;
this.userStore.updateUser(user, function (err, rowCount) {
this.userStore.updateUser(user, (err, rowCount) => {
if (err) {
return self._handleStorageError(err, callback);
}
@ -183,9 +184,9 @@ UserService.prototype._handleStorageError = function (err, callback) {
// implements null object pattern by creating a user service like object that is always disabled.
Object.defineProperty(UserService, 'nullService', {
get: function () {
get() {
return {
isEnabled: function (callback) {
isEnabled(callback) {
callback(null, false);
}
};
@ -193,7 +194,7 @@ Object.defineProperty(UserService, 'nullService', {
});
// factory method for creating user service instance
UserService.create = function (options, previewFeatures, metrics, logger) {
UserService.create = (options, previewFeatures, metrics, logger) => {
options = options || {};
var featureEnabled = _.contains(previewFeatures, 'Users');
@ -212,12 +213,10 @@ UserService.create = function (options, previewFeatures, metrics, logger) {
};
// get provider name by provider specific user id issued by zumo
UserService.getProviderNameByUserId = function (userId) {
return _.strLeft(userId, ':');
};
UserService.getProviderNameByUserId = userId => _.strLeft(userId, ':');
// returns full name of provider for short code
UserService.getProviderNameByKey = function (key) {
UserService.getProviderNameByKey = key => {
var name = key.toLowerCase();
if (name == 'microsoft') {
name = 'MicrosoftAccount';
@ -226,7 +225,7 @@ UserService.getProviderNameByKey = function (key) {
};
// derive short code for provider from its full name
UserService.getProviderKeyByName = function (name) {
UserService.getProviderKeyByName = name => {
var key = name.toLowerCase();
if (key == 'microsoftaccount') {
key = 'microsoft';

Просмотреть файл

@ -25,7 +25,7 @@ UserStore.prototype.isEnabled = function (callback) {
top: 1
};
this.storage.query(query, this.logger, null, function (err, results) {
this.storage.query(query, this.logger, null, (err, results) => {
var tableNotFoundError = self._isTableNotFoundError(err);
// if it is an error but not the expected table found error then we're not able to determine at this time whether users feature is enabled or not
if (err && !tableNotFoundError) {
@ -45,13 +45,14 @@ UserStore.prototype.isEnabled = function (callback) {
// get user by 3rd party identity provider specific user id
UserStore.prototype.getUserByProviderId = function (provider, providerId, callback) {
var self = this,
query = {
table: tableName,
filter: provider + "Id eq '" + providerId + "'"
};
var self = this;
this.storage.query(query, this.logger, null, function (err, results) {
var query = {
table: tableName,
filter: provider + "Id eq '" + providerId + "'"
};
this.storage.query(query, this.logger, null, (err, results) => {
if (err) {
self._callErrorCallback(err, callback);
return;
@ -70,7 +71,7 @@ UserStore.prototype.getUserByProviderId = function (provider, providerId, callba
UserStore.prototype.updateUser = function (user, callback) {
var self = this;
this.storage.update(tableName, user.id, user, this.logger, null, function (err, rowCount) {
this.storage.update(tableName, user.id, user, this.logger, null, (err, rowCount) => {
if (err) {
self._callErrorCallback(err, callback);
return;
@ -82,13 +83,13 @@ UserStore.prototype.updateUser = function (user, callback) {
// create new user in the storage
UserStore.prototype.createUser = function (provider, providerId, providerProperties, callback) {
var self = this,
user = {};
var self = this;
var user = {};
user[provider + 'Id'] = providerId;
user[provider + 'Properties'] = providerProperties;
this.storage.insert(tableName, user, this.logger, null, function (err, insertedUser) {
this.storage.insert(tableName, user, this.logger, null, (err, insertedUser) => {
if (err) {
self._callErrorCallback(err, callback);
return;
@ -100,14 +101,15 @@ UserStore.prototype.createUser = function (provider, providerId, providerPropert
// get user by unique id
UserStore.prototype.getUserById = function (userId, callback) {
var self = this,
query = {
table: tableName,
filter: "id eq '" + userId + "'",
top: 1
};
var self = this;
this.storage.query(query, this.logger, null, function (err, results) {
var query = {
table: tableName,
filter: "id eq '" + userId + "'",
top: 1
};
this.storage.query(query, this.logger, null, (err, results) => {
if (err) {
self._callErrorCallback(err, callback);
return;
@ -126,7 +128,7 @@ UserStore.prototype._callErrorCallback = function (err, callback) {
}
};
UserStore.prototype._isTableNotFoundError = function (err) {
UserStore.prototype._isTableNotFoundError = err => {
var isTableNotFound = err &&
err.innerError &&
err.innerError.sqlstate === '42S02' &&