"Recursive Lambda Refactor V1"
This commit is contained in:
Родитель
9999c49f15
Коммит
83f22432d8
7750
runtime/Zumo.Node.js
7750
runtime/Zumo.Node.js
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -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' &&
|
||||
|
|
Загрузка…
Ссылка в новой задаче