Merge pull request #4267 from strongloop/update-dev-deps

Update dev dependencies + switch from "var" to "const"
This commit is contained in:
Miroslav Bajtoš 2019-10-08 08:21:20 +02:00 committed by GitHub
commit f2f0b3aa91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
98 changed files with 2194 additions and 2196 deletions

View File

@ -3,8 +3,8 @@
// This file is licensed under the MIT License. // This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
/* global module:false */
'use strict'; 'use strict';
module.exports = function(grunt) { module.exports = function(grunt) {
// Do not report warnings from unit-tests exercising deprecated paths // Do not report warnings from unit-tests exercising deprecated paths
process.env.NO_DEPRECATION = 'loopback'; process.env.NO_DEPRECATION = 'loopback';
@ -218,8 +218,8 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-karma'); grunt.loadNpmTasks('grunt-karma');
grunt.registerTask('e2e-server', function() { grunt.registerTask('e2e-server', function() {
var done = this.async(); const done = this.async();
var app = require('./test/fixtures/e2e/app'); const app = require('./test/fixtures/e2e/app');
app.listen(0, function() { app.listen(0, function() {
process.env.PORT = this.address().port; process.env.PORT = this.address().port;
done(); done();

View File

@ -8,11 +8,11 @@
*/ */
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
var loopback = require('../../lib/loopback'); const loopback = require('../../lib/loopback');
var assert = require('assert'); const assert = require('assert');
var uid = require('uid2'); const uid = require('uid2');
var DEFAULT_TOKEN_LEN = 64; const DEFAULT_TOKEN_LEN = 64;
/** /**
* Token based authentication and access control. * Token based authentication and access control.
@ -93,11 +93,11 @@ module.exports = function(AccessToken) {
*/ */
AccessToken.getIdForRequest = function(req, options) { AccessToken.getIdForRequest = function(req, options) {
options = options || {}; options = options || {};
var params = options.params || []; let params = options.params || [];
var headers = options.headers || []; let headers = options.headers || [];
var cookies = options.cookies || []; let cookies = options.cookies || [];
var i = 0; let i = 0;
var length, id; let length, id;
// https://github.com/strongloop/loopback/issues/1326 // https://github.com/strongloop/loopback/issues/1326
if (options.searchDefaultTokenKeys !== false) { if (options.searchDefaultTokenKeys !== false) {
@ -107,7 +107,7 @@ module.exports = function(AccessToken) {
} }
for (length = params.length; i < length; i++) { for (length = params.length; i < length; i++) {
var param = params[i]; const param = params[i];
// replacement for deprecated req.param() // replacement for deprecated req.param()
id = req.params && req.params[param] !== undefined ? req.params[param] : id = req.params && req.params[param] !== undefined ? req.params[param] :
req.body && req.body[param] !== undefined ? req.body[param] : req.body && req.body[param] !== undefined ? req.body[param] :
@ -134,7 +134,7 @@ module.exports = function(AccessToken) {
id = id.substring(7); id = id.substring(7);
if (options.bearerTokenBase64Encoded) { if (options.bearerTokenBase64Encoded) {
// Decode from base64 // Decode from base64
var buf = new Buffer(id, 'base64'); const buf = new Buffer(id, 'base64');
id = buf.toString('utf8'); id = buf.toString('utf8');
} }
} else if (/^Basic /i.test(id)) { } else if (/^Basic /i.test(id)) {
@ -147,7 +147,7 @@ module.exports = function(AccessToken) {
// "a2b2c3:" (curl http://a2b2c3@localhost:3000/) // "a2b2c3:" (curl http://a2b2c3@localhost:3000/)
// "token:a2b2c3" (curl http://token:a2b2c3@localhost:3000/) // "token:a2b2c3" (curl http://token:a2b2c3@localhost:3000/)
// ":a2b2c3" // ":a2b2c3"
var parts = /^([^:]*):(.*)$/.exec(id); const parts = /^([^:]*):(.*)$/.exec(id);
if (parts) { if (parts) {
id = parts[2].length > parts[1].length ? parts[2] : parts[1]; id = parts[2].length > parts[1].length ? parts[2] : parts[1];
} }
@ -186,7 +186,7 @@ module.exports = function(AccessToken) {
} else if (isValid) { } else if (isValid) {
cb(null, token); cb(null, token);
} else { } else {
var e = new Error(g.f('Invalid Access Token')); const e = new Error(g.f('Invalid Access Token'));
e.status = e.statusCode = 401; e.status = e.statusCode = 401;
e.code = 'INVALID_TOKEN'; e.code = 'INVALID_TOKEN';
cb(e); cb(e);
@ -213,7 +213,7 @@ module.exports = function(AccessToken) {
options = {}; options = {};
} }
var id = this.getIdForRequest(req, options); const id = this.getIdForRequest(req, options);
if (id) { if (id) {
this.resolve(id, cb); this.resolve(id, cb);
@ -239,9 +239,9 @@ module.exports = function(AccessToken) {
assert(this.ttl, 'token.ttl must exist'); assert(this.ttl, 'token.ttl must exist');
assert(this.ttl >= -1, 'token.ttl must be >= -1'); assert(this.ttl >= -1, 'token.ttl must be >= -1');
var AccessToken = this.constructor; const AccessToken = this.constructor;
var userRelation = AccessToken.relations.user; // may not be set up const userRelation = AccessToken.relations.user; // may not be set up
var User = userRelation && userRelation.modelTo; let User = userRelation && userRelation.modelTo;
// redefine user model if accessToken's principalType is available // redefine user model if accessToken's principalType is available
if (this.principalType) { if (this.principalType) {
@ -253,13 +253,13 @@ module.exports = function(AccessToken) {
} }
} }
var now = Date.now(); const now = Date.now();
var created = this.created.getTime(); const created = this.created.getTime();
var elapsedSeconds = (now - created) / 1000; const elapsedSeconds = (now - created) / 1000;
var secondsToLive = this.ttl; const secondsToLive = this.ttl;
var eternalTokensAllowed = !!(User && User.settings.allowEternalTokens); const eternalTokensAllowed = !!(User && User.settings.allowEternalTokens);
var isEternalToken = secondsToLive === -1; const isEternalToken = secondsToLive === -1;
var isValid = isEternalToken ? const isValid = isEternalToken ?
eternalTokensAllowed : eternalTokensAllowed :
elapsedSeconds < secondsToLive; elapsedSeconds < secondsToLive;

View File

@ -30,20 +30,20 @@
Map to oAuth 2.0 scopes Map to oAuth 2.0 scopes
*/ */
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
var loopback = require('../../lib/loopback'); const loopback = require('../../lib/loopback');
var utils = require('../../lib/utils'); const utils = require('../../lib/utils');
var async = require('async'); const async = require('async');
var extend = require('util')._extend; const extend = require('util')._extend;
var assert = require('assert'); const assert = require('assert');
var debug = require('debug')('loopback:security:acl'); const debug = require('debug')('loopback:security:acl');
var ctx = require('../../lib/access-context'); const ctx = require('../../lib/access-context');
var AccessContext = ctx.AccessContext; const AccessContext = ctx.AccessContext;
var Principal = ctx.Principal; const Principal = ctx.Principal;
var AccessRequest = ctx.AccessRequest; const AccessRequest = ctx.AccessRequest;
var Role = loopback.Role; const Role = loopback.Role;
assert(Role, 'Role model must be defined before ACL model'); assert(Role, 'Role model must be defined before ACL model');
/** /**
@ -107,18 +107,18 @@ module.exports = function(ACL) {
* @returns {Number} * @returns {Number}
*/ */
ACL.getMatchingScore = function getMatchingScore(rule, req) { ACL.getMatchingScore = function getMatchingScore(rule, req) {
var props = ['model', 'property', 'accessType']; const props = ['model', 'property', 'accessType'];
var score = 0; let score = 0;
for (var i = 0; i < props.length; i++) { for (let i = 0; i < props.length; i++) {
// Shift the score by 4 for each of the properties as the weight // Shift the score by 4 for each of the properties as the weight
score = score * 4; score = score * 4;
var ruleValue = rule[props[i]] || ACL.ALL; const ruleValue = rule[props[i]] || ACL.ALL;
var requestedValue = req[props[i]] || ACL.ALL; const requestedValue = req[props[i]] || ACL.ALL;
var isMatchingMethodName = props[i] === 'property' && const isMatchingMethodName = props[i] === 'property' &&
req.methodNames.indexOf(ruleValue) !== -1; req.methodNames.indexOf(ruleValue) !== -1;
var isMatchingAccessType = ruleValue === requestedValue; let isMatchingAccessType = ruleValue === requestedValue;
if (props[i] === 'accessType' && !isMatchingAccessType) { if (props[i] === 'accessType' && !isMatchingAccessType) {
switch (ruleValue) { switch (ruleValue) {
case ACL.EXECUTE: case ACL.EXECUTE:
@ -219,11 +219,11 @@ module.exports = function(ACL) {
acls = acls.sort(function(rule1, rule2) { acls = acls.sort(function(rule1, rule2) {
return ACL.getMatchingScore(rule2, req) - ACL.getMatchingScore(rule1, req); return ACL.getMatchingScore(rule2, req) - ACL.getMatchingScore(rule1, req);
}); });
var permission = ACL.DEFAULT; let permission = ACL.DEFAULT;
var score = 0; let score = 0;
for (var i = 0; i < acls.length; i++) { for (let i = 0; i < acls.length; i++) {
var candidate = acls[i]; const candidate = acls[i];
score = ACL.getMatchingScore(candidate, req); score = ACL.getMatchingScore(candidate, req);
if (score < 0) { if (score < 0) {
// the highest scored ACL did not match // the highest scored ACL did not match
@ -239,8 +239,8 @@ module.exports = function(ACL) {
break; break;
} }
// For wildcard match, find the strongest permission // For wildcard match, find the strongest permission
var candidateOrder = AccessContext.permissionOrder[candidate.permission]; const candidateOrder = AccessContext.permissionOrder[candidate.permission];
var permissionOrder = AccessContext.permissionOrder[permission]; const permissionOrder = AccessContext.permissionOrder[permission];
if (candidateOrder > permissionOrder) { if (candidateOrder > permissionOrder) {
permission = candidate.permission; permission = candidate.permission;
break; break;
@ -255,7 +255,7 @@ module.exports = function(ACL) {
debug('with score:', acl.score(req)); debug('with score:', acl.score(req));
}); });
} }
var res = new AccessRequest({ const res = new AccessRequest({
model: req.model, model: req.model,
property: req.property, property: req.property,
accessType: req.accessType, accessType: req.accessType,
@ -276,11 +276,11 @@ module.exports = function(ACL) {
* @return {Object[]} An array of ACLs * @return {Object[]} An array of ACLs
*/ */
ACL.getStaticACLs = function getStaticACLs(model, property) { ACL.getStaticACLs = function getStaticACLs(model, property) {
var modelClass = this.registry.findModel(model); const modelClass = this.registry.findModel(model);
var staticACLs = []; const staticACLs = [];
if (modelClass && modelClass.settings.acls) { if (modelClass && modelClass.settings.acls) {
modelClass.settings.acls.forEach(function(acl) { modelClass.settings.acls.forEach(function(acl) {
var prop = acl.property; let prop = acl.property;
// We support static ACL property with array of string values. // We support static ACL property with array of string values.
if (Array.isArray(prop) && prop.indexOf(property) >= 0) if (Array.isArray(prop) && prop.indexOf(property) >= 0)
prop = property; prop = property;
@ -296,7 +296,7 @@ module.exports = function(ACL) {
} }
}); });
} }
var prop = modelClass && ( const prop = modelClass && (
// regular property // regular property
modelClass.definition.properties[property] || modelClass.definition.properties[property] ||
// relation/scope // relation/scope
@ -339,17 +339,17 @@ module.exports = function(ACL) {
principalId = principalId.toString(); principalId = principalId.toString();
} }
property = property || ACL.ALL; property = property || ACL.ALL;
var propertyQuery = (property === ACL.ALL) ? undefined : {inq: [property, ACL.ALL]}; const propertyQuery = (property === ACL.ALL) ? undefined : {inq: [property, ACL.ALL]};
accessType = accessType || ACL.ALL; accessType = accessType || ACL.ALL;
var accessTypeQuery = (accessType === ACL.ALL) ? undefined : const accessTypeQuery = (accessType === ACL.ALL) ? undefined :
{inq: [accessType, ACL.ALL, ACL.EXECUTE]}; {inq: [accessType, ACL.ALL, ACL.EXECUTE]};
var req = new AccessRequest({model, property, accessType, registry: this.registry}); const req = new AccessRequest({model, property, accessType, registry: this.registry});
var acls = this.getStaticACLs(model, property); let acls = this.getStaticACLs(model, property);
// resolved is an instance of AccessRequest // resolved is an instance of AccessRequest
var resolved = this.resolvePermission(acls, req); let resolved = this.resolvePermission(acls, req);
if (resolved && resolved.permission === ACL.DENY) { if (resolved && resolved.permission === ACL.DENY) {
debug('Permission denied by statically resolved permission'); debug('Permission denied by statically resolved permission');
@ -360,7 +360,7 @@ module.exports = function(ACL) {
return callback.promise; return callback.promise;
} }
var self = this; const self = this;
this.find({where: {principalType: principalType, principalId: principalId, this.find({where: {principalType: principalType, principalId: principalId,
model: model, property: propertyQuery, accessType: accessTypeQuery}}, model: model, property: propertyQuery, accessType: accessTypeQuery}},
function(err, dynACLs) { function(err, dynACLs) {
@ -431,33 +431,33 @@ module.exports = function(ACL) {
*/ */
ACL.checkAccessForContext = function(context, callback) { ACL.checkAccessForContext = function(context, callback) {
if (!callback) callback = utils.createPromiseCallback(); if (!callback) callback = utils.createPromiseCallback();
var self = this; const self = this;
self.resolveRelatedModels(); self.resolveRelatedModels();
var roleModel = self.roleModel; const roleModel = self.roleModel;
if (!(context instanceof AccessContext)) { if (!(context instanceof AccessContext)) {
context.registry = this.registry; context.registry = this.registry;
context = new AccessContext(context); context = new AccessContext(context);
} }
var authorizedRoles = {}; let authorizedRoles = {};
var remotingContext = context.remotingContext; const remotingContext = context.remotingContext;
var model = context.model; const model = context.model;
var modelDefaultPermission = model && model.settings.defaultPermission; const modelDefaultPermission = model && model.settings.defaultPermission;
var property = context.property; const property = context.property;
var accessType = context.accessType; const accessType = context.accessType;
var modelName = context.modelName; const modelName = context.modelName;
var methodNames = context.methodNames; const methodNames = context.methodNames;
var propertyQuery = (property === ACL.ALL) ? undefined : {inq: methodNames.concat([ACL.ALL])}; const propertyQuery = (property === ACL.ALL) ? undefined : {inq: methodNames.concat([ACL.ALL])};
var accessTypeQuery = (accessType === ACL.ALL) ? const accessTypeQuery = (accessType === ACL.ALL) ?
undefined : undefined :
(accessType === ACL.REPLICATE) ? (accessType === ACL.REPLICATE) ?
{inq: [ACL.REPLICATE, ACL.WRITE, ACL.ALL]} : {inq: [ACL.REPLICATE, ACL.WRITE, ACL.ALL]} :
{inq: [accessType, ACL.ALL]}; {inq: [accessType, ACL.ALL]};
var req = new AccessRequest({ const req = new AccessRequest({
model: modelName, model: modelName,
property, property,
accessType, accessType,
@ -475,8 +475,8 @@ module.exports = function(ACL) {
return callback.promise; return callback.promise;
} }
var effectiveACLs = []; const effectiveACLs = [];
var staticACLs = self.getStaticACLs(model.modelName, property); const staticACLs = self.getStaticACLs(model.modelName, property);
const query = { const query = {
where: { where: {
@ -488,16 +488,16 @@ module.exports = function(ACL) {
this.find(query, function(err, acls) { this.find(query, function(err, acls) {
if (err) return callback(err); if (err) return callback(err);
var inRoleTasks = []; const inRoleTasks = [];
acls = acls.concat(staticACLs); acls = acls.concat(staticACLs);
acls.forEach(function(acl) { acls.forEach(function(acl) {
// Check exact matches // Check exact matches
for (var i = 0; i < context.principals.length; i++) { for (let i = 0; i < context.principals.length; i++) {
var p = context.principals[i]; const p = context.principals[i];
var typeMatch = p.type === acl.principalType; const typeMatch = p.type === acl.principalType;
var idMatch = String(p.id) === String(acl.principalId); const idMatch = String(p.id) === String(acl.principalId);
if (typeMatch && idMatch) { if (typeMatch && idMatch) {
effectiveACLs.push(acl); effectiveACLs.push(acl);
return; return;
@ -525,7 +525,7 @@ module.exports = function(ACL) {
if (err) return callback(err, null); if (err) return callback(err, null);
// resolved is an instance of AccessRequest // resolved is an instance of AccessRequest
var resolved = self.resolvePermission(effectiveACLs, req); const resolved = self.resolvePermission(effectiveACLs, req);
debug('---Resolved---'); debug('---Resolved---');
resolved.debug(); resolved.debug();
@ -562,7 +562,7 @@ module.exports = function(ACL) {
ACL.checkAccessForToken = function(token, model, modelId, method, callback) { ACL.checkAccessForToken = function(token, model, modelId, method, callback) {
assert(token, 'Access token is required'); assert(token, 'Access token is required');
if (!callback) callback = utils.createPromiseCallback(); if (!callback) callback = utils.createPromiseCallback();
var context = new AccessContext({ const context = new AccessContext({
registry: this.registry, registry: this.registry,
accessToken: token, accessToken: token,
model: model, model: model,
@ -580,7 +580,7 @@ module.exports = function(ACL) {
ACL.resolveRelatedModels = function() { ACL.resolveRelatedModels = function() {
if (!this.roleModel) { if (!this.roleModel) {
var reg = this.registry; const reg = this.registry;
this.roleModel = reg.getModelByType('Role'); this.roleModel = reg.getModelByType('Role');
this.roleMappingModel = reg.getModelByType('RoleMapping'); this.roleMappingModel = reg.getModelByType('RoleMapping');
this.userModel = reg.getModelByType('User'); this.userModel = reg.getModelByType('User');
@ -617,7 +617,7 @@ module.exports = function(ACL) {
break; break;
default: default:
// try resolving a user model with a name matching the principalType // try resolving a user model with a name matching the principalType
var userModel = this.registry.findModel(type); const userModel = this.registry.findModel(type);
if (userModel) { if (userModel) {
userModel.findOne( userModel.findOne(
{where: {or: [{username: id}, {email: id}, {id: id}]}}, {where: {or: [{username: id}, {email: id}, {id: id}]}},
@ -625,7 +625,7 @@ module.exports = function(ACL) {
); );
} else { } else {
process.nextTick(function() { process.nextTick(function() {
var err = new Error(g.f('Invalid principal type: %s', type)); const err = new Error(g.f('Invalid principal type: %s', type));
err.statusCode = 400; err.statusCode = 400;
err.code = 'INVALID_PRINCIPAL_TYPE'; err.code = 'INVALID_PRINCIPAL_TYPE';
cb(err); cb(err);
@ -646,7 +646,7 @@ module.exports = function(ACL) {
*/ */
ACL.isMappedToRole = function(principalType, principalId, role, cb) { ACL.isMappedToRole = function(principalType, principalId, role, cb) {
cb = cb || utils.createPromiseCallback(); cb = cb || utils.createPromiseCallback();
var self = this; const self = this;
this.resolvePrincipal(principalType, principalId, this.resolvePrincipal(principalType, principalId,
function(err, principal) { function(err, principal) {
if (err) return cb(err); if (err) return cb(err);

View File

@ -4,23 +4,23 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var utils = require('../../lib/utils'); const utils = require('../../lib/utils');
/*! /*!
* Application management functions * Application management functions
*/ */
var crypto = require('crypto'); const crypto = require('crypto');
function generateKey(hmacKey, algorithm, encoding) { function generateKey(hmacKey, algorithm, encoding) {
hmacKey = hmacKey || 'loopback'; hmacKey = hmacKey || 'loopback';
algorithm = algorithm || 'sha1'; algorithm = algorithm || 'sha1';
encoding = encoding || 'hex'; encoding = encoding || 'hex';
var hmac = crypto.createHmac(algorithm, hmacKey); const hmac = crypto.createHmac(algorithm, hmacKey);
var buf = crypto.randomBytes(32); const buf = crypto.randomBytes(32);
hmac.update(buf); hmac.update(buf);
var key = hmac.digest(encoding); const key = hmac.digest(encoding);
return key; return key;
} }
@ -83,7 +83,7 @@ module.exports = function(Application) {
return next(); return next();
} }
var app = ctx.instance; const app = ctx.instance;
app.created = app.modified = new Date(); app.created = app.modified = new Date();
if (!app.id) { if (!app.id) {
app.id = generateKey('id', 'md5'); app.id = generateKey('id', 'md5');
@ -115,8 +115,8 @@ module.exports = function(Application) {
} }
cb = cb || utils.createPromiseCallback(); cb = cb || utils.createPromiseCallback();
var props = {owner: owner, name: name}; const props = {owner: owner, name: name};
for (var p in options) { for (const p in options) {
if (!(p in props)) { if (!(p in props)) {
props[p] = options[p]; props[p] = options[p];
} }
@ -182,9 +182,9 @@ module.exports = function(Application) {
cb(err, null); cb(err, null);
return cb.promise; return cb.promise;
} }
var result = null; let result = null;
var keyNames = ['clientKey', 'javaScriptKey', 'restApiKey', 'windowsKey', 'masterKey']; const keyNames = ['clientKey', 'javaScriptKey', 'restApiKey', 'windowsKey', 'masterKey'];
for (var i = 0; i < keyNames.length; i++) { for (let i = 0; i < keyNames.length; i++) {
if (app[keyNames[i]] === key) { if (app[keyNames[i]] === key) {
result = { result = {
application: app, application: app,

View File

@ -8,15 +8,15 @@
*/ */
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
var PersistedModel = require('../../lib/loopback').PersistedModel; const PersistedModel = require('../../lib/loopback').PersistedModel;
var loopback = require('../../lib/loopback'); const loopback = require('../../lib/loopback');
var utils = require('../../lib/utils'); const utils = require('../../lib/utils');
var crypto = require('crypto'); const crypto = require('crypto');
var CJSON = {stringify: require('canonical-json')}; const CJSON = {stringify: require('canonical-json')};
var async = require('async'); const async = require('async');
var assert = require('assert'); const assert = require('assert');
var debug = require('debug')('loopback:change'); const debug = require('debug')('loopback:change');
/** /**
* Change list entry. * Change list entry.
@ -58,10 +58,10 @@ module.exports = function(Change) {
Change.setup = function() { Change.setup = function() {
PersistedModel.setup.call(this); PersistedModel.setup.call(this);
var Change = this; const Change = this;
Change.getter.id = function() { Change.getter.id = function() {
var hasModel = this.modelName && this.modelId; const hasModel = this.modelName && this.modelId;
if (!hasModel) return null; if (!hasModel) return null;
return Change.idForModel(this.modelName, this.modelId); return Change.idForModel(this.modelName, this.modelId);
@ -80,12 +80,12 @@ module.exports = function(Change) {
*/ */
Change.rectifyModelChanges = function(modelName, modelIds, callback) { Change.rectifyModelChanges = function(modelName, modelIds, callback) {
var Change = this; const Change = this;
var errors = []; const errors = [];
callback = callback || utils.createPromiseCallback(); callback = callback || utils.createPromiseCallback();
var tasks = modelIds.map(function(id) { const tasks = modelIds.map(function(id) {
return function(cb) { return function(cb) {
Change.findOrCreateChange(modelName, id, function(err, change) { Change.findOrCreateChange(modelName, id, function(err, change) {
if (err) return next(err); if (err) return next(err);
@ -106,13 +106,13 @@ module.exports = function(Change) {
async.parallel(tasks, function(err) { async.parallel(tasks, function(err) {
if (err) return callback(err); if (err) return callback(err);
if (errors.length) { if (errors.length) {
var desc = errors const desc = errors
.map(function(e) { .map(function(e) {
return '#' + e.modelId + ' - ' + e.toString(); return '#' + e.modelId + ' - ' + e.toString();
}) })
.join('\n'); .join('\n');
var msg = g.f('Cannot rectify %s changes:\n%s', modelName, desc); const msg = g.f('Cannot rectify %s changes:\n%s', modelName, desc);
err = new Error(msg); err = new Error(msg);
err.details = {errors: errors}; err.details = {errors: errors};
return callback(err); return callback(err);
@ -148,15 +148,15 @@ module.exports = function(Change) {
Change.findOrCreateChange = function(modelName, modelId, callback) { Change.findOrCreateChange = function(modelName, modelId, callback) {
assert(this.registry.findModel(modelName), modelName + ' does not exist'); assert(this.registry.findModel(modelName), modelName + ' does not exist');
callback = callback || utils.createPromiseCallback(); callback = callback || utils.createPromiseCallback();
var id = this.idForModel(modelName, modelId); const id = this.idForModel(modelName, modelId);
var Change = this; const Change = this;
this.findById(id, function(err, change) { this.findById(id, function(err, change) {
if (err) return callback(err); if (err) return callback(err);
if (change) { if (change) {
callback(null, change); callback(null, change);
} else { } else {
var ch = new Change({ const ch = new Change({
id: id, id: id,
modelName: modelName, modelName: modelName,
modelId: modelId, modelId: modelId,
@ -177,8 +177,8 @@ module.exports = function(Change) {
*/ */
Change.prototype.rectify = function(cb) { Change.prototype.rectify = function(cb) {
var change = this; const change = this;
var currentRev = this.rev; const currentRev = this.rev;
change.debug('rectify change'); change.debug('rectify change');
@ -274,8 +274,8 @@ module.exports = function(Change) {
Change.prototype.currentRevision = function(cb) { Change.prototype.currentRevision = function(cb) {
cb = cb || utils.createPromiseCallback(); cb = cb || utils.createPromiseCallback();
var model = this.getModelCtor(); const model = this.getModelCtor();
var id = this.getModelId(); const id = this.getModelId();
model.findById(id, function(err, inst) { model.findById(id, function(err, inst) {
if (err) return cb(err); if (err) return cb(err);
if (inst) { if (inst) {
@ -345,8 +345,8 @@ module.exports = function(Change) {
Change.prototype.equals = function(change) { Change.prototype.equals = function(change) {
if (!change) return false; if (!change) return false;
var thisRev = this.rev || null; const thisRev = this.rev || null;
var thatRev = change.rev || null; const thatRev = change.rev || null;
return thisRev === thatRev; return thisRev === thatRev;
}; };
@ -423,8 +423,8 @@ module.exports = function(Change) {
callback(null, {deltas: [], conflicts: []}); callback(null, {deltas: [], conflicts: []});
return callback.promise; return callback.promise;
} }
var remoteChangeIndex = {}; const remoteChangeIndex = {};
var modelIds = []; const modelIds = [];
remoteChanges.forEach(function(ch) { remoteChanges.forEach(function(ch) {
modelIds.push(ch.modelId); modelIds.push(ch.modelId);
remoteChangeIndex[ch.modelId] = new Change(ch); remoteChangeIndex[ch.modelId] = new Change(ch);
@ -439,18 +439,18 @@ module.exports = function(Change) {
}, },
}, function(err, allLocalChanges) { }, function(err, allLocalChanges) {
if (err) return callback(err); if (err) return callback(err);
var deltas = []; const deltas = [];
var conflicts = []; const conflicts = [];
var localModelIds = []; const localModelIds = [];
var localChanges = allLocalChanges.filter(function(c) { const localChanges = allLocalChanges.filter(function(c) {
return c.checkpoint >= since; return c.checkpoint >= since;
}); });
localChanges.forEach(function(localChange) { localChanges.forEach(function(localChange) {
localChange = new Change(localChange); localChange = new Change(localChange);
localModelIds.push(localChange.modelId); localModelIds.push(localChange.modelId);
var remoteChange = remoteChangeIndex[localChange.modelId]; const remoteChange = remoteChangeIndex[localChange.modelId];
if (remoteChange && !localChange.equals(remoteChange)) { if (remoteChange && !localChange.equals(remoteChange)) {
if (remoteChange.conflictsWith(localChange)) { if (remoteChange.conflictsWith(localChange)) {
remoteChange.debug('remote conflict'); remoteChange.debug('remote conflict');
@ -466,8 +466,8 @@ module.exports = function(Change) {
modelIds.forEach(function(id) { modelIds.forEach(function(id) {
if (localModelIds.indexOf(id) !== -1) return; if (localModelIds.indexOf(id) !== -1) return;
var d = remoteChangeIndex[id]; const d = remoteChangeIndex[id];
var oldChange = allLocalChanges.filter(function(c) { const oldChange = allLocalChanges.filter(function(c) {
return c.modelId === id; return c.modelId === id;
})[0]; })[0];
@ -495,7 +495,7 @@ module.exports = function(Change) {
Change.rectifyAll = function(cb) { Change.rectifyAll = function(cb) {
debug('rectify all'); debug('rectify all');
var Change = this; const Change = this;
// this should be optimized // this should be optimized
this.find(function(err, changes) { this.find(function(err, changes) {
if (err) return cb(err); if (err) return cb(err);
@ -513,7 +513,7 @@ module.exports = function(Change) {
*/ */
Change.getCheckpointModel = function() { Change.getCheckpointModel = function() {
var checkpointModel = this.Checkpoint; let checkpointModel = this.Checkpoint;
if (checkpointModel) return checkpointModel; if (checkpointModel) return checkpointModel;
// FIXME(bajtos) This code creates multiple different models with the same // FIXME(bajtos) This code creates multiple different models with the same
// model name, which is not a valid supported usage of juggler's API. // model name, which is not a valid supported usage of juggler's API.
@ -526,7 +526,7 @@ module.exports = function(Change) {
Change.prototype.debug = function() { Change.prototype.debug = function() {
if (debug.enabled) { if (debug.enabled) {
var args = Array.prototype.slice.call(arguments); const args = Array.prototype.slice.call(arguments);
args[0] = args[0] + ' %s'; args[0] = args[0] + ' %s';
args.push(this.modelName); args.push(this.modelName);
debug.apply(this, args); debug.apply(this, args);
@ -551,16 +551,16 @@ module.exports = function(Change) {
Change.prototype.getModelId = function() { Change.prototype.getModelId = function() {
// TODO(ritch) get rid of the need to create an instance // TODO(ritch) get rid of the need to create an instance
var Model = this.getModelCtor(); const Model = this.getModelCtor();
var id = this.modelId; const id = this.modelId;
var m = new Model(); const m = new Model();
m.setId(id); m.setId(id);
return m.getId(); return m.getId();
}; };
Change.prototype.getModel = function(callback) { Change.prototype.getModel = function(callback) {
var Model = this.constructor.settings.trackModel; const Model = this.constructor.settings.trackModel;
var id = this.getModelId(); const id = this.getModelId();
Model.findById(id, callback); Model.findById(id, callback);
}; };
@ -595,10 +595,10 @@ module.exports = function(Change) {
*/ */
Conflict.prototype.models = function(cb) { Conflict.prototype.models = function(cb) {
var conflict = this; const conflict = this;
var SourceModel = this.SourceModel; const SourceModel = this.SourceModel;
var TargetModel = this.TargetModel; const TargetModel = this.TargetModel;
var source, target; let source, target;
async.parallel([ async.parallel([
getSourceModel, getSourceModel,
@ -637,8 +637,8 @@ module.exports = function(Change) {
*/ */
Conflict.prototype.changes = function(cb) { Conflict.prototype.changes = function(cb) {
var conflict = this; const conflict = this;
var sourceChange, targetChange; let sourceChange, targetChange;
async.parallel([ async.parallel([
getSourceChange, getSourceChange,
@ -646,7 +646,7 @@ module.exports = function(Change) {
], done); ], done);
function getSourceChange(cb) { function getSourceChange(cb) {
var SourceModel = conflict.SourceModel; const SourceModel = conflict.SourceModel;
SourceModel.findLastChange(conflict.modelId, function(err, change) { SourceModel.findLastChange(conflict.modelId, function(err, change) {
if (err) return cb(err); if (err) return cb(err);
sourceChange = change; sourceChange = change;
@ -655,7 +655,7 @@ module.exports = function(Change) {
} }
function getTargetChange(cb) { function getTargetChange(cb) {
var TargetModel = conflict.TargetModel; const TargetModel = conflict.TargetModel;
TargetModel.findLastChange(conflict.modelId, function(err, change) { TargetModel.findLastChange(conflict.modelId, function(err, change) {
if (err) return cb(err); if (err) return cb(err);
targetChange = change; targetChange = change;
@ -684,7 +684,7 @@ module.exports = function(Change) {
*/ */
Conflict.prototype.resolve = function(cb) { Conflict.prototype.resolve = function(cb) {
var conflict = this; const conflict = this;
conflict.TargetModel.findLastChange( conflict.TargetModel.findLastChange(
this.modelId, this.modelId,
function(err, targetChange) { function(err, targetChange) {
@ -718,14 +718,14 @@ module.exports = function(Change) {
* @param {Error} err * @param {Error} err
*/ */
Conflict.prototype.resolveUsingTarget = function(cb) { Conflict.prototype.resolveUsingTarget = function(cb) {
var conflict = this; const conflict = this;
conflict.models(function(err, source, target) { conflict.models(function(err, source, target) {
if (err) return done(err); if (err) return done(err);
if (target === null) { if (target === null) {
return conflict.SourceModel.deleteById(conflict.modelId, done); return conflict.SourceModel.deleteById(conflict.modelId, done);
} }
var inst = new conflict.SourceModel( const inst = new conflict.SourceModel(
target.toObject(), target.toObject(),
{persisted: true} {persisted: true}
); );
@ -751,7 +751,7 @@ module.exports = function(Change) {
* @returns {Conflict} A new Conflict instance. * @returns {Conflict} A new Conflict instance.
*/ */
Conflict.prototype.swapParties = function() { Conflict.prototype.swapParties = function() {
var Ctor = this.constructor; const Ctor = this.constructor;
return new Ctor(this.modelId, this.TargetModel, this.SourceModel); return new Ctor(this.modelId, this.TargetModel, this.SourceModel);
}; };
@ -765,14 +765,14 @@ module.exports = function(Change) {
*/ */
Conflict.prototype.resolveManually = function(data, cb) { Conflict.prototype.resolveManually = function(data, cb) {
var conflict = this; const conflict = this;
if (!data) { if (!data) {
return conflict.SourceModel.deleteById(conflict.modelId, done); return conflict.SourceModel.deleteById(conflict.modelId, done);
} }
conflict.models(function(err, source, target) { conflict.models(function(err, source, target) {
if (err) return done(err); if (err) return done(err);
var inst = source || new conflict.SourceModel(target); const inst = source || new conflict.SourceModel(target);
inst.setAttributes(data); inst.setAttributes(data);
inst.save(function(err) { inst.save(function(err) {
if (err) return done(err); if (err) return done(err);
@ -801,11 +801,11 @@ module.exports = function(Change) {
*/ */
Conflict.prototype.type = function(cb) { Conflict.prototype.type = function(cb) {
var conflict = this; const conflict = this;
this.changes(function(err, sourceChange, targetChange) { this.changes(function(err, sourceChange, targetChange) {
if (err) return cb(err); if (err) return cb(err);
var sourceChangeType = sourceChange.type(); const sourceChangeType = sourceChange.type();
var targetChangeType = targetChange.type(); const targetChangeType = targetChange.type();
if (sourceChangeType === Change.UPDATE && targetChangeType === Change.UPDATE) { if (sourceChangeType === Change.UPDATE && targetChangeType === Change.UPDATE) {
return cb(null, Change.UPDATE); return cb(null, Change.UPDATE);
} }

View File

@ -8,7 +8,7 @@
*/ */
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
/** /**
* Checkpoint list entry. * Checkpoint list entry.
@ -35,15 +35,15 @@ module.exports = function(Checkpoint) {
* @param {Number} checkpoint The current checkpoint seq * @param {Number} checkpoint The current checkpoint seq
*/ */
Checkpoint.current = function(cb) { Checkpoint.current = function(cb) {
var Checkpoint = this; const Checkpoint = this;
Checkpoint._getSingleton(function(err, cp) { Checkpoint._getSingleton(function(err, cp) {
cb(err, cp.seq); cb(err, cp.seq);
}); });
}; };
Checkpoint._getSingleton = function(cb) { Checkpoint._getSingleton = function(cb) {
var query = {limit: 1}; // match all instances, return only one const query = {limit: 1}; // match all instances, return only one
var initialData = {seq: 1}; const initialData = {seq: 1};
this.findOrCreate(query, initialData, cb); this.findOrCreate(query, initialData, cb);
}; };
@ -54,10 +54,10 @@ module.exports = function(Checkpoint) {
* @param {Object} checkpoint The current checkpoint * @param {Object} checkpoint The current checkpoint
*/ */
Checkpoint.bumpLastSeq = function(cb) { Checkpoint.bumpLastSeq = function(cb) {
var Checkpoint = this; const Checkpoint = this;
Checkpoint._getSingleton(function(err, cp) { Checkpoint._getSingleton(function(err, cp) {
if (err) return cb(err); if (err) return cb(err);
var originalSeq = cp.seq; const originalSeq = cp.seq;
cp.seq++; cp.seq++;
// Update the checkpoint but only if it was not changed under our hands // Update the checkpoint but only if it was not changed under our hands
Checkpoint.updateAll({id: cp.id, seq: originalSeq}, {seq: cp.seq}, function(err, info) { Checkpoint.updateAll({id: cp.id, seq: originalSeq}, {seq: cp.seq}, function(err, info) {

View File

@ -4,7 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
/** /**
* Email model. Extends LoopBack base [Model](#model-new-model). * Email model. Extends LoopBack base [Model](#model-new-model).

View File

@ -4,7 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
/** /**
* Data model for key-value databases. * Data model for key-value databases.
@ -233,10 +233,10 @@ function throwNotAttached(modelName, methodName) {
function convertNullToNotFoundError(ctx, cb) { function convertNullToNotFoundError(ctx, cb) {
if (ctx.result !== null) return cb(); if (ctx.result !== null) return cb();
var modelName = ctx.method.sharedClass.name; const modelName = ctx.method.sharedClass.name;
var id = ctx.getArgByName('id'); const id = ctx.getArgByName('id');
var msg = g.f('Unknown "%s" {{key}} "%s".', modelName, id); const msg = g.f('Unknown "%s" {{key}} "%s".', modelName, id);
var error = new Error(msg); const error = new Error(msg);
error.statusCode = error.status = 404; error.statusCode = error.status = 404;
error.code = 'KEY_NOT_FOUND'; error.code = 'KEY_NOT_FOUND';
cb(error); cb(error);

View File

@ -4,8 +4,8 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../lib/loopback'); const loopback = require('../../lib/loopback');
var utils = require('../../lib/utils'); const utils = require('../../lib/utils');
/** /**
* The `RoleMapping` model extends from the built in `loopback.Model` type. * The `RoleMapping` model extends from the built in `loopback.Model` type.
@ -26,7 +26,7 @@ module.exports = function(RoleMapping) {
RoleMapping.resolveRelatedModels = function() { RoleMapping.resolveRelatedModels = function() {
if (!this.userModel) { if (!this.userModel) {
var reg = this.registry; const reg = this.registry;
this.roleModel = reg.getModelByType('Role'); this.roleModel = reg.getModelByType('Role');
this.userModel = reg.getModelByType('User'); this.userModel = reg.getModelByType('User');
this.applicationModel = reg.getModelByType('Application'); this.applicationModel = reg.getModelByType('Application');
@ -44,7 +44,7 @@ module.exports = function(RoleMapping) {
this.constructor.resolveRelatedModels(); this.constructor.resolveRelatedModels();
if (this.principalType === RoleMapping.APPLICATION) { if (this.principalType === RoleMapping.APPLICATION) {
var applicationModel = this.constructor.applicationModel; const applicationModel = this.constructor.applicationModel;
applicationModel.findById(this.principalId, callback); applicationModel.findById(this.principalId, callback);
} else { } else {
process.nextTick(function() { process.nextTick(function() {
@ -63,7 +63,7 @@ module.exports = function(RoleMapping) {
RoleMapping.prototype.user = function(callback) { RoleMapping.prototype.user = function(callback) {
callback = callback || utils.createPromiseCallback(); callback = callback || utils.createPromiseCallback();
this.constructor.resolveRelatedModels(); this.constructor.resolveRelatedModels();
var userModel; let userModel;
if (this.principalType === RoleMapping.USER) { if (this.principalType === RoleMapping.USER) {
userModel = this.constructor.userModel; userModel = this.constructor.userModel;
@ -94,7 +94,7 @@ module.exports = function(RoleMapping) {
this.constructor.resolveRelatedModels(); this.constructor.resolveRelatedModels();
if (this.principalType === RoleMapping.ROLE) { if (this.principalType === RoleMapping.ROLE) {
var roleModel = this.constructor.roleModel; const roleModel = this.constructor.roleModel;
roleModel.findById(this.principalId, callback); roleModel.findById(this.principalId, callback);
} else { } else {
process.nextTick(function() { process.nextTick(function() {

View File

@ -4,15 +4,15 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../lib/loopback'); const loopback = require('../../lib/loopback');
var debug = require('debug')('loopback:security:role'); const debug = require('debug')('loopback:security:role');
var assert = require('assert'); const assert = require('assert');
var async = require('async'); const async = require('async');
var utils = require('../../lib/utils'); const utils = require('../../lib/utils');
var ctx = require('../../lib/access-context'); const ctx = require('../../lib/access-context');
var AccessContext = ctx.AccessContext; const AccessContext = ctx.AccessContext;
var Principal = ctx.Principal; const Principal = ctx.Principal;
var RoleMapping = loopback.RoleMapping; const RoleMapping = loopback.RoleMapping;
assert(RoleMapping, 'RoleMapping model must be defined before Role model'); assert(RoleMapping, 'RoleMapping model must be defined before Role model');
@ -24,7 +24,7 @@ assert(RoleMapping, 'RoleMapping model must be defined before Role model');
module.exports = function(Role) { module.exports = function(Role) {
Role.resolveRelatedModels = function() { Role.resolveRelatedModels = function() {
if (!this.userModel) { if (!this.userModel) {
var reg = this.registry; const reg = this.registry;
this.roleMappingModel = reg.getModelByType('RoleMapping'); this.roleMappingModel = reg.getModelByType('RoleMapping');
this.userModel = reg.getModelByType('User'); this.userModel = reg.getModelByType('User');
this.applicationModel = reg.getModelByType('Application'); this.applicationModel = reg.getModelByType('Application');
@ -74,29 +74,29 @@ module.exports = function(Role) {
query.where = query.where || {}; query.where = query.where || {};
roleModel.resolveRelatedModels(); roleModel.resolveRelatedModels();
var relsToModels = { const relsToModels = {
users: roleModel.userModel, users: roleModel.userModel,
applications: roleModel.applicationModel, applications: roleModel.applicationModel,
roles: roleModel, roles: roleModel,
}; };
var ACL = loopback.ACL; const ACL = loopback.ACL;
var relsToTypes = { const relsToTypes = {
users: ACL.USER, users: ACL.USER,
applications: ACL.APP, applications: ACL.APP,
roles: ACL.ROLE, roles: ACL.ROLE,
}; };
var principalModel = relsToModels[rel]; let principalModel = relsToModels[rel];
var principalType = relsToTypes[rel]; let principalType = relsToTypes[rel];
// redefine user model and user type if user principalType is custom (available and not "USER") // redefine user model and user type if user principalType is custom (available and not "USER")
var isCustomUserPrincipalType = rel === 'users' && const isCustomUserPrincipalType = rel === 'users' &&
query.where.principalType && query.where.principalType &&
query.where.principalType !== RoleMapping.USER; query.where.principalType !== RoleMapping.USER;
if (isCustomUserPrincipalType) { if (isCustomUserPrincipalType) {
var registry = this.constructor.registry; const registry = this.constructor.registry;
principalModel = registry.findModel(query.where.principalType); principalModel = registry.findModel(query.where.principalType);
principalType = query.where.principalType; principalType = query.where.principalType;
} }
@ -133,11 +133,10 @@ module.exports = function(Role) {
roleModel.roleMappingModel.find({ roleModel.roleMappingModel.find({
where: {roleId: context.id, principalType: principalType}, where: {roleId: context.id, principalType: principalType},
}, function(err, mappings) { }, function(err, mappings) {
var ids;
if (err) { if (err) {
return callback(err); return callback(err);
} }
ids = mappings.map(function(m) { const ids = mappings.map(function(m) {
return m.principalId; return m.principalId;
}); });
query.where = query.where || {}; query.where = query.where || {};
@ -177,18 +176,18 @@ module.exports = function(Role) {
}); });
return; return;
} }
var modelClass = context.model; const modelClass = context.model;
var modelId = context.modelId; const modelId = context.modelId;
var user = context.getUser(); const user = context.getUser();
var userId = user && user.id; const userId = user && user.id;
var principalType = user && user.principalType; const principalType = user && user.principalType;
var opts = {accessToken: context.accessToken}; const opts = {accessToken: context.accessToken};
Role.isOwner(modelClass, modelId, userId, principalType, opts, callback); Role.isOwner(modelClass, modelId, userId, principalType, opts, callback);
}); });
function isUserClass(modelClass) { function isUserClass(modelClass) {
if (!modelClass) return false; if (!modelClass) return false;
var User = modelClass.modelBuilder.models.User; const User = modelClass.modelBuilder.models.User;
if (!User) return false; if (!User) return false;
return modelClass == User || modelClass.prototype instanceof User; return modelClass == User || modelClass.prototype instanceof User;
} }
@ -222,7 +221,7 @@ module.exports = function(Role) {
* @promise * @promise
*/ */
Role.isOwner = function isOwner(modelClass, modelId, userId, principalType, options, callback) { Role.isOwner = function isOwner(modelClass, modelId, userId, principalType, options, callback) {
var _this = this; const _this = this;
if (!callback && typeof options === 'function') { if (!callback && typeof options === 'function') {
callback = options; callback = options;
@ -253,8 +252,8 @@ module.exports = function(Role) {
// 1. the app has a single user model and principalType is 'USER' // 1. the app has a single user model and principalType is 'USER'
// 2. the app has multiple user models and principalType is not 'USER' // 2. the app has multiple user models and principalType is not 'USER'
// multiple user models // multiple user models
var isMultipleUsers = _isMultipleUsers(); const isMultipleUsers = _isMultipleUsers();
var isPrincipalTypeValid = const isPrincipalTypeValid =
(!isMultipleUsers && principalType === Principal.USER) || (!isMultipleUsers && principalType === Principal.USER) ||
(isMultipleUsers && principalType !== Principal.USER); (isMultipleUsers && principalType !== Principal.USER);
@ -271,7 +270,7 @@ module.exports = function(Role) {
// Is the modelClass User or a subclass of User? // Is the modelClass User or a subclass of User?
if (isUserClass(modelClass)) { if (isUserClass(modelClass)) {
var userModelName = modelClass.modelName; const userModelName = modelClass.modelName;
// matching ids is enough if principalType is USER or matches given user model name // matching ids is enough if principalType is USER or matches given user model name
if (principalType === Principal.USER || principalType === userModelName) { if (principalType === Principal.USER || principalType === userModelName) {
process.nextTick(function() { process.nextTick(function() {
@ -289,7 +288,7 @@ module.exports = function(Role) {
} }
debug('Model found: %j', inst); debug('Model found: %j', inst);
var ownerRelations = modelClass.settings.ownerRelations; const ownerRelations = modelClass.settings.ownerRelations;
if (!ownerRelations) { if (!ownerRelations) {
return legacyOwnershipCheck(inst); return legacyOwnershipCheck(inst);
} else { } else {
@ -308,24 +307,24 @@ module.exports = function(Role) {
// ownership check induced the whole isOwner() to resolve as false. // ownership check induced the whole isOwner() to resolve as false.
// This behaviour will be pruned at next LoopBack major release. // This behaviour will be pruned at next LoopBack major release.
function legacyOwnershipCheck(inst) { function legacyOwnershipCheck(inst) {
var ownerId = inst.userId || inst.owner; const ownerId = inst.userId || inst.owner;
if (principalType === Principal.USER && ownerId && 'function' !== typeof ownerId) { if (principalType === Principal.USER && ownerId && 'function' !== typeof ownerId) {
return callback(null, matches(ownerId, userId)); return callback(null, matches(ownerId, userId));
} }
// Try to follow belongsTo // Try to follow belongsTo
for (var r in modelClass.relations) { for (const r in modelClass.relations) {
var rel = modelClass.relations[r]; const rel = modelClass.relations[r];
// relation should be belongsTo and target a User based class // relation should be belongsTo and target a User based class
var belongsToUser = rel.type === 'belongsTo' && isUserClass(rel.modelTo); const belongsToUser = rel.type === 'belongsTo' && isUserClass(rel.modelTo);
if (!belongsToUser) { if (!belongsToUser) {
continue; continue;
} }
// checking related user // checking related user
var relatedUser = rel.modelTo; const relatedUser = rel.modelTo;
var userModelName = relatedUser.modelName; const userModelName = relatedUser.modelName;
var isMultipleUsers = _isMultipleUsers(relatedUser); const isMultipleUsers = _isMultipleUsers(relatedUser);
// a relation can be considered for isOwner resolution if: // a relation can be considered for isOwner resolution if:
// 1. the app has a single user model and principalType is 'USER' // 1. the app has a single user model and principalType is 'USER'
// 2. the app has multiple user models and principalType is the related user model name // 2. the app has multiple user models and principalType is the related user model name
@ -349,20 +348,20 @@ module.exports = function(Role) {
} }
function checkOwnership(inst) { function checkOwnership(inst) {
var ownerRelations = inst.constructor.settings.ownerRelations; const ownerRelations = inst.constructor.settings.ownerRelations;
// collecting related users // collecting related users
var relWithUsers = []; const relWithUsers = [];
for (var r in modelClass.relations) { for (const r in modelClass.relations) {
var rel = modelClass.relations[r]; const rel = modelClass.relations[r];
// relation should be belongsTo and target a User based class // relation should be belongsTo and target a User based class
if (rel.type !== 'belongsTo' || !isUserClass(rel.modelTo)) { if (rel.type !== 'belongsTo' || !isUserClass(rel.modelTo)) {
continue; continue;
} }
// checking related user // checking related user
var relatedUser = rel.modelTo; const relatedUser = rel.modelTo;
var userModelName = relatedUser.modelName; const userModelName = relatedUser.modelName;
var isMultipleUsers = _isMultipleUsers(relatedUser); const isMultipleUsers = _isMultipleUsers(relatedUser);
// a relation can be considered for isOwner resolution if: // a relation can be considered for isOwner resolution if:
// 1. the app has a single user model and principalType is 'USER' // 1. the app has a single user model and principalType is 'USER'
// 2. the app has multiple user models and principalType is the related user model name // 2. the app has multiple user models and principalType is the related user model name
@ -403,8 +402,8 @@ module.exports = function(Role) {
// user model by type. The relation with AccessToken is used to check // user model by type. The relation with AccessToken is used to check
// if polymorphism is used, and thus if multiple users. // if polymorphism is used, and thus if multiple users.
function _isMultipleUsers(userModel) { function _isMultipleUsers(userModel) {
var oneOfUserModels = userModel || _this.registry.getModelByType('User'); const oneOfUserModels = userModel || _this.registry.getModelByType('User');
var accessTokensRel = oneOfUserModels.relations.accessTokens; const accessTokensRel = oneOfUserModels.relations.accessTokens;
return !!(accessTokensRel && accessTokensRel.polymorphic); return !!(accessTokensRel && accessTokensRel.polymorphic);
} }
}; };
@ -480,11 +479,11 @@ module.exports = function(Role) {
debug('isInRole(): %s', role); debug('isInRole(): %s', role);
context.debug(); context.debug();
var resolver = Role.resolvers[role]; const resolver = Role.resolvers[role];
if (resolver) { if (resolver) {
debug('Custom resolver found for role %s', role); debug('Custom resolver found for role %s', role);
var promise = resolver(role, context, callback); const promise = resolver(role, context, callback);
if (promise && typeof promise.then === 'function') { if (promise && typeof promise.then === 'function') {
promise.then( promise.then(
function(result) { callback(null, result); }, function(result) { callback(null, result); },
@ -502,9 +501,9 @@ module.exports = function(Role) {
return callback.promise; return callback.promise;
} }
var inRole = context.principals.some(function(p) { const inRole = context.principals.some(function(p) {
var principalType = p.type || undefined; const principalType = p.type || undefined;
var principalId = p.id || undefined; const principalId = p.id || undefined;
// Check if it's the same role // Check if it's the same role
return principalType === RoleMapping.ROLE && principalId === role; return principalType === RoleMapping.ROLE && principalId === role;
@ -518,7 +517,7 @@ module.exports = function(Role) {
return callback.promise; return callback.promise;
} }
var roleMappingModel = this.roleMappingModel; const roleMappingModel = this.roleMappingModel;
this.findOne({where: {name: role}}, function(err, result) { this.findOne({where: {name: role}}, function(err, result) {
if (err) { if (err) {
if (callback) callback(err); if (callback) callback(err);
@ -532,10 +531,10 @@ module.exports = function(Role) {
// Iterate through the list of principals // Iterate through the list of principals
async.some(context.principals, function(p, done) { async.some(context.principals, function(p, done) {
var principalType = p.type || undefined; const principalType = p.type || undefined;
var principalId = p.id || undefined; let principalId = p.id || undefined;
var roleId = result.id.toString(); const roleId = result.id.toString();
var principalIdIsString = typeof principalId === 'string'; const principalIdIsString = typeof principalId === 'string';
if (principalId !== null && principalId !== undefined && !principalIdIsString) { if (principalId !== null && principalId !== undefined && !principalIdIsString) {
principalId = principalId.toString(); principalId = principalId.toString();
@ -585,18 +584,18 @@ module.exports = function(Role) {
if (!(context instanceof AccessContext)) { if (!(context instanceof AccessContext)) {
context = new AccessContext(context); context = new AccessContext(context);
} }
var roles = []; const roles = [];
this.resolveRelatedModels(); this.resolveRelatedModels();
var addRole = function(role) { const addRole = function(role) {
if (role && roles.indexOf(role) === -1) { if (role && roles.indexOf(role) === -1) {
roles.push(role); roles.push(role);
} }
}; };
var self = this; const self = this;
// Check against the smart roles // Check against the smart roles
var inRoleTasks = []; const inRoleTasks = [];
Object.keys(Role.resolvers).forEach(function(role) { Object.keys(Role.resolvers).forEach(function(role) {
inRoleTasks.push(function(done) { inRoleTasks.push(function(done) {
self.isInRole(role, context, function(err, inRole) { self.isInRole(role, context, function(err, inRole) {
@ -613,11 +612,11 @@ module.exports = function(Role) {
}); });
}); });
var roleMappingModel = this.roleMappingModel; const roleMappingModel = this.roleMappingModel;
context.principals.forEach(function(p) { context.principals.forEach(function(p) {
// Check against the role mappings // Check against the role mappings
var principalType = p.type || undefined; const principalType = p.type || undefined;
var principalId = p.id == null ? undefined : p.id; let principalId = p.id == null ? undefined : p.id;
if (typeof principalId !== 'string' && principalId != null) { if (typeof principalId !== 'string' && principalId != null) {
principalId = principalId.toString(); principalId = principalId.toString();
@ -631,7 +630,7 @@ module.exports = function(Role) {
if (principalType && principalId) { if (principalType && principalId) {
// Please find() treat undefined matches all values // Please find() treat undefined matches all values
inRoleTasks.push(function(done) { inRoleTasks.push(function(done) {
var filter = {where: {principalType: principalType, principalId: principalId}}; const filter = {where: {principalType: principalType, principalId: principalId}};
if (options.returnOnlyRoleNames === true) { if (options.returnOnlyRoleNames === true) {
filter.include = ['role']; filter.include = ['role'];
} }
@ -642,7 +641,7 @@ module.exports = function(Role) {
return; return;
} }
mappings.forEach(function(m) { mappings.forEach(function(m) {
var role; let role;
if (options.returnOnlyRoleNames === true) { if (options.returnOnlyRoleNames === true) {
role = m.toJSON().role.name; role = m.toJSON().role.name;
} else { } else {

View File

@ -4,8 +4,8 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var loopback = require('../../lib/loopback'); const loopback = require('../../lib/loopback');
/** /**
* Resource owner grants/delegates permissions to client applications * Resource owner grants/delegates permissions to client applications
@ -21,7 +21,7 @@ var loopback = require('../../lib/loopback');
module.exports = function(Scope) { module.exports = function(Scope) {
Scope.resolveRelatedModels = function() { Scope.resolveRelatedModels = function() {
if (!this.aclModel) { if (!this.aclModel) {
var reg = this.registry; const reg = this.registry;
this.aclModel = reg.getModelByType(loopback.ACL); this.aclModel = reg.getModelByType(loopback.ACL);
} }
}; };
@ -38,7 +38,7 @@ module.exports = function(Scope) {
*/ */
Scope.checkPermission = function(scope, model, property, accessType, callback) { Scope.checkPermission = function(scope, model, property, accessType, callback) {
this.resolveRelatedModels(); this.resolveRelatedModels();
var aclModel = this.aclModel; const aclModel = this.aclModel;
assert(aclModel, assert(aclModel,
'ACL model must be defined before Scope.checkPermission is called'); 'ACL model must be defined before Scope.checkPermission is called');

View File

@ -8,18 +8,18 @@
*/ */
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
var isEmail = require('isemail'); const isEmail = require('isemail');
var loopback = require('../../lib/loopback'); const loopback = require('../../lib/loopback');
var utils = require('../../lib/utils'); const utils = require('../../lib/utils');
var path = require('path'); const path = require('path');
var qs = require('querystring'); const qs = require('querystring');
var SALT_WORK_FACTOR = 10; const SALT_WORK_FACTOR = 10;
var crypto = require('crypto'); const crypto = require('crypto');
// bcrypt's max length is 72 bytes; // bcrypt's max length is 72 bytes;
// See https://github.com/kelektiv/node.bcrypt.js/blob/45f498ef6dc6e8234e58e07834ce06a50ff16352/src/node_blf.h#L59 // See https://github.com/kelektiv/node.bcrypt.js/blob/45f498ef6dc6e8234e58e07834ce06a50ff16352/src/node_blf.h#L59
var MAX_PASSWORD_LENGTH = 72; const MAX_PASSWORD_LENGTH = 72;
var bcrypt; let bcrypt;
try { try {
// Try the native module first // Try the native module first
bcrypt = require('bcrypt'); bcrypt = require('bcrypt');
@ -32,12 +32,12 @@ try {
bcrypt = require('bcryptjs'); bcrypt = require('bcryptjs');
} }
var DEFAULT_TTL = 1209600; // 2 weeks in seconds const DEFAULT_TTL = 1209600; // 2 weeks in seconds
var DEFAULT_RESET_PW_TTL = 15 * 60; // 15 mins in seconds const DEFAULT_RESET_PW_TTL = 15 * 60; // 15 mins in seconds
var DEFAULT_MAX_TTL = 31556926; // 1 year in seconds const DEFAULT_MAX_TTL = 31556926; // 1 year in seconds
var assert = require('assert'); const assert = require('assert');
var debug = require('debug')('loopback:user'); const debug = require('debug')('loopback:user');
/** /**
* Built-in User model. * Built-in User model.
@ -123,18 +123,18 @@ module.exports = function(User) {
tokenData = {}; tokenData = {};
} }
var userSettings = this.constructor.settings; const userSettings = this.constructor.settings;
tokenData.ttl = Math.min(tokenData.ttl || userSettings.ttl, userSettings.maxTTL); tokenData.ttl = Math.min(tokenData.ttl || userSettings.ttl, userSettings.maxTTL);
this.accessTokens.create(tokenData, options, cb); this.accessTokens.create(tokenData, options, cb);
return cb.promise; return cb.promise;
}; };
function splitPrincipal(name, realmDelimiter) { function splitPrincipal(name, realmDelimiter) {
var parts = [null, name]; const parts = [null, name];
if (!realmDelimiter) { if (!realmDelimiter) {
return parts; return parts;
} }
var index = name.indexOf(realmDelimiter); const index = name.indexOf(realmDelimiter);
if (index !== -1) { if (index !== -1) {
parts[0] = name.substring(0, index); parts[0] = name.substring(0, index);
parts[1] = name.substring(index + realmDelimiter.length); parts[1] = name.substring(index + realmDelimiter.length);
@ -150,7 +150,7 @@ module.exports = function(User) {
* @returns {Object} The normalized credential object * @returns {Object} The normalized credential object
*/ */
User.normalizeCredentials = function(credentials, realmRequired, realmDelimiter) { User.normalizeCredentials = function(credentials, realmRequired, realmDelimiter) {
var query = {}; const query = {};
credentials = credentials || {}; credentials = credentials || {};
if (!realmRequired) { if (!realmRequired) {
if (credentials.email) { if (credentials.email) {
@ -162,7 +162,7 @@ module.exports = function(User) {
if (credentials.realm) { if (credentials.realm) {
query.realm = credentials.realm; query.realm = credentials.realm;
} }
var parts; let parts;
if (credentials.email) { if (credentials.email) {
parts = splitPrincipal(credentials.email, realmDelimiter); parts = splitPrincipal(credentials.email, realmDelimiter);
query.email = parts[1]; query.email = parts[1];
@ -205,7 +205,7 @@ module.exports = function(User) {
*/ */
User.login = function(credentials, include, fn) { User.login = function(credentials, include, fn) {
var self = this; const self = this;
if (typeof include === 'function') { if (typeof include === 'function') {
fn = include; fn = include;
include = undefined; include = undefined;
@ -222,25 +222,25 @@ module.exports = function(User) {
include = include.toLowerCase(); include = include.toLowerCase();
} }
var realmDelimiter; let realmDelimiter;
// Check if realm is required // Check if realm is required
var realmRequired = !!(self.settings.realmRequired || const realmRequired = !!(self.settings.realmRequired ||
self.settings.realmDelimiter); self.settings.realmDelimiter);
if (realmRequired) { if (realmRequired) {
realmDelimiter = self.settings.realmDelimiter; realmDelimiter = self.settings.realmDelimiter;
} }
var query = self.normalizeCredentials(credentials, realmRequired, const query = self.normalizeCredentials(credentials, realmRequired,
realmDelimiter); realmDelimiter);
if (realmRequired) { if (realmRequired) {
if (!query.realm) { if (!query.realm) {
var err1 = new Error(g.f('{{realm}} is required')); const err1 = new Error(g.f('{{realm}} is required'));
err1.statusCode = 400; err1.statusCode = 400;
err1.code = 'REALM_REQUIRED'; err1.code = 'REALM_REQUIRED';
fn(err1); fn(err1);
return fn.promise; return fn.promise;
} else if (typeof query.realm !== 'string') { } else if (typeof query.realm !== 'string') {
var err5 = new Error(g.f('Invalid realm')); const err5 = new Error(g.f('Invalid realm'));
err5.statusCode = 400; err5.statusCode = 400;
err5.code = 'INVALID_REALM'; err5.code = 'INVALID_REALM';
fn(err5); fn(err5);
@ -248,20 +248,20 @@ module.exports = function(User) {
} }
} }
if (!query.email && !query.username) { if (!query.email && !query.username) {
var err2 = new Error(g.f('{{username}} or {{email}} is required')); const err2 = new Error(g.f('{{username}} or {{email}} is required'));
err2.statusCode = 400; err2.statusCode = 400;
err2.code = 'USERNAME_EMAIL_REQUIRED'; err2.code = 'USERNAME_EMAIL_REQUIRED';
fn(err2); fn(err2);
return fn.promise; return fn.promise;
} }
if (query.username && typeof query.username !== 'string') { if (query.username && typeof query.username !== 'string') {
var err3 = new Error(g.f('Invalid username')); const err3 = new Error(g.f('Invalid username'));
err3.statusCode = 400; err3.statusCode = 400;
err3.code = 'INVALID_USERNAME'; err3.code = 'INVALID_USERNAME';
fn(err3); fn(err3);
return fn.promise; return fn.promise;
} else if (query.email && typeof query.email !== 'string') { } else if (query.email && typeof query.email !== 'string') {
var err4 = new Error(g.f('Invalid email')); const err4 = new Error(g.f('Invalid email'));
err4.statusCode = 400; err4.statusCode = 400;
err4.code = 'INVALID_EMAIL'; err4.code = 'INVALID_EMAIL';
fn(err4); fn(err4);
@ -269,7 +269,7 @@ module.exports = function(User) {
} }
self.findOne({where: query}, function(err, user) { self.findOne({where: query}, function(err, user) {
var defaultError = new Error(g.f('login failed')); const defaultError = new Error(g.f('login failed'));
defaultError.statusCode = 401; defaultError.statusCode = 401;
defaultError.code = 'LOGIN_FAILED'; defaultError.code = 'LOGIN_FAILED';
@ -344,7 +344,7 @@ module.exports = function(User) {
User.logout = function(tokenId, fn) { User.logout = function(tokenId, fn) {
fn = fn || utils.createPromiseCallback(); fn = fn || utils.createPromiseCallback();
var err; let err;
if (!tokenId) { if (!tokenId) {
err = new Error(g.f('{{accessToken}} is required to logout')); err = new Error(g.f('{{accessToken}} is required to logout'));
err.statusCode = 401; err.statusCode = 401;
@ -370,12 +370,12 @@ module.exports = function(User) {
// Do nothing when the access control was disabled for this user model. // Do nothing when the access control was disabled for this user model.
if (!ctx.Model.relations.accessTokens) return next(); if (!ctx.Model.relations.accessTokens) return next();
var AccessToken = ctx.Model.relations.accessTokens.modelTo; const AccessToken = ctx.Model.relations.accessTokens.modelTo;
var pkName = ctx.Model.definition.idName() || 'id'; const pkName = ctx.Model.definition.idName() || 'id';
ctx.Model.find({where: ctx.where, fields: [pkName]}, function(err, list) { ctx.Model.find({where: ctx.where, fields: [pkName]}, function(err, list) {
if (err) return next(err); if (err) return next(err);
var ids = list.map(function(u) { return u[pkName]; }); const ids = list.map(function(u) { return u[pkName]; });
ctx.where = {}; ctx.where = {};
ctx.where[pkName] = {inq: ids}; ctx.where[pkName] = {inq: ids};
@ -720,9 +720,9 @@ module.exports = function(User) {
} }
cb = cb || utils.createPromiseCallback(); cb = cb || utils.createPromiseCallback();
var user = this; const user = this;
var userModel = this.constructor; const userModel = this.constructor;
var registry = userModel.registry; const registry = userModel.registry;
verifyOptions = Object.assign({}, verifyOptions); verifyOptions = Object.assign({}, verifyOptions);
// final assertion is performed once all options are assigned // final assertion is performed once all options are assigned
assert(typeof verifyOptions === 'object', assert(typeof verifyOptions === 'object',
@ -743,19 +743,19 @@ module.exports = function(User) {
verifyOptions.mailer = verifyOptions.mailer || userModel.email || verifyOptions.mailer = verifyOptions.mailer || userModel.email ||
registry.getModelByType(loopback.Email); registry.getModelByType(loopback.Email);
var pkName = userModel.definition.idName() || 'id'; const pkName = userModel.definition.idName() || 'id';
verifyOptions.redirect = verifyOptions.redirect || '/'; verifyOptions.redirect = verifyOptions.redirect || '/';
var defaultTemplate = path.join(__dirname, '..', '..', 'templates', 'verify.ejs'); const defaultTemplate = path.join(__dirname, '..', '..', 'templates', 'verify.ejs');
verifyOptions.template = path.resolve(verifyOptions.template || defaultTemplate); verifyOptions.template = path.resolve(verifyOptions.template || defaultTemplate);
verifyOptions.user = user; verifyOptions.user = user;
verifyOptions.protocol = verifyOptions.protocol || 'http'; verifyOptions.protocol = verifyOptions.protocol || 'http';
var app = userModel.app; const app = userModel.app;
verifyOptions.host = verifyOptions.host || (app && app.get('host')) || 'localhost'; verifyOptions.host = verifyOptions.host || (app && app.get('host')) || 'localhost';
verifyOptions.port = verifyOptions.port || (app && app.get('port')) || 3000; verifyOptions.port = verifyOptions.port || (app && app.get('port')) || 3000;
verifyOptions.restApiRoot = verifyOptions.restApiRoot || (app && app.get('restApiRoot')) || '/api'; verifyOptions.restApiRoot = verifyOptions.restApiRoot || (app && app.get('restApiRoot')) || '/api';
var displayPort = ( const displayPort = (
(verifyOptions.protocol === 'http' && verifyOptions.port == '80') || (verifyOptions.protocol === 'http' && verifyOptions.port == '80') ||
(verifyOptions.protocol === 'https' && verifyOptions.port == '443') (verifyOptions.protocol === 'https' && verifyOptions.port == '443')
) ? '' : ':' + verifyOptions.port; ) ? '' : ':' + verifyOptions.port;
@ -796,7 +796,7 @@ module.exports = function(User) {
assertVerifyOptions(verifyOptions); assertVerifyOptions(verifyOptions);
// argument "options" is passed depending on verifyOptions.generateVerificationToken function requirements // argument "options" is passed depending on verifyOptions.generateVerificationToken function requirements
var tokenGenerator = verifyOptions.generateVerificationToken; const tokenGenerator = verifyOptions.generateVerificationToken;
if (tokenGenerator.length == 3) { if (tokenGenerator.length == 3) {
tokenGenerator(user, options, addTokenToUserAndSave); tokenGenerator(user, options, addTokenToUserAndSave);
} else { } else {
@ -824,7 +824,7 @@ module.exports = function(User) {
verifyOptions.text = verifyOptions.text.replace(/\{href\}/g, verifyOptions.verifyHref); verifyOptions.text = verifyOptions.text.replace(/\{href\}/g, verifyOptions.verifyHref);
// argument "options" is passed depending on templateFn function requirements // argument "options" is passed depending on templateFn function requirements
var templateFn = verifyOptions.templateFn; const templateFn = verifyOptions.templateFn;
if (templateFn.length == 3) { if (templateFn.length == 3) {
templateFn(verifyOptions, options, setHtmlContentAndSend); templateFn(verifyOptions, options, setHtmlContentAndSend);
} else { } else {
@ -841,7 +841,7 @@ module.exports = function(User) {
delete verifyOptions.template; delete verifyOptions.template;
// argument "options" is passed depending on Email.send function requirements // argument "options" is passed depending on Email.send function requirements
var Email = verifyOptions.mailer; const Email = verifyOptions.mailer;
if (Email.send.length == 3) { if (Email.send.length == 3) {
Email.send(verifyOptions, options, handleAfterSend); Email.send(verifyOptions, options, handleAfterSend);
} else { } else {
@ -873,8 +873,8 @@ module.exports = function(User) {
} }
function createVerificationEmailBody(verifyOptions, options, cb) { function createVerificationEmailBody(verifyOptions, options, cb) {
var template = loopback.template(verifyOptions.template); const template = loopback.template(verifyOptions.template);
var body = template(verifyOptions); const body = template(verifyOptions);
cb(null, body); cb(null, body);
} }
@ -952,11 +952,11 @@ module.exports = function(User) {
User.resetPassword = function(options, cb) { User.resetPassword = function(options, cb) {
cb = cb || utils.createPromiseCallback(); cb = cb || utils.createPromiseCallback();
var UserModel = this; const UserModel = this;
var ttl = UserModel.settings.resetPasswordTokenTTL || DEFAULT_RESET_PW_TTL; const ttl = UserModel.settings.resetPasswordTokenTTL || DEFAULT_RESET_PW_TTL;
options = options || {}; options = options || {};
if (typeof options.email !== 'string') { if (typeof options.email !== 'string') {
var err = new Error(g.f('Email is required')); const err = new Error(g.f('Email is required'));
err.statusCode = 400; err.statusCode = 400;
err.code = 'EMAIL_REQUIRED'; err.code = 'EMAIL_REQUIRED';
cb(err); cb(err);
@ -970,7 +970,7 @@ module.exports = function(User) {
} catch (err) { } catch (err) {
return cb(err); return cb(err);
} }
var where = { const where = {
email: options.email, email: options.email,
}; };
if (options.realm) { if (options.realm) {
@ -1031,12 +1031,12 @@ module.exports = function(User) {
*/ */
User.hashPassword = function(plain) { User.hashPassword = function(plain) {
this.validatePassword(plain); this.validatePassword(plain);
var salt = bcrypt.genSaltSync(this.settings.saltWorkFactor || SALT_WORK_FACTOR); const salt = bcrypt.genSaltSync(this.settings.saltWorkFactor || SALT_WORK_FACTOR);
return bcrypt.hashSync(plain, salt); return bcrypt.hashSync(plain, salt);
}; };
User.validatePassword = function(plain) { User.validatePassword = function(plain) {
var err; let err;
if (!plain || typeof plain !== 'string') { if (!plain || typeof plain !== 'string') {
err = new Error(g.f('Invalid password.')); err = new Error(g.f('Invalid password.'));
err.code = 'INVALID_PASSWORD'; err.code = 'INVALID_PASSWORD';
@ -1045,7 +1045,7 @@ module.exports = function(User) {
} }
// Bcrypt only supports up to 72 bytes; the rest is silently dropped. // Bcrypt only supports up to 72 bytes; the rest is silently dropped.
var len = Buffer.byteLength(plain, 'utf8'); const len = Buffer.byteLength(plain, 'utf8');
if (len > MAX_PASSWORD_LENGTH) { if (len > MAX_PASSWORD_LENGTH) {
err = new Error(g.f('The password entered was too long. Max length is %d (entered %d)', err = new Error(g.f('The password entered was too long. Max length is %d (entered %d)',
MAX_PASSWORD_LENGTH, len)); MAX_PASSWORD_LENGTH, len));
@ -1064,20 +1064,20 @@ module.exports = function(User) {
if (!Array.isArray(userIds) || !userIds.length) if (!Array.isArray(userIds) || !userIds.length)
return process.nextTick(cb); return process.nextTick(cb);
var accessTokenRelation = this.relations.accessTokens; const accessTokenRelation = this.relations.accessTokens;
if (!accessTokenRelation) if (!accessTokenRelation)
return process.nextTick(cb); return process.nextTick(cb);
var AccessToken = accessTokenRelation.modelTo; const AccessToken = accessTokenRelation.modelTo;
var query = {userId: {inq: userIds}}; const query = {userId: {inq: userIds}};
var tokenPK = AccessToken.definition.idName() || 'id'; const tokenPK = AccessToken.definition.idName() || 'id';
if (options.accessToken && tokenPK in options.accessToken) { if (options.accessToken && tokenPK in options.accessToken) {
query[tokenPK] = {neq: options.accessToken[tokenPK]}; query[tokenPK] = {neq: options.accessToken[tokenPK]};
} }
// add principalType in AccessToken.query if using polymorphic relations // add principalType in AccessToken.query if using polymorphic relations
// between AccessToken and User // between AccessToken and User
var relatedUser = AccessToken.relations.user; const relatedUser = AccessToken.relations.user;
var isRelationPolymorphic = relatedUser && relatedUser.polymorphic && const isRelationPolymorphic = relatedUser && relatedUser.polymorphic &&
!relatedUser.modelTo; !relatedUser.modelTo;
if (isRelationPolymorphic) { if (isRelationPolymorphic) {
query.principalType = this.modelName; query.principalType = this.modelName;
@ -1092,7 +1092,7 @@ module.exports = function(User) {
User.setup = function() { User.setup = function() {
// We need to call the base class's setup method // We need to call the base class's setup method
User.base.setup.call(this); User.base.setup.call(this);
var UserModel = this; const UserModel = this;
// max ttl // max ttl
this.settings.maxTTL = this.settings.maxTTL || DEFAULT_MAX_TTL; this.settings.maxTTL = this.settings.maxTTL || DEFAULT_MAX_TTL;
@ -1121,7 +1121,7 @@ module.exports = function(User) {
// Make sure emailVerified is not set by creation // Make sure emailVerified is not set by creation
UserModel.beforeRemote('create', function(ctx, user, next) { UserModel.beforeRemote('create', function(ctx, user, next) {
var body = ctx.req.body; const body = ctx.req.body;
if (body && body.emailVerified) { if (body && body.emailVerified) {
body.emailVerified = false; body.emailVerified = false;
} }
@ -1157,9 +1157,9 @@ module.exports = function(User) {
description: 'Logout a user with access token.', description: 'Logout a user with access token.',
accepts: [ accepts: [
{arg: 'access_token', type: 'string', http: function(ctx) { {arg: 'access_token', type: 'string', http: function(ctx) {
var req = ctx && ctx.req; const req = ctx && ctx.req;
var accessToken = req && req.accessToken; const accessToken = req && req.accessToken;
var tokenID = accessToken ? accessToken.id : undefined; const tokenID = accessToken ? accessToken.id : undefined;
return tokenID; return tokenID;
}, description: 'Do not supply this argument, it is automatically extracted ' + }, description: 'Do not supply this argument, it is automatically extracted ' +
@ -1361,8 +1361,8 @@ module.exports = function(User) {
if (ctx.isNewInstance) return next(); if (ctx.isNewInstance) return next();
if (!ctx.where && !ctx.instance) return next(); if (!ctx.where && !ctx.instance) return next();
var pkName = ctx.Model.definition.idName() || 'id'; const pkName = ctx.Model.definition.idName() || 'id';
var where = ctx.where; let where = ctx.where;
if (!where) { if (!where) {
where = {}; where = {};
where[pkName] = ctx.instance[pkName]; where[pkName] = ctx.instance[pkName];
@ -1371,13 +1371,13 @@ module.exports = function(User) {
ctx.Model.find({where: where}, ctx.options, function(err, userInstances) { ctx.Model.find({where: where}, ctx.options, function(err, userInstances) {
if (err) return next(err); if (err) return next(err);
ctx.hookState.originalUserData = userInstances.map(function(u) { ctx.hookState.originalUserData = userInstances.map(function(u) {
var user = {}; const user = {};
user[pkName] = u[pkName]; user[pkName] = u[pkName];
user.email = u.email; user.email = u.email;
user.password = u.password; user.password = u.password;
return user; return user;
}); });
var emailChanged; let emailChanged;
if (ctx.instance) { if (ctx.instance) {
// Check if map does not return an empty array // Check if map does not return an empty array
// Fix server crashes when try to PUT a non existent id // Fix server crashes when try to PUT a non existent id
@ -1407,15 +1407,15 @@ module.exports = function(User) {
if (!ctx.instance && !ctx.data) return next(); if (!ctx.instance && !ctx.data) return next();
if (!ctx.hookState.originalUserData) return next(); if (!ctx.hookState.originalUserData) return next();
var pkName = ctx.Model.definition.idName() || 'id'; const pkName = ctx.Model.definition.idName() || 'id';
var newEmail = (ctx.instance || ctx.data).email; const newEmail = (ctx.instance || ctx.data).email;
var newPassword = (ctx.instance || ctx.data).password; const newPassword = (ctx.instance || ctx.data).password;
if (!newEmail && !newPassword) return next(); if (!newEmail && !newPassword) return next();
if (ctx.options.preserveAccessTokens) return next(); if (ctx.options.preserveAccessTokens) return next();
var userIdsToExpire = ctx.hookState.originalUserData.filter(function(u) { const userIdsToExpire = ctx.hookState.originalUserData.filter(function(u) {
return (newEmail && u.email !== newEmail) || return (newEmail && u.email !== newEmail) ||
(newPassword && u.password !== newPassword); (newPassword && u.password !== newPassword);
}).map(function(u) { }).map(function(u) {
@ -1426,7 +1426,7 @@ module.exports = function(User) {
}; };
function emailValidator(err, done) { function emailValidator(err, done) {
var value = this.email; const value = this.email;
if (value == null) if (value == null)
return; return;
if (typeof value !== 'string') if (typeof value !== 'string')
@ -1437,9 +1437,9 @@ function emailValidator(err, done) {
} }
function joinUrlPath(args) { function joinUrlPath(args) {
var result = arguments[0]; let result = arguments[0];
for (var ix = 1; ix < arguments.length; ix++) { for (let ix = 1; ix < arguments.length; ix++) {
var next = arguments[ix]; const next = arguments[ix];
result += result[result.length - 1] === '/' && next[0] === '/' ? result += result[result.length - 1] === '/' && next[0] === '/' ?
next.slice(1) : next; next.slice(1) : next;
} }

View File

@ -4,11 +4,11 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
var loopback = require('../../'); const loopback = require('../../');
var client = loopback(); const client = loopback();
var CartItem = require('./models').CartItem; const CartItem = require('./models').CartItem;
var remote = loopback.createDataSource({ const remote = loopback.createDataSource({
connector: loopback.Remote, connector: loopback.Remote,
url: 'http://localhost:3000', url: 'http://localhost:3000',
}); });

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../'); const loopback = require('../../');
var CartItem = exports.CartItem = loopback.PersistedModel.extend('CartItem', { const CartItem = exports.CartItem = loopback.PersistedModel.extend('CartItem', {
tax: {type: Number, default: 0.1}, tax: {type: Number, default: 0.1},
price: Number, price: Number,
item: String, item: String,
@ -17,7 +17,7 @@ var CartItem = exports.CartItem = loopback.PersistedModel.extend('CartItem', {
CartItem.sum = function(cartId, callback) { CartItem.sum = function(cartId, callback) {
this.find({where: {cartId: cartId}}, function(err, items) { this.find({where: {cartId: cartId}}, function(err, items) {
if (err) return callback(err); if (err) return callback(err);
var total = items const total = items
.map(function(item) { .map(function(item) {
return item.total(); return item.total();
}) })
@ -33,8 +33,7 @@ CartItem.remoteMethod('sum',
{ {
accepts: {arg: 'cartId', type: 'number'}, accepts: {arg: 'cartId', type: 'number'},
returns: {arg: 'total', type: 'number'}, returns: {arg: 'total', type: 'number'},
} });
);
CartItem.prototype.total = function() { CartItem.prototype.total = function() {
return this.price * this.qty * (1 + this.tax); return this.price * this.qty * (1 + this.tax);

View File

@ -4,10 +4,10 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../'); const loopback = require('../../');
var server = module.exports = loopback(); const server = module.exports = loopback();
var CartItem = require('./models').CartItem; const CartItem = require('./models').CartItem;
var memory = loopback.createDataSource({ const memory = loopback.createDataSource({
connector: loopback.Memory, connector: loopback.Memory,
}); });

View File

@ -4,18 +4,18 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
var loopback = require('../../'); const loopback = require('../../');
var app = loopback(); const app = loopback();
app.use(loopback.rest()); app.use(loopback.rest());
var schema = { const schema = {
name: String, name: String,
}; };
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
var Color = app.registry.createModel('color', schema); const Color = app.registry.createModel('color', schema);
app.model(Color, {dataSource: 'db'}); app.model(Color, {dataSource: 'db'});
Color.create({name: 'red'}); Color.create({name: 'red'});

View File

@ -4,20 +4,20 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
var models = require('../../lib/models'); const models = require('../../lib/models');
var loopback = require('../../'); const loopback = require('../../');
var app = loopback(); const app = loopback();
app.use(loopback.rest()); app.use(loopback.rest());
var dataSource = loopback.createDataSource('db', {connector: loopback.Memory}); const dataSource = loopback.createDataSource('db', {connector: loopback.Memory});
var Application = models.Application(dataSource); const Application = models.Application(dataSource);
app.model(Application); app.model(Application);
var data = { const data = {
pushSettings: [{ pushSettings: [{
'platform': 'apns', 'platform': 'apns',
'apns': { 'apns': {

View File

@ -4,19 +4,19 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../'); const loopback = require('../../');
var app = loopback(); const app = loopback();
var db = app.dataSource('db', {connector: 'memory'}); const db = app.dataSource('db', {connector: 'memory'});
var Color = app.registry.createModel('color', {}, {trackChanges: true}); const Color = app.registry.createModel('color', {}, {trackChanges: true});
app.model(Color, {dataSource: 'db'}); app.model(Color, {dataSource: 'db'});
var Color2 = app.registry.createModel('color2', {}, {trackChanges: true}); const Color2 = app.registry.createModel('color2', {}, {trackChanges: true});
app.model(Color2, {dataSource: 'db'}); app.model(Color2, {dataSource: 'db'});
var target = Color2; const target = Color2;
var source = Color; const source = Color;
var SPEED = process.env.SPEED || 100; const SPEED = process.env.SPEED || 100;
var conflicts; let conflicts;
var steps = [ const steps = [
createSomeInitialSourceData, createSomeInitialSourceData,
@ -137,7 +137,7 @@ function list(model, msg) {
function run(steps) { function run(steps) {
setInterval(function() { setInterval(function() {
var step = steps.shift(); const step = steps.shift();
if (step) { if (step) {
console.log(step.name); console.log(step.name);
step(); step();

View File

@ -4,15 +4,15 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
var loopback = require('../../'); const loopback = require('../../');
var app = loopback(); const app = loopback();
app.use(loopback.rest()); app.use(loopback.rest());
var dataSource = app.dataSource('db', {adapter: 'memory'}); const dataSource = app.dataSource('db', {adapter: 'memory'});
var Color = dataSource.define('color', { const Color = dataSource.define('color', {
'name': String, 'name': String,
}); });

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var loopback = require('./loopback'); const loopback = require('./loopback');
var debug = require('debug')('loopback:security:access-context'); const debug = require('debug')('loopback:security:access-context');
const DEFAULT_SCOPES = ['DEFAULT']; const DEFAULT_SCOPES = ['DEFAULT'];
@ -50,7 +50,7 @@ function AccessContext(context) {
'Application registry is mandatory in AccessContext but missing in provided context'); 'Application registry is mandatory in AccessContext but missing in provided context');
this.registry = context.registry; this.registry = context.registry;
this.principals = context.principals || []; this.principals = context.principals || [];
var model = context.model; let model = context.model;
model = ('string' === typeof model) ? this.registry.getModel(model) : model; model = ('string' === typeof model) ? this.registry.getModel(model) : model;
this.model = model; this.model = model;
this.modelName = model && model.modelName; this.modelName = model && model.modelName;
@ -77,9 +77,9 @@ function AccessContext(context) {
'AccessToken model must be defined before AccessContext model'); 'AccessToken model must be defined before AccessContext model');
this.accessToken = context.accessToken || loopback.AccessToken.ANONYMOUS; this.accessToken = context.accessToken || loopback.AccessToken.ANONYMOUS;
var principalType = context.principalType || Principal.USER; const principalType = context.principalType || Principal.USER;
var principalId = context.principalId || undefined; const principalId = context.principalId || undefined;
var principalName = context.principalName || undefined; const principalName = context.principalName || undefined;
if (principalId != null) { if (principalId != null) {
this.addPrincipal(principalType, principalId, principalName); this.addPrincipal(principalType, principalId, principalName);
} }
@ -126,9 +126,9 @@ AccessContext.permissionOrder = {
* @returns {boolean} * @returns {boolean}
*/ */
AccessContext.prototype.addPrincipal = function(principalType, principalId, principalName) { AccessContext.prototype.addPrincipal = function(principalType, principalId, principalName) {
var principal = new Principal(principalType, principalId, principalName); const principal = new Principal(principalType, principalId, principalName);
for (var i = 0; i < this.principals.length; i++) { for (let i = 0; i < this.principals.length; i++) {
var p = this.principals[i]; const p = this.principals[i];
if (p.equals(principal)) { if (p.equals(principal)) {
return false; return false;
} }
@ -142,7 +142,7 @@ AccessContext.prototype.addPrincipal = function(principalType, principalId, prin
* @returns {*} * @returns {*}
*/ */
AccessContext.prototype.getUserId = function() { AccessContext.prototype.getUserId = function() {
var user = this.getUser(); const user = this.getUser();
return user && user.id; return user && user.id;
}; };
@ -151,10 +151,10 @@ AccessContext.prototype.getUserId = function() {
* @returns {*} * @returns {*}
*/ */
AccessContext.prototype.getUser = function() { AccessContext.prototype.getUser = function() {
var BaseUser = this.registry.getModel('User'); const BaseUser = this.registry.getModel('User');
for (var i = 0; i < this.principals.length; i++) { for (let i = 0; i < this.principals.length; i++) {
var p = this.principals[i]; const p = this.principals[i];
var isBuiltinPrincipal = p.type === Principal.APP || const isBuiltinPrincipal = p.type === Principal.APP ||
p.type === Principal.ROLE || p.type === Principal.ROLE ||
p.type == Principal.SCOPE; p.type == Principal.SCOPE;
if (isBuiltinPrincipal) continue; if (isBuiltinPrincipal) continue;
@ -165,7 +165,7 @@ AccessContext.prototype.getUser = function() {
} }
// or permit to resolve a valid user model // or permit to resolve a valid user model
var userModel = this.registry.findModel(p.type); const userModel = this.registry.findModel(p.type);
if (!userModel) continue; if (!userModel) continue;
if (userModel.prototype instanceof BaseUser) { if (userModel.prototype instanceof BaseUser) {
return {id: p.id, principalType: p.type}; return {id: p.id, principalType: p.type};
@ -178,8 +178,8 @@ AccessContext.prototype.getUser = function() {
* @returns {*} * @returns {*}
*/ */
AccessContext.prototype.getAppId = function() { AccessContext.prototype.getAppId = function() {
for (var i = 0; i < this.principals.length; i++) { for (let i = 0; i < this.principals.length; i++) {
var p = this.principals[i]; const p = this.principals[i];
if (p.type === Principal.APPLICATION) { if (p.type === Principal.APPLICATION) {
return p.id; return p.id;
} }
@ -325,7 +325,7 @@ function AccessRequest(model, property, accessType, permission, methodNames, reg
} }
if (arguments.length === 1 && typeof model === 'object') { if (arguments.length === 1 && typeof model === 'object') {
// The argument is an object that contains all required properties // The argument is an object that contains all required properties
var obj = model || {}; const obj = model || {};
this.model = obj.model || AccessContext.ALL; this.model = obj.model || AccessContext.ALL;
this.property = obj.property || AccessContext.ALL; this.property = obj.property || AccessContext.ALL;
this.accessType = obj.accessType || AccessContext.ALL; this.accessType = obj.accessType || AccessContext.ALL;
@ -363,10 +363,10 @@ AccessRequest.prototype.isWildcard = function() {
*/ */
AccessRequest.prototype.exactlyMatches = function(acl) { AccessRequest.prototype.exactlyMatches = function(acl) {
var matchesModel = acl.model === this.model; const matchesModel = acl.model === this.model;
var matchesProperty = acl.property === this.property; const matchesProperty = acl.property === this.property;
var matchesMethodName = this.methodNames.indexOf(acl.property) !== -1; const matchesMethodName = this.methodNames.indexOf(acl.property) !== -1;
var matchesAccessType = acl.accessType === this.accessType; const matchesAccessType = acl.accessType === this.accessType;
if (matchesModel && matchesAccessType) { if (matchesModel && matchesAccessType) {
return matchesProperty || matchesMethodName; return matchesProperty || matchesMethodName;
@ -388,9 +388,9 @@ AccessRequest.prototype.settleDefaultPermission = function(defaultPermission) {
if (this.permission !== 'DEFAULT') if (this.permission !== 'DEFAULT')
return; return;
var modelName = this.model; const modelName = this.model;
if (!defaultPermission) { if (!defaultPermission) {
var modelClass = this.registry.findModel(modelName); const modelClass = this.registry.findModel(modelName);
defaultPermission = modelClass && modelClass.settings.defaultPermission; defaultPermission = modelClass && modelClass.settings.defaultPermission;
} }

View File

@ -8,17 +8,17 @@
*/ */
'use strict'; 'use strict';
var g = require('./globalize'); const g = require('./globalize');
var DataSource = require('loopback-datasource-juggler').DataSource; const DataSource = require('loopback-datasource-juggler').DataSource;
var Registry = require('./registry'); const Registry = require('./registry');
var assert = require('assert'); const assert = require('assert');
var fs = require('fs'); const fs = require('fs');
var extend = require('util')._extend; const extend = require('util')._extend;
var RemoteObjects = require('strong-remoting'); const RemoteObjects = require('strong-remoting');
var classify = require('underscore.string/classify'); const classify = require('underscore.string/classify');
var camelize = require('underscore.string/camelize'); const camelize = require('underscore.string/camelize');
var path = require('path'); const path = require('path');
var util = require('util'); const util = require('util');
/** /**
* The `App` object represents a Loopback application. * The `App` object represents a Loopback application.
@ -49,7 +49,7 @@ function App() {
* Export the app prototype. * Export the app prototype.
*/ */
var app = module.exports = {}; const app = module.exports = {};
/** /**
* Lazily load a set of [remote objects](http://apidocs.strongloop.com/strong-remoting/#remoteobjectsoptions). * Lazily load a set of [remote objects](http://apidocs.strongloop.com/strong-remoting/#remoteobjectsoptions).
@ -62,7 +62,7 @@ app.remotes = function() {
if (this._remotes) { if (this._remotes) {
return this._remotes; return this._remotes;
} else { } else {
var options = {}; let options = {};
if (this.get) { if (this.get) {
options = this.get('remoting'); options = this.get('remoting');
@ -78,7 +78,7 @@ app.remotes = function() {
app.disuse = function(route) { app.disuse = function(route) {
if (this.stack) { if (this.stack) {
for (var i = 0; i < this.stack.length; i++) { for (let i = 0; i < this.stack.length; i++) {
if (this.stack[i].route === route) { if (this.stack[i].route === route) {
this.stack.splice(i, 1); this.stack.splice(i, 1);
} }
@ -111,11 +111,11 @@ app.disuse = function(route) {
*/ */
app.model = function(Model, config) { app.model = function(Model, config) {
var isPublic = true; let isPublic = true;
var registry = this.registry; const registry = this.registry;
if (typeof Model === 'string') { if (typeof Model === 'string') {
var msg = 'app.model(modelName, settings) is no longer supported. ' + const msg = 'app.model(modelName, settings) is no longer supported. ' +
'Use app.registry.createModel(modelName, definition) and ' + 'Use app.registry.createModel(modelName, definition) and ' +
'app.model(ModelCtor, config) instead.'; 'app.model(ModelCtor, config) instead.';
throw new Error(msg); throw new Error(msg);
@ -130,7 +130,7 @@ app.model = function(Model, config) {
Model.modelName + ' must be a descendant of loopback.Model'); Model.modelName + ' must be a descendant of loopback.Model');
} }
var modelName = Model.modelName; const modelName = Model.modelName;
this.models[modelName] = this.models[modelName] =
this.models[classify(modelName)] = this.models[classify(modelName)] =
this.models[camelize(modelName)] = Model; this.models[camelize(modelName)] = Model;
@ -149,7 +149,7 @@ app.model = function(Model, config) {
this.emit('modelRemoted', Model.sharedClass); this.emit('modelRemoted', Model.sharedClass);
} }
var self = this; const self = this;
Model.on('remoteMethodDisabled', function(model, methodName) { Model.on('remoteMethodDisabled', function(model, methodName) {
clearHandlerCache(self); clearHandlerCache(self);
self.emit('remoteMethodDisabled', model, methodName); self.emit('remoteMethodDisabled', model, methodName);
@ -266,7 +266,7 @@ app.models = function() {
*/ */
app.dataSource = function(name, config) { app.dataSource = function(name, config) {
try { try {
var ds = dataSourcesFromConfig(name, config, this.connectors, this.registry); const ds = dataSourcesFromConfig(name, config, this.connectors, this.registry);
this.dataSources[name] = this.dataSources[name] =
this.dataSources[classify(name)] = this.dataSources[classify(name)] =
this.dataSources[camelize(name)] = ds; this.dataSources[camelize(name)] = ds;
@ -307,7 +307,7 @@ app.connector = function(name, connector) {
*/ */
app.remoteObjects = function() { app.remoteObjects = function() {
var result = {}; const result = {};
this.remotes().classes().forEach(function(sharedClass) { this.remotes().classes().forEach(function(sharedClass) {
result[sharedClass.name] = sharedClass.ctor; result[sharedClass.name] = sharedClass.ctor;
@ -322,13 +322,13 @@ app.remoteObjects = function() {
*/ */
app.handler = function(type, options) { app.handler = function(type, options) {
var handlers = this._handlers || (this._handlers = {}); const handlers = this._handlers || (this._handlers = {});
if (handlers[type]) { if (handlers[type]) {
return handlers[type]; return handlers[type];
} }
var remotes = this.remotes(); const remotes = this.remotes();
var handler = this._handlers[type] = remotes.handler(type, options); const handler = this._handlers[type] = remotes.handler(type, options);
remotes.classes().forEach(function(sharedClass) { remotes.classes().forEach(function(sharedClass) {
sharedClass.ctor.emit('mounted', app, sharedClass, remotes); sharedClass.ctor.emit('mounted', app, sharedClass, remotes);
@ -348,15 +348,15 @@ app.dataSources = app.datasources = {};
*/ */
app.enableAuth = function(options) { app.enableAuth = function(options) {
var AUTH_MODELS = ['User', 'AccessToken', 'ACL', 'Role', 'RoleMapping']; const AUTH_MODELS = ['User', 'AccessToken', 'ACL', 'Role', 'RoleMapping'];
var remotes = this.remotes(); const remotes = this.remotes();
var app = this; const app = this;
if (options && options.dataSource) { if (options && options.dataSource) {
var appModels = app.registry.modelBuilder.models; const appModels = app.registry.modelBuilder.models;
AUTH_MODELS.forEach(function(m) { AUTH_MODELS.forEach(function(m) {
var Model = app.registry.findModel(m); const Model = app.registry.findModel(m);
if (!Model) { if (!Model) {
throw new Error( throw new Error(
g.f('Authentication requires model %s to be defined.', m) g.f('Authentication requires model %s to be defined.', m)
@ -367,10 +367,10 @@ app.enableAuth = function(options) {
// Find descendants of Model that are attached, // Find descendants of Model that are attached,
// for example "Customer" extending "User" model // for example "Customer" extending "User" model
for (var name in appModels) { for (const name in appModels) {
var candidate = appModels[name]; const candidate = appModels[name];
var isSubclass = candidate.prototype instanceof Model; const isSubclass = candidate.prototype instanceof Model;
var isAttached = !!candidate.dataSource || !!candidate.app; const isAttached = !!candidate.dataSource || !!candidate.app;
if (isSubclass && isAttached) return; if (isSubclass && isAttached) return;
} }
@ -382,22 +382,22 @@ app.enableAuth = function(options) {
} }
remotes.authorization = function(ctx, next) { remotes.authorization = function(ctx, next) {
var method = ctx.method; const method = ctx.method;
var req = ctx.req; const req = ctx.req;
var Model = method.ctor; const Model = method.ctor;
var modelInstance = ctx.instance; const modelInstance = ctx.instance;
var modelId = modelInstance && modelInstance.id || const modelId = modelInstance && modelInstance.id ||
// replacement for deprecated req.param() // replacement for deprecated req.param()
(req.params && req.params.id !== undefined ? req.params.id : (req.params && req.params.id !== undefined ? req.params.id :
req.body && req.body.id !== undefined ? req.body.id : req.body && req.body.id !== undefined ? req.body.id :
req.query && req.query.id !== undefined ? req.query.id : req.query && req.query.id !== undefined ? req.query.id :
undefined); undefined);
var modelName = Model.modelName; const modelName = Model.modelName;
var modelSettings = Model.settings || {}; const modelSettings = Model.settings || {};
var errStatusCode = modelSettings.aclErrorStatus || app.get('aclErrorStatus') || 401; let errStatusCode = modelSettings.aclErrorStatus || app.get('aclErrorStatus') || 401;
if (!req.accessToken) { if (!req.accessToken) {
errStatusCode = 401; errStatusCode = 401;
} }
@ -415,7 +415,7 @@ app.enableAuth = function(options) {
} else if (allowed) { } else if (allowed) {
next(); next();
} else { } else {
var messages = { const messages = {
403: { 403: {
message: g.f('Access Denied'), message: g.f('Access Denied'),
code: 'ACCESS_DENIED', code: 'ACCESS_DENIED',
@ -430,7 +430,7 @@ app.enableAuth = function(options) {
}, },
}; };
var e = new Error(messages[errStatusCode].message || messages[403].message); const e = new Error(messages[errStatusCode].message || messages[403].message);
e.statusCode = errStatusCode; e.statusCode = errStatusCode;
e.code = messages[errStatusCode].code || messages[403].code; e.code = messages[errStatusCode].code || messages[403].code;
next(e); next(e);
@ -547,7 +547,7 @@ app.boot = function(options) {
}; };
function dataSourcesFromConfig(name, config, connectorRegistry, registry) { function dataSourcesFromConfig(name, config, connectorRegistry, registry) {
var connectorPath; let connectorPath;
assert(typeof config === 'object', assert(typeof config === 'object',
'can not create data source without config object'); 'can not create data source without config object');
@ -574,7 +574,7 @@ function configureModel(ModelCtor, config, app) {
assert(ModelCtor.prototype instanceof ModelCtor.registry.getModel('Model'), assert(ModelCtor.prototype instanceof ModelCtor.registry.getModel('Model'),
ModelCtor.modelName + ' must be a descendant of loopback.Model'); ModelCtor.modelName + ' must be a descendant of loopback.Model');
var dataSource = config.dataSource; let dataSource = config.dataSource;
if (dataSource) { if (dataSource) {
if (typeof dataSource === 'string') { if (typeof dataSource === 'string') {
@ -627,15 +627,15 @@ function clearHandlerCache(app) {
* as the request handler. * as the request handler.
*/ */
app.listen = function(cb) { app.listen = function(cb) {
var self = this; const self = this;
var server = require('http').createServer(this); const server = require('http').createServer(this);
server.on('listening', function() { server.on('listening', function() {
self.set('port', this.address().port); self.set('port', this.address().port);
var listeningOnAll = false; let listeningOnAll = false;
var host = self.get('host'); let host = self.get('host');
if (!host) { if (!host) {
listeningOnAll = true; listeningOnAll = true;
host = this.address().address; host = this.address().address;
@ -650,17 +650,17 @@ app.listen = function(cb) {
// that can be copied and pasted into the browser. // that can be copied and pasted into the browser.
host = 'localhost'; host = 'localhost';
} }
var url = 'http://' + host + ':' + self.get('port') + '/'; const url = 'http://' + host + ':' + self.get('port') + '/';
self.set('url', url); self.set('url', url);
} }
}); });
var useAppConfig = const useAppConfig =
arguments.length === 0 || arguments.length === 0 ||
(arguments.length == 1 && typeof arguments[0] == 'function'); (arguments.length == 1 && typeof arguments[0] == 'function');
if (useAppConfig) { if (useAppConfig) {
var port = this.get('port'); let port = this.get('port');
// NOTE(bajtos) port:undefined no longer works on node@6, // NOTE(bajtos) port:undefined no longer works on node@6,
// we must pass port:0 explicitly // we must pass port:0 explicitly
if (port === undefined) port = 0; if (port === undefined) port = 0;

View File

@ -4,8 +4,8 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter;
var util = require('util'); const util = require('util');
module.exports = browserExpress; module.exports = browserExpress;

View File

@ -74,7 +74,7 @@ module.exports = function(registry) {
// object instance it loaded during the first call. // object instance it loaded during the first call.
definitionJson = cloneDeepJson(definitionJson); definitionJson = cloneDeepJson(definitionJson);
var Model = registry.createModel(definitionJson); const Model = registry.createModel(definitionJson);
customizeFn(Model); customizeFn(Model);
return Model; return Model;
} }

View File

@ -5,15 +5,15 @@
'use strict'; 'use strict';
var util = require('util'); const util = require('util');
var extend = require('util')._extend; const extend = require('util')._extend;
var g = require('./globalize'); const g = require('./globalize');
module.exports = function(modelCtor, remotingConfig, modelConfig) { module.exports = function(modelCtor, remotingConfig, modelConfig) {
var settings = {}; const settings = {};
// apply config.json settings // apply config.json settings
var configHasSharedMethodsSettings = remotingConfig && const configHasSharedMethodsSettings = remotingConfig &&
remotingConfig.sharedMethods && remotingConfig.sharedMethods &&
typeof remotingConfig.sharedMethods === 'object'; typeof remotingConfig.sharedMethods === 'object';
if (configHasSharedMethodsSettings) if (configHasSharedMethodsSettings)
@ -21,7 +21,7 @@ module.exports = function(modelCtor, remotingConfig, modelConfig) {
// apply model-config.json settings // apply model-config.json settings
const options = modelConfig.options; const options = modelConfig.options;
var modelConfigHasSharedMethodsSettings = options && const modelConfigHasSharedMethodsSettings = options &&
options.remoting && options.remoting &&
options.remoting.sharedMethods && options.remoting.sharedMethods &&
typeof options.remoting.sharedMethods === 'object'; typeof options.remoting.sharedMethods === 'object';
@ -30,30 +30,30 @@ module.exports = function(modelCtor, remotingConfig, modelConfig) {
// validate setting values // validate setting values
Object.keys(settings).forEach(function(setting) { Object.keys(settings).forEach(function(setting) {
var settingValue = settings[setting]; const settingValue = settings[setting];
var settingValueType = typeof settingValue; const settingValueType = typeof settingValue;
if (settingValueType !== 'boolean') if (settingValueType !== 'boolean')
throw new TypeError(g.f('Expected boolean, got %s', settingValueType)); throw new TypeError(g.f('Expected boolean, got %s', settingValueType));
}); });
// set sharedMethod.shared using the merged settings // set sharedMethod.shared using the merged settings
var sharedMethods = modelCtor.sharedClass.methods({includeDisabled: true}); const sharedMethods = modelCtor.sharedClass.methods({includeDisabled: true});
// re-map glob style values to regular expressions // re-map glob style values to regular expressions
var tests = Object const tests = Object
.keys(settings) .keys(settings)
.filter(function(setting) { .filter(function(setting) {
return settings.hasOwnProperty(setting) && setting.indexOf('*') >= 0; return settings.hasOwnProperty(setting) && setting.indexOf('*') >= 0;
}) })
.map(function(setting) { .map(function(setting) {
// Turn * into an testable regexp string // Turn * into an testable regexp string
var glob = escapeRegExp(setting).replace(/\*/g, '(.)*'); const glob = escapeRegExp(setting).replace(/\*/g, '(.)*');
return {regex: new RegExp(glob), setting: settings[setting]}; return {regex: new RegExp(glob), setting: settings[setting]};
}) || []; }) || [];
sharedMethods.forEach(function(sharedMethod) { sharedMethods.forEach(function(sharedMethod) {
// use the specific setting if it exists // use the specific setting if it exists
var methodName = sharedMethod.isStatic ? sharedMethod.name : 'prototype.' + sharedMethod.name; const methodName = sharedMethod.isStatic ? sharedMethod.name : 'prototype.' + sharedMethod.name;
var hasSpecificSetting = settings.hasOwnProperty(methodName); const hasSpecificSetting = settings.hasOwnProperty(methodName);
if (hasSpecificSetting) { if (hasSpecificSetting) {
if (settings[methodName] === false) { if (settings[methodName] === false) {
sharedMethod.sharedClass.disableMethodByName(methodName); sharedMethod.sharedClass.disableMethodByName(methodName);

View File

@ -14,11 +14,11 @@ module.exports = Connector;
* Module dependencies. * Module dependencies.
*/ */
var EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter;
var debug = require('debug')('connector'); const debug = require('debug')('connector');
var util = require('util'); const util = require('util');
var inherits = util.inherits; const inherits = util.inherits;
var assert = require('assert'); const assert = require('assert');
/** /**
* Create a new `Connector` with the given `options`. * Create a new `Connector` with the given `options`.
@ -45,7 +45,7 @@ inherits(Connector, EventEmitter);
*/ */
Connector._createJDBAdapter = function(jdbModule) { Connector._createJDBAdapter = function(jdbModule) {
var fauxSchema = {}; const fauxSchema = {};
jdbModule.initialize(fauxSchema, function() { jdbModule.initialize(fauxSchema, function() {
// connected // connected
}); });

View File

@ -8,11 +8,11 @@
*/ */
'use strict'; 'use strict';
var g = require('../globalize'); const g = require('../globalize');
var mailer = require('nodemailer'); const mailer = require('nodemailer');
var assert = require('assert'); const assert = require('assert');
var debug = require('debug')('loopback:connector:mail'); const debug = require('debug')('loopback:connector:mail');
var loopback = require('../loopback'); const loopback = require('../loopback');
/** /**
* Export the MailConnector class. * Export the MailConnector class.
@ -27,7 +27,7 @@ module.exports = MailConnector;
function MailConnector(settings) { function MailConnector(settings) {
assert(typeof settings === 'object', 'cannot initialize MailConnector without a settings object'); assert(typeof settings === 'object', 'cannot initialize MailConnector without a settings object');
var transports = settings.transports; let transports = settings.transports;
// if transports is not in settings object AND settings.transport exists // if transports is not in settings object AND settings.transport exists
if (!transports && settings.transport) { if (!transports && settings.transport) {
@ -74,17 +74,17 @@ MailConnector.prototype.DataAccessObject = Mailer;
*/ */
MailConnector.prototype.setupTransport = function(setting) { MailConnector.prototype.setupTransport = function(setting) {
var connector = this; const connector = this;
connector.transports = connector.transports || []; connector.transports = connector.transports || [];
connector.transportsIndex = connector.transportsIndex || {}; connector.transportsIndex = connector.transportsIndex || {};
var transport; let transport;
var transportType = (setting.type || 'STUB').toLowerCase(); const transportType = (setting.type || 'STUB').toLowerCase();
if (transportType === 'smtp') { if (transportType === 'smtp') {
transport = mailer.createTransport(setting); transport = mailer.createTransport(setting);
} else { } else {
var transportModuleName = 'nodemailer-' + transportType + '-transport'; const transportModuleName = 'nodemailer-' + transportType + '-transport';
var transportModule = require(transportModuleName); const transportModule = require(transportModuleName);
transport = mailer.createTransport(transportModule(setting)); transport = mailer.createTransport(transportModule(setting));
} }
@ -138,12 +138,12 @@ MailConnector.prototype.defaultTransport = function() {
*/ */
Mailer.send = function(options, fn) { Mailer.send = function(options, fn) {
var dataSource = this.dataSource; const dataSource = this.dataSource;
var settings = dataSource && dataSource.settings; const settings = dataSource && dataSource.settings;
var connector = dataSource.connector; const connector = dataSource.connector;
assert(connector, 'Cannot send mail without a connector!'); assert(connector, 'Cannot send mail without a connector!');
var transport = connector.transportForName(options.transport); let transport = connector.transportForName(options.transport);
if (!transport) { if (!transport) {
transport = connector.defaultTransport(); transport = connector.defaultTransport();

View File

@ -14,12 +14,12 @@ module.exports = Memory;
* Module dependencies. * Module dependencies.
*/ */
var Connector = require('./base-connector'); const Connector = require('./base-connector');
var debug = require('debug')('memory'); const debug = require('debug')('memory');
var util = require('util'); const util = require('util');
var inherits = util.inherits; const inherits = util.inherits;
var assert = require('assert'); const assert = require('assert');
var JdbMemory = require('loopback-datasource-juggler/lib/connectors/memory'); const JdbMemory = require('loopback-datasource-juggler/lib/connectors/memory');
/** /**
* Create a new `Memory` connector with the given `options`. * Create a new `Memory` connector with the given `options`.

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var g = require('./globalize'); const g = require('./globalize');
var juggler = require('loopback-datasource-juggler'); const juggler = require('loopback-datasource-juggler');
var remoting = require('strong-remoting'); const remoting = require('strong-remoting');
module.exports = function(loopback) { module.exports = function(loopback) {
juggler.getCurrentContext = juggler.getCurrentContext =

View File

@ -4,8 +4,8 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var path = require('path'); const path = require('path');
var SG = require('strong-globalize'); const SG = require('strong-globalize');
SG.SetRootDir(path.join(__dirname, '..'), {autonomousMsgLoading: 'all'}); SG.SetRootDir(path.join(__dirname, '..'), {autonomousMsgLoading: 'all'});
module.exports = SG(); module.exports = SG();

View File

@ -8,17 +8,17 @@
*/ */
'use strict'; 'use strict';
var express = require('express'); const express = require('express');
var loopbackExpress = require('./server-app'); const loopbackExpress = require('./server-app');
var proto = require('./application'); const proto = require('./application');
var fs = require('fs'); const fs = require('fs');
var ejs = require('ejs'); const ejs = require('ejs');
var path = require('path'); const path = require('path');
var merge = require('util')._extend; const merge = require('util')._extend;
var assert = require('assert'); const assert = require('assert');
var Registry = require('./registry'); const Registry = require('./registry');
var juggler = require('loopback-datasource-juggler'); const juggler = require('loopback-datasource-juggler');
var configureSharedMethods = require('./configure-shared-methods'); const configureSharedMethods = require('./configure-shared-methods');
/** /**
* LoopBack core module. It provides static properties and * LoopBack core module. It provides static properties and
@ -40,7 +40,7 @@ var configureSharedMethods = require('./configure-shared-methods');
* @header loopback * @header loopback
*/ */
var loopback = module.exports = createApplication; const loopback = module.exports = createApplication;
/*! /*!
* Framework version. * Framework version.
@ -73,7 +73,7 @@ Object.defineProperties(loopback, {
*/ */
function createApplication(options) { function createApplication(options) {
var app = loopbackExpress(); const app = loopbackExpress();
merge(app, proto); merge(app, proto);
@ -107,7 +107,7 @@ function createApplication(options) {
if (loopback.localRegistry || options && options.localRegistry === true) { if (loopback.localRegistry || options && options.localRegistry === true) {
// setup the app registry // setup the app registry
var registry = app.registry = new Registry(); const registry = app.registry = new Registry();
if (options && options.loadBuiltinModels === true) { if (options && options.loadBuiltinModels === true) {
require('./builtin-models')(registry); require('./builtin-models')(registry);
} }
@ -119,8 +119,8 @@ function createApplication(options) {
} }
function mixin(source) { function mixin(source) {
for (var key in source) { for (const key in source) {
var desc = Object.getOwnPropertyDescriptor(source, key); const desc = Object.getOwnPropertyDescriptor(source, key);
// Fix for legacy (pre-ES5) browsers like PhantomJS // Fix for legacy (pre-ES5) browsers like PhantomJS
if (!desc) continue; if (!desc) continue;
@ -204,8 +204,8 @@ loopback.remoteMethod = function(fn, options) {
*/ */
loopback.template = function(file) { loopback.template = function(file) {
var templates = this._templates || (this._templates = {}); const templates = this._templates || (this._templates = {});
var str = templates[file] || (templates[file] = fs.readFileSync(file, 'utf8')); const str = templates[file] || (templates[file] = fs.readFileSync(file, 'utf8'));
return ejs.compile(str, { return ejs.compile(str, {
filename: file, filename: file,
}); });

View File

@ -7,14 +7,14 @@
* Module Dependencies. * Module Dependencies.
*/ */
'use strict'; 'use strict';
var g = require('./globalize'); const g = require('./globalize');
var assert = require('assert'); const assert = require('assert');
var debug = require('debug')('loopback:model'); const debug = require('debug')('loopback:model');
var RemoteObjects = require('strong-remoting'); const RemoteObjects = require('strong-remoting');
var SharedClass = require('strong-remoting').SharedClass; const SharedClass = require('strong-remoting').SharedClass;
var extend = require('util')._extend; const extend = require('util')._extend;
var deprecated = require('depd')('loopback'); const deprecated = require('depd')('loopback');
module.exports = function(registry) { module.exports = function(registry) {
/** /**
@ -104,7 +104,7 @@ module.exports = function(registry) {
* @property {Array.<Object>} settings.acls Array of ACLs for the model. * @property {Array.<Object>} settings.acls Array of ACLs for the model.
* @class * @class
*/ */
var Model = registry.modelBuilder.define('Model'); const Model = registry.modelBuilder.define('Model');
Model.registry = registry; Model.registry = registry;
@ -115,23 +115,23 @@ module.exports = function(registry) {
*/ */
Model.setup = function() { Model.setup = function() {
var ModelCtor = this; const ModelCtor = this;
var Parent = this.super_; const Parent = this.super_;
if (!ModelCtor.registry && Parent && Parent.registry) { if (!ModelCtor.registry && Parent && Parent.registry) {
ModelCtor.registry = Parent.registry; ModelCtor.registry = Parent.registry;
} }
var options = this.settings; const options = this.settings;
var typeName = this.modelName; const typeName = this.modelName;
// support remoting prototype methods // support remoting prototype methods
// it's important to setup this function *before* calling `new SharedClass` // it's important to setup this function *before* calling `new SharedClass`
// otherwise remoting metadata from our base model is picked up // otherwise remoting metadata from our base model is picked up
ModelCtor.sharedCtor = function(data, id, options, fn) { ModelCtor.sharedCtor = function(data, id, options, fn) {
var ModelCtor = this; const ModelCtor = this;
var isRemoteInvocationWithOptions = typeof data !== 'object' && const isRemoteInvocationWithOptions = typeof data !== 'object' &&
typeof id === 'object' && typeof id === 'object' &&
typeof options === 'function'; typeof options === 'function';
if (isRemoteInvocationWithOptions) { if (isRemoteInvocationWithOptions) {
@ -161,13 +161,13 @@ module.exports = function(registry) {
} }
if (id != null && data) { if (id != null && data) {
var model = new ModelCtor(data); const model = new ModelCtor(data);
model.id = id; model.id = id;
fn(null, model); fn(null, model);
} else if (data) { } else if (data) {
fn(null, new ModelCtor(data)); fn(null, new ModelCtor(data));
} else if (id != null) { } else if (id != null) {
var filter = {}; const filter = {};
ModelCtor.findById(id, filter, options, function(err, model) { ModelCtor.findById(id, filter, options, function(err, model) {
if (err) { if (err) {
fn(err); fn(err);
@ -185,7 +185,7 @@ module.exports = function(registry) {
} }
}; };
var idDesc = ModelCtor.modelName + ' id'; const idDesc = ModelCtor.modelName + ' id';
ModelCtor.sharedCtor.accepts = [ ModelCtor.sharedCtor.accepts = [
{arg: 'id', type: 'any', required: true, http: {source: 'path'}, {arg: 'id', type: 'any', required: true, http: {source: 'path'},
description: idDesc}, description: idDesc},
@ -199,11 +199,11 @@ module.exports = function(registry) {
ModelCtor.sharedCtor.returns = {root: true}; ModelCtor.sharedCtor.returns = {root: true};
var remotingOptions = {}; const remotingOptions = {};
extend(remotingOptions, options.remoting || {}); extend(remotingOptions, options.remoting || {});
// create a sharedClass // create a sharedClass
var sharedClass = ModelCtor.sharedClass = new SharedClass( const sharedClass = ModelCtor.sharedClass = new SharedClass(
ModelCtor.modelName, ModelCtor.modelName,
ModelCtor, ModelCtor,
remotingOptions remotingOptions
@ -211,9 +211,9 @@ module.exports = function(registry) {
// before remote hook // before remote hook
ModelCtor.beforeRemote = function(name, fn) { ModelCtor.beforeRemote = function(name, fn) {
var className = this.modelName; const className = this.modelName;
this._runWhenAttachedToApp(function(app) { this._runWhenAttachedToApp(function(app) {
var remotes = app.remotes(); const remotes = app.remotes();
remotes.before(className + '.' + name, function(ctx, next) { remotes.before(className + '.' + name, function(ctx, next) {
return fn(ctx, ctx.result, next); return fn(ctx, ctx.result, next);
}); });
@ -222,9 +222,9 @@ module.exports = function(registry) {
// after remote hook // after remote hook
ModelCtor.afterRemote = function(name, fn) { ModelCtor.afterRemote = function(name, fn) {
var className = this.modelName; const className = this.modelName;
this._runWhenAttachedToApp(function(app) { this._runWhenAttachedToApp(function(app) {
var remotes = app.remotes(); const remotes = app.remotes();
remotes.after(className + '.' + name, function(ctx, next) { remotes.after(className + '.' + name, function(ctx, next) {
return fn(ctx, ctx.result, next); return fn(ctx, ctx.result, next);
}); });
@ -232,16 +232,16 @@ module.exports = function(registry) {
}; };
ModelCtor.afterRemoteError = function(name, fn) { ModelCtor.afterRemoteError = function(name, fn) {
var className = this.modelName; const className = this.modelName;
this._runWhenAttachedToApp(function(app) { this._runWhenAttachedToApp(function(app) {
var remotes = app.remotes(); const remotes = app.remotes();
remotes.afterError(className + '.' + name, fn); remotes.afterError(className + '.' + name, fn);
}); });
}; };
ModelCtor._runWhenAttachedToApp = function(fn) { ModelCtor._runWhenAttachedToApp = function(fn) {
if (this.app) return fn(this.app); if (this.app) return fn(this.app);
var self = this; const self = this;
self.once('attached', function() { self.once('attached', function() {
fn(self.app); fn(self.app);
}); });
@ -261,8 +261,8 @@ module.exports = function(registry) {
// resolve relation functions // resolve relation functions
sharedClass.resolve(function resolver(define) { sharedClass.resolve(function resolver(define) {
var relations = ModelCtor.relations || {}; const relations = ModelCtor.relations || {};
var defineRaw = define; const defineRaw = define;
define = function(name, options, fn) { define = function(name, options, fn) {
if (options.accepts) { if (options.accepts) {
options = extend({}, options); options = extend({}, options);
@ -272,8 +272,8 @@ module.exports = function(registry) {
}; };
// get the relations // get the relations
for (var relationName in relations) { for (const relationName in relations) {
var relation = relations[relationName]; const relation = relations[relationName];
if (relation.type === 'belongsTo') { if (relation.type === 'belongsTo') {
ModelCtor.belongsToRemoting(relationName, relation, define); ModelCtor.belongsToRemoting(relationName, relation, define);
} else if ( } else if (
@ -295,8 +295,8 @@ module.exports = function(registry) {
} }
// handle scopes // handle scopes
var scopes = ModelCtor.scopes || {}; const scopes = ModelCtor.scopes || {};
for (var scopeName in scopes) { for (const scopeName in scopes) {
ModelCtor.scopeRemoting(scopeName, scopes[scopeName], define); ModelCtor.scopeRemoting(scopeName, scopes[scopeName], define);
} }
}); });
@ -307,9 +307,9 @@ module.exports = function(registry) {
/*! /*!
* Get the reference to ACL in a lazy fashion to avoid race condition in require * Get the reference to ACL in a lazy fashion to avoid race condition in require
*/ */
var _aclModel = null; let _aclModel = null;
Model._ACL = function getACL(ACL) { Model._ACL = function getACL(ACL) {
var registry = this.registry; const registry = this.registry;
if (ACL !== undefined) { if (ACL !== undefined) {
// The function is used as a setter // The function is used as a setter
_aclModel = ACL; _aclModel = ACL;
@ -317,7 +317,7 @@ module.exports = function(registry) {
if (_aclModel) { if (_aclModel) {
return _aclModel; return _aclModel;
} }
var aclModel = registry.getModel('ACL'); const aclModel = registry.getModel('ACL');
_aclModel = registry.getModelByType(aclModel); _aclModel = registry.getModelByType(aclModel);
return _aclModel; return _aclModel;
}; };
@ -335,9 +335,9 @@ module.exports = function(registry) {
*/ */
Model.checkAccess = function(token, modelId, sharedMethod, ctx, callback) { Model.checkAccess = function(token, modelId, sharedMethod, ctx, callback) {
var ANONYMOUS = registry.getModel('AccessToken').ANONYMOUS; const ANONYMOUS = registry.getModel('AccessToken').ANONYMOUS;
token = token || ANONYMOUS; token = token || ANONYMOUS;
var aclModel = Model._ACL(); const aclModel = Model._ACL();
ctx = ctx || {}; ctx = ctx || {};
if (typeof ctx === 'function' && callback === undefined) { if (typeof ctx === 'function' && callback === undefined) {
@ -376,7 +376,7 @@ module.exports = function(registry) {
'method is a required argument and must be a RemoteMethod object' 'method is a required argument and must be a RemoteMethod object'
); );
var ACL = Model._ACL(); const ACL = Model._ACL();
// Check the explicit setting of accessType // Check the explicit setting of accessType
if (method.accessType) { if (method.accessType) {
@ -390,7 +390,7 @@ module.exports = function(registry) {
} }
// Default GET requests to READ // Default GET requests to READ
var verb = method.http && method.http.verb; let verb = method.http && method.http.verb;
if (typeof verb === 'string') { if (typeof verb === 'string') {
verb = verb.toUpperCase(); verb = verb.toUpperCase();
} }
@ -438,7 +438,7 @@ module.exports = function(registry) {
*/ */
Model.getApp = function(callback) { Model.getApp = function(callback) {
var self = this; const self = this;
self._runWhenAttachedToApp(function(app) { self._runWhenAttachedToApp(function(app) {
assert(self.app); assert(self.app);
assert.equal(app, self.app); assert.equal(app, self.app);
@ -463,7 +463,7 @@ module.exports = function(registry) {
Model.remoteMethod = function(name, options) { Model.remoteMethod = function(name, options) {
if (options.isStatic === undefined) { if (options.isStatic === undefined) {
var m = name.match(/^prototype\.(.*)$/); const m = name.match(/^prototype\.(.*)$/);
options.isStatic = !m; options.isStatic = !m;
name = options.isStatic ? name : m[1]; name = options.isStatic ? name : m[1];
} }
@ -492,13 +492,13 @@ module.exports = function(registry) {
} }
function createOptionsViaModelMethod(ctx) { function createOptionsViaModelMethod(ctx) {
var ModelCtor = (ctx.method && ctx.method.ctor) || this; const ModelCtor = (ctx.method && ctx.method.ctor) || this;
/** /**
* Configure default values for juggler settings to protect user-supplied * Configure default values for juggler settings to protect user-supplied
* input from attacking juggler * input from attacking juggler
*/ */
var DEFAULT_OPTIONS = { const DEFAULT_OPTIONS = {
// Default to `true` so that hidden properties cannot be used in query // Default to `true` so that hidden properties cannot be used in query
prohibitHiddenPropertiesInQuery: ModelCtor._getProhibitHiddenPropertiesInQuery({}, true), prohibitHiddenPropertiesInQuery: ModelCtor._getProhibitHiddenPropertiesInQuery({}, true),
// Default to `12` for the max depth of a query object // Default to `12` for the max depth of a query object
@ -526,7 +526,7 @@ module.exports = function(registry) {
Model.disableRemoteMethod = function(name, isStatic) { Model.disableRemoteMethod = function(name, isStatic) {
deprecated('Model.disableRemoteMethod is deprecated. ' + deprecated('Model.disableRemoteMethod is deprecated. ' +
'Use Model.disableRemoteMethodByName instead.'); 'Use Model.disableRemoteMethodByName instead.');
var key = this.sharedClass.getKeyFromMethodNameAndTarget(name, isStatic); const key = this.sharedClass.getKeyFromMethodNameAndTarget(name, isStatic);
this.sharedClass.disableMethodByName(key); this.sharedClass.disableMethodByName(key);
this.emit('remoteMethodDisabled', this.sharedClass, key); this.emit('remoteMethodDisabled', this.sharedClass, key);
}; };
@ -544,10 +544,10 @@ module.exports = function(registry) {
}; };
Model.belongsToRemoting = function(relationName, relation, define) { Model.belongsToRemoting = function(relationName, relation, define) {
var modelName = relation.modelTo && relation.modelTo.modelName; let modelName = relation.modelTo && relation.modelTo.modelName;
modelName = modelName || 'PersistedModel'; modelName = modelName || 'PersistedModel';
var fn = this.prototype[relationName]; const fn = this.prototype[relationName];
var pathName = (relation.options.http && relation.options.http.path) || relationName; const pathName = (relation.options.http && relation.options.http.path) || relationName;
define('__get__' + relationName, { define('__get__' + relationName, {
isStatic: false, isStatic: false,
http: {verb: 'get', path: '/' + pathName}, http: {verb: 'get', path: '/' + pathName},
@ -564,17 +564,17 @@ module.exports = function(registry) {
function convertNullToNotFoundError(toModelName, ctx, cb) { function convertNullToNotFoundError(toModelName, ctx, cb) {
if (ctx.result !== null) return cb(); if (ctx.result !== null) return cb();
var fk = ctx.getArgByName('fk'); const fk = ctx.getArgByName('fk');
var msg = g.f('Unknown "%s" id "%s".', toModelName, fk); const msg = g.f('Unknown "%s" id "%s".', toModelName, fk);
var error = new Error(msg); const error = new Error(msg);
error.statusCode = error.status = 404; error.statusCode = error.status = 404;
error.code = 'MODEL_NOT_FOUND'; error.code = 'MODEL_NOT_FOUND';
cb(error); cb(error);
} }
Model.hasOneRemoting = function(relationName, relation, define) { Model.hasOneRemoting = function(relationName, relation, define) {
var pathName = (relation.options.http && relation.options.http.path) || relationName; const pathName = (relation.options.http && relation.options.http.path) || relationName;
var toModelName = relation.modelTo.modelName; const toModelName = relation.modelTo.modelName;
define('__get__' + relationName, { define('__get__' + relationName, {
isStatic: false, isStatic: false,
@ -631,10 +631,10 @@ module.exports = function(registry) {
}; };
Model.hasManyRemoting = function(relationName, relation, define) { Model.hasManyRemoting = function(relationName, relation, define) {
var pathName = (relation.options.http && relation.options.http.path) || relationName; const pathName = (relation.options.http && relation.options.http.path) || relationName;
var toModelName = relation.modelTo.modelName; const toModelName = relation.modelTo.modelName;
var findByIdFunc = this.prototype['__findById__' + relationName]; const findByIdFunc = this.prototype['__findById__' + relationName];
define('__findById__' + relationName, { define('__findById__' + relationName, {
isStatic: false, isStatic: false,
http: {verb: 'get', path: '/' + pathName + '/:fk'}, http: {verb: 'get', path: '/' + pathName + '/:fk'},
@ -653,7 +653,7 @@ module.exports = function(registry) {
rest: {after: convertNullToNotFoundError.bind(null, toModelName)}, rest: {after: convertNullToNotFoundError.bind(null, toModelName)},
}, findByIdFunc); }, findByIdFunc);
var destroyByIdFunc = this.prototype['__destroyById__' + relationName]; const destroyByIdFunc = this.prototype['__destroyById__' + relationName];
define('__destroyById__' + relationName, { define('__destroyById__' + relationName, {
isStatic: false, isStatic: false,
http: {verb: 'delete', path: '/' + pathName + '/:fk'}, http: {verb: 'delete', path: '/' + pathName + '/:fk'},
@ -671,7 +671,7 @@ module.exports = function(registry) {
returns: [], returns: [],
}, destroyByIdFunc); }, destroyByIdFunc);
var updateByIdFunc = this.prototype['__updateById__' + relationName]; const updateByIdFunc = this.prototype['__updateById__' + relationName];
define('__updateById__' + relationName, { define('__updateById__' + relationName, {
isStatic: false, isStatic: false,
http: {verb: 'put', path: '/' + pathName + '/:fk'}, http: {verb: 'put', path: '/' + pathName + '/:fk'},
@ -689,9 +689,9 @@ module.exports = function(registry) {
}, updateByIdFunc); }, updateByIdFunc);
if (relation.modelThrough || relation.type === 'referencesMany') { if (relation.modelThrough || relation.type === 'referencesMany') {
var modelThrough = relation.modelThrough || relation.modelTo; const modelThrough = relation.modelThrough || relation.modelTo;
var accepts = []; const accepts = [];
if (relation.type === 'hasMany' && relation.modelThrough) { if (relation.type === 'hasMany' && relation.modelThrough) {
// Restrict: only hasManyThrough relation can have additional properties // Restrict: only hasManyThrough relation can have additional properties
accepts.push({ accepts.push({
@ -700,7 +700,7 @@ module.exports = function(registry) {
}); });
} }
var addFunc = this.prototype['__link__' + relationName]; const addFunc = this.prototype['__link__' + relationName];
define('__link__' + relationName, { define('__link__' + relationName, {
isStatic: false, isStatic: false,
http: {verb: 'put', path: '/' + pathName + '/rel/:fk'}, http: {verb: 'put', path: '/' + pathName + '/rel/:fk'},
@ -716,7 +716,7 @@ module.exports = function(registry) {
returns: {arg: relationName, type: modelThrough.modelName, root: true}, returns: {arg: relationName, type: modelThrough.modelName, root: true},
}, addFunc); }, addFunc);
var removeFunc = this.prototype['__unlink__' + relationName]; const removeFunc = this.prototype['__unlink__' + relationName];
define('__unlink__' + relationName, { define('__unlink__' + relationName, {
isStatic: false, isStatic: false,
http: {verb: 'delete', path: '/' + pathName + '/rel/:fk'}, http: {verb: 'delete', path: '/' + pathName + '/rel/:fk'},
@ -736,7 +736,7 @@ module.exports = function(registry) {
// FIXME: [rfeng] How to map a function with callback(err, true|false) to HEAD? // FIXME: [rfeng] How to map a function with callback(err, true|false) to HEAD?
// true --> 200 and false --> 404? // true --> 200 and false --> 404?
var existsFunc = this.prototype['__exists__' + relationName]; const existsFunc = this.prototype['__exists__' + relationName];
define('__exists__' + relationName, { define('__exists__' + relationName, {
isStatic: false, isStatic: false,
http: {verb: 'head', path: '/' + pathName + '/rel/:fk'}, http: {verb: 'head', path: '/' + pathName + '/rel/:fk'},
@ -756,10 +756,10 @@ module.exports = function(registry) {
// After hook to map exists to 200/404 for HEAD // After hook to map exists to 200/404 for HEAD
after: function(ctx, cb) { after: function(ctx, cb) {
if (ctx.result === false) { if (ctx.result === false) {
var modelName = ctx.method.sharedClass.name; const modelName = ctx.method.sharedClass.name;
var id = ctx.getArgByName('id'); const id = ctx.getArgByName('id');
var msg = g.f('Unknown "%s" {{id}} "%s".', modelName, id); const msg = g.f('Unknown "%s" {{id}} "%s".', modelName, id);
var error = new Error(msg); const error = new Error(msg);
error.statusCode = error.status = 404; error.statusCode = error.status = 404;
error.code = 'MODEL_NOT_FOUND'; error.code = 'MODEL_NOT_FOUND';
cb(error); cb(error);
@ -773,17 +773,17 @@ module.exports = function(registry) {
}; };
Model.scopeRemoting = function(scopeName, scope, define) { Model.scopeRemoting = function(scopeName, scope, define) {
var pathName = const pathName =
(scope.options && scope.options.http && scope.options.http.path) || scopeName; (scope.options && scope.options.http && scope.options.http.path) || scopeName;
var modelTo = scope.modelTo; let modelTo = scope.modelTo;
var isStatic = scope.isStatic; const isStatic = scope.isStatic;
var toModelName = scope.modelTo.modelName; let toModelName = scope.modelTo.modelName;
// https://github.com/strongloop/loopback/issues/811 // https://github.com/strongloop/loopback/issues/811
// Check if the scope is for a hasMany relation // Check if the scope is for a hasMany relation
var relation = this.relations[scopeName]; const relation = this.relations[scopeName];
if (relation && relation.modelTo) { if (relation && relation.modelTo) {
// For a relation with through model, the toModelName should be the one // For a relation with through model, the toModelName should be the one
// from the target model // from the target model
@ -884,22 +884,22 @@ module.exports = function(registry) {
} }
options = options || {}; options = options || {};
var regExp = /^__([^_]+)__([^_]+)$/; const regExp = /^__([^_]+)__([^_]+)$/;
var relation = this.relations[relationName]; const relation = this.relations[relationName];
if (relation && relation._nestRemotingProcessed) { if (relation && relation._nestRemotingProcessed) {
return; // Prevent unwanted circular traversals! return; // Prevent unwanted circular traversals!
} else if (relation && relation.modelTo && relation.modelTo.sharedClass) { } else if (relation && relation.modelTo && relation.modelTo.sharedClass) {
relation._nestRemotingProcessed = true; relation._nestRemotingProcessed = true;
var self = this; const self = this;
var sharedClass = this.sharedClass; const sharedClass = this.sharedClass;
var sharedToClass = relation.modelTo.sharedClass; const sharedToClass = relation.modelTo.sharedClass;
var toModelName = relation.modelTo.modelName; const toModelName = relation.modelTo.modelName;
var pathName = options.pathName || relation.options.path || relationName; const pathName = options.pathName || relation.options.path || relationName;
var paramName = options.paramName || 'nk'; const paramName = options.paramName || 'nk';
var http = [].concat(sharedToClass.http || [])[0]; const http = [].concat(sharedToClass.http || [])[0];
var httpPath, acceptArgs; let httpPath, acceptArgs;
if (relation.multiple) { if (relation.multiple) {
httpPath = pathName + '/:' + paramName; httpPath = pathName + '/:' + paramName;
@ -921,30 +921,30 @@ module.exports = function(registry) {
// A method should return the method name to use, if it is to be // A method should return the method name to use, if it is to be
// included as a nested method - a falsy return value will skip. // included as a nested method - a falsy return value will skip.
var filter = filterCallback || options.filterMethod || function(method, relation) { const filter = filterCallback || options.filterMethod || function(method, relation) {
var matches = method.name.match(regExp); const matches = method.name.match(regExp);
if (matches) { if (matches) {
return '__' + matches[1] + '__' + relation.name + '__' + matches[2]; return '__' + matches[1] + '__' + relation.name + '__' + matches[2];
} }
}; };
sharedToClass.methods().forEach(function(method) { sharedToClass.methods().forEach(function(method) {
var methodName; let methodName;
if (!method.isStatic && (methodName = filter(method, relation))) { if (!method.isStatic && (methodName = filter(method, relation))) {
var prefix = relation.multiple ? '__findById__' : '__get__'; const prefix = relation.multiple ? '__findById__' : '__get__';
var getterName = options.getterName || (prefix + relationName); const getterName = options.getterName || (prefix + relationName);
var getterFn = relation.modelFrom.prototype[getterName]; const getterFn = relation.modelFrom.prototype[getterName];
if (typeof getterFn !== 'function') { if (typeof getterFn !== 'function') {
throw new Error(g.f('Invalid remote method: `%s`', getterName)); throw new Error(g.f('Invalid remote method: `%s`', getterName));
} }
var nestedFn = relation.modelTo.prototype[method.name]; const nestedFn = relation.modelTo.prototype[method.name];
if (typeof nestedFn !== 'function') { if (typeof nestedFn !== 'function') {
throw new Error(g.f('Invalid remote method: `%s`', method.name)); throw new Error(g.f('Invalid remote method: `%s`', method.name));
} }
var opts = {}; const opts = {};
opts.accepts = acceptArgs.concat(method.accepts || []); opts.accepts = acceptArgs.concat(method.accepts || []);
opts.returns = [].concat(method.returns || []); opts.returns = [].concat(method.returns || []);
@ -954,10 +954,10 @@ module.exports = function(registry) {
opts.rest.delegateTo = method; opts.rest.delegateTo = method;
opts.http = []; opts.http = [];
var routes = [].concat(method.http || []); const routes = [].concat(method.http || []);
routes.forEach(function(route) { routes.forEach(function(route) {
if (route.path) { if (route.path) {
var copy = extend({}, route); const copy = extend({}, route);
copy.path = httpPath + route.path; copy.path = httpPath + route.path;
opts.http.push(copy); opts.http.push(copy);
} }
@ -1015,19 +1015,19 @@ module.exports = function(registry) {
if (options.hooks === false) return; // don't inherit before/after hooks if (options.hooks === false) return; // don't inherit before/after hooks
self.once('mounted', function(app, sc, remotes) { self.once('mounted', function(app, sc, remotes) {
var listenerTree = extend({}, remotes.listenerTree || {}); const listenerTree = extend({}, remotes.listenerTree || {});
listenerTree.before = listenerTree.before || {}; listenerTree.before = listenerTree.before || {};
listenerTree.after = listenerTree.after || {}; listenerTree.after = listenerTree.after || {};
var beforeListeners = listenerTree.before[toModelName] || {}; const beforeListeners = listenerTree.before[toModelName] || {};
var afterListeners = listenerTree.after[toModelName] || {}; const afterListeners = listenerTree.after[toModelName] || {};
sharedClass.methods().forEach(function(method) { sharedClass.methods().forEach(function(method) {
var delegateTo = method.rest && method.rest.delegateTo; const delegateTo = method.rest && method.rest.delegateTo;
if (delegateTo && delegateTo.ctor == relation.modelTo) { if (delegateTo && delegateTo.ctor == relation.modelTo) {
var before = method.isStatic ? beforeListeners : beforeListeners['prototype']; const before = method.isStatic ? beforeListeners : beforeListeners['prototype'];
var after = method.isStatic ? afterListeners : afterListeners['prototype']; const after = method.isStatic ? afterListeners : afterListeners['prototype'];
var m = method.isStatic ? method.name : 'prototype.' + method.name; const m = method.isStatic ? method.name : 'prototype.' + method.name;
if (before && before[delegateTo.name]) { if (before && before[delegateTo.name]) {
self.beforeRemote(m, function(ctx, result, next) { self.beforeRemote(m, function(ctx, result, next) {
before[delegateTo.name]._listeners.call(null, ctx, next); before[delegateTo.name]._listeners.call(null, ctx, next);
@ -1042,7 +1042,7 @@ module.exports = function(registry) {
}); });
}); });
} else { } else {
var msg = g.f('Relation `%s` does not exist for model `%s`', relationName, this.modelName); const msg = g.f('Relation `%s` does not exist for model `%s`', relationName, this.modelName);
throw new Error(msg); throw new Error(msg);
} }
}; };

View File

@ -7,20 +7,20 @@
* Module Dependencies. * Module Dependencies.
*/ */
'use strict'; 'use strict';
var g = require('./globalize'); const g = require('./globalize');
var runtime = require('./runtime'); const runtime = require('./runtime');
var assert = require('assert'); const assert = require('assert');
var async = require('async'); const async = require('async');
var deprecated = require('depd')('loopback'); const deprecated = require('depd')('loopback');
var debug = require('debug')('loopback:persisted-model'); const debug = require('debug')('loopback:persisted-model');
var PassThrough = require('stream').PassThrough; const PassThrough = require('stream').PassThrough;
var utils = require('./utils'); const utils = require('./utils');
var filterNodes = require('loopback-filters'); const filterNodes = require('loopback-filters');
var REPLICATION_CHUNK_SIZE = -1; const REPLICATION_CHUNK_SIZE = -1;
module.exports = function(registry) { module.exports = function(registry) {
var Model = registry.getModel('Model'); const Model = registry.getModel('Model');
/** /**
* Extends Model with basic query and CRUD support. * Extends Model with basic query and CRUD support.
@ -38,7 +38,7 @@ module.exports = function(registry) {
* @class PersistedModel * @class PersistedModel
*/ */
var PersistedModel = Model.extend('PersistedModel'); const PersistedModel = Model.extend('PersistedModel');
/*! /*!
* Setup the `PersistedModel` constructor. * Setup the `PersistedModel` constructor.
@ -48,7 +48,7 @@ module.exports = function(registry) {
// call Model.setup first // call Model.setup first
Model.setup.call(this); Model.setup.call(this);
var PersistedModel = this; const PersistedModel = this;
// enable change tracking (usually for replication) // enable change tracking (usually for replication)
if (this.settings.trackChanges) { if (this.settings.trackChanges) {
@ -85,10 +85,10 @@ module.exports = function(registry) {
function convertNullToNotFoundError(ctx, cb) { function convertNullToNotFoundError(ctx, cb) {
if (ctx.result !== null) return cb(); if (ctx.result !== null) return cb();
var modelName = ctx.method.sharedClass.name; const modelName = ctx.method.sharedClass.name;
var id = ctx.getArgByName('id'); const id = ctx.getArgByName('id');
var msg = g.f('Unknown "%s" {{id}} "%s".', modelName, id); const msg = g.f('Unknown "%s" {{id}} "%s".', modelName, id);
var error = new Error(msg); const error = new Error(msg);
error.statusCode = error.status = 404; error.statusCode = error.status = 404;
error.code = 'MODEL_NOT_FOUND'; error.code = 'MODEL_NOT_FOUND';
cb(error); cb(error);
@ -403,7 +403,7 @@ module.exports = function(registry) {
*/ */
PersistedModel.prototype.save = function(options, callback) { PersistedModel.prototype.save = function(options, callback) {
var Model = this.constructor; const Model = this.constructor;
if (typeof options == 'function') { if (typeof options == 'function') {
callback = options; callback = options;
@ -421,9 +421,9 @@ module.exports = function(registry) {
options.throws = false; options.throws = false;
} }
var inst = this; const inst = this;
var data = inst.toObject(true); const data = inst.toObject(true);
var id = this.getId(); const id = this.getId();
if (!id) { if (!id) {
return Model.create(this, callback); return Model.create(this, callback);
@ -438,7 +438,7 @@ module.exports = function(registry) {
if (valid) { if (valid) {
save(); save();
} else { } else {
var err = new Model.ValidationError(inst); const err = new Model.ValidationError(inst);
// throws option is dangerous for async usage // throws option is dangerous for async usage
if (options.throws) { if (options.throws) {
throw err; throw err;
@ -581,7 +581,7 @@ module.exports = function(registry) {
*/ */
PersistedModel.prototype.setId = function(val) { PersistedModel.prototype.setId = function(val) {
var ds = this.getDataSource(); const ds = this.getDataSource();
this[this.getIdName()] = val; this[this.getIdName()] = val;
}; };
@ -592,7 +592,7 @@ module.exports = function(registry) {
*/ */
PersistedModel.prototype.getId = function() { PersistedModel.prototype.getId = function() {
var data = this.toObject(); const data = this.toObject();
if (!data) return; if (!data) return;
return data[this.getIdName()]; return data[this.getIdName()];
}; };
@ -614,8 +614,8 @@ module.exports = function(registry) {
*/ */
PersistedModel.getIdName = function() { PersistedModel.getIdName = function() {
var Model = this; const Model = this;
var ds = Model.getDataSource(); const ds = Model.getDataSource();
if (ds.idName) { if (ds.idName) {
return ds.idName(Model.modelName); return ds.idName(Model.modelName);
@ -625,9 +625,9 @@ module.exports = function(registry) {
}; };
PersistedModel.setupRemoting = function() { PersistedModel.setupRemoting = function() {
var PersistedModel = this; const PersistedModel = this;
var typeName = PersistedModel.modelName; const typeName = PersistedModel.modelName;
var options = PersistedModel.settings; const options = PersistedModel.settings;
// if there is atleast one updateOnly property, then we set // if there is atleast one updateOnly property, then we set
// createOnlyInstance flag in __create__ to indicate loopback-swagger // createOnlyInstance flag in __create__ to indicate loopback-swagger
@ -640,7 +640,7 @@ module.exports = function(registry) {
options.replaceOnPUT = options.replaceOnPUT !== false; options.replaceOnPUT = options.replaceOnPUT !== false;
function setRemoting(scope, name, options) { function setRemoting(scope, name, options) {
var fn = scope[name]; const fn = scope[name];
fn._delegate = true; fn._delegate = true;
options.isStatic = scope === PersistedModel; options.isStatic = scope === PersistedModel;
PersistedModel.remoteMethod(name, options); PersistedModel.remoteMethod(name, options);
@ -662,7 +662,7 @@ module.exports = function(registry) {
http: {verb: 'post', path: '/'}, http: {verb: 'post', path: '/'},
}); });
var upsertOptions = { const upsertOptions = {
aliases: ['upsert', 'updateOrCreate'], aliases: ['upsert', 'updateOrCreate'],
description: 'Patch an existing model instance or insert a new one ' + description: 'Patch an existing model instance or insert a new one ' +
'into the data source.', 'into the data source.',
@ -683,7 +683,7 @@ module.exports = function(registry) {
} }
setRemoting(PersistedModel, 'patchOrCreate', upsertOptions); setRemoting(PersistedModel, 'patchOrCreate', upsertOptions);
var replaceOrCreateOptions = { const replaceOrCreateOptions = {
description: 'Replace an existing model instance or insert a new one into the data source.', description: 'Replace an existing model instance or insert a new one into the data source.',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [ accepts: [
@ -741,10 +741,10 @@ module.exports = function(registry) {
return cb(); return cb();
} }
if (!ctx.result.exists) { if (!ctx.result.exists) {
var modelName = ctx.method.sharedClass.name; const modelName = ctx.method.sharedClass.name;
var id = ctx.getArgByName('id'); const id = ctx.getArgByName('id');
var msg = 'Unknown "' + modelName + '" id "' + id + '".'; const msg = 'Unknown "' + modelName + '" id "' + id + '".';
var error = new Error(msg); const error = new Error(msg);
error.statusCode = error.status = 404; error.statusCode = error.status = 404;
error.code = 'MODEL_NOT_FOUND'; error.code = 'MODEL_NOT_FOUND';
cb(error); cb(error);
@ -772,7 +772,7 @@ module.exports = function(registry) {
rest: {after: convertNullToNotFoundError}, rest: {after: convertNullToNotFoundError},
}); });
var replaceByIdOptions = { const replaceByIdOptions = {
description: 'Replace attributes for a model instance and persist it into the data source.', description: 'Replace attributes for a model instance and persist it into the data source.',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [ accepts: [
@ -889,7 +889,7 @@ module.exports = function(registry) {
http: {verb: 'get', path: '/count'}, http: {verb: 'get', path: '/count'},
}); });
var updateAttributesOptions = { const updateAttributesOptions = {
aliases: ['updateAttributes'], aliases: ['updateAttributes'],
description: 'Patch attributes for a model instance and persist it into ' + description: 'Patch attributes for a model instance and persist it into ' +
'the data source.', 'the data source.',
@ -1038,7 +1038,7 @@ module.exports = function(registry) {
*/ */
PersistedModel.diff = function(since, remoteChanges, callback) { PersistedModel.diff = function(since, remoteChanges, callback) {
var Change = this.getChangeModel(); const Change = this.getChangeModel();
Change.diff(this.modelName, since, remoteChanges, callback); Change.diff(this.modelName, since, remoteChanges, callback);
}; };
@ -1064,9 +1064,9 @@ module.exports = function(registry) {
filter = {}; filter = {};
} }
var idName = this.dataSource.idName(this.modelName); const idName = this.dataSource.idName(this.modelName);
var Change = this.getChangeModel(); const Change = this.getChangeModel();
var model = this; const model = this;
const changeFilter = this.createChangeFilter(since, filter); const changeFilter = this.createChangeFilter(since, filter);
filter = filter || {}; filter = filter || {};
@ -1078,13 +1078,13 @@ module.exports = function(registry) {
Change.find(changeFilter, function(err, changes) { Change.find(changeFilter, function(err, changes) {
if (err) return callback(err); if (err) return callback(err);
if (!Array.isArray(changes) || changes.length === 0) return callback(null, []); if (!Array.isArray(changes) || changes.length === 0) return callback(null, []);
var ids = changes.map(function(change) { const ids = changes.map(function(change) {
return change.getModelId(); return change.getModelId();
}); });
filter.where[idName] = {inq: ids}; filter.where[idName] = {inq: ids};
model.find(filter, function(err, models) { model.find(filter, function(err, models) {
if (err) return callback(err); if (err) return callback(err);
var modelIds = models.map(function(m) { const modelIds = models.map(function(m) {
return m[idName].toString(); return m[idName].toString();
}); });
callback(null, changes.filter(function(ch) { callback(null, changes.filter(function(ch) {
@ -1102,7 +1102,7 @@ module.exports = function(registry) {
*/ */
PersistedModel.checkpoint = function(cb) { PersistedModel.checkpoint = function(cb) {
var Checkpoint = this.getChangeModel().getCheckpointModel(); const Checkpoint = this.getChangeModel().getCheckpointModel();
Checkpoint.bumpLastSeq(cb); Checkpoint.bumpLastSeq(cb);
}; };
@ -1115,7 +1115,7 @@ module.exports = function(registry) {
*/ */
PersistedModel.currentCheckpoint = function(cb) { PersistedModel.currentCheckpoint = function(cb) {
var Checkpoint = this.getChangeModel().getCheckpointModel(); const Checkpoint = this.getChangeModel().getCheckpointModel();
Checkpoint.current(cb); Checkpoint.current(cb);
}; };
@ -1136,7 +1136,7 @@ module.exports = function(registry) {
*/ */
PersistedModel.replicate = function(since, targetModel, options, callback) { PersistedModel.replicate = function(since, targetModel, options, callback) {
var lastArg = arguments[arguments.length - 1]; const lastArg = arguments[arguments.length - 1];
if (typeof lastArg === 'function' && arguments.length > 1) { if (typeof lastArg === 'function' && arguments.length > 1) {
callback = lastArg; callback = lastArg;
@ -1157,7 +1157,7 @@ module.exports = function(registry) {
options = options || {}; options = options || {};
var sourceModel = this; const sourceModel = this;
callback = callback || utils.createPromiseCallback(); callback = callback || utils.createPromiseCallback();
debug('replicating %s since %s to %s since %s', debug('replicating %s since %s to %s since %s',
@ -1181,7 +1181,7 @@ module.exports = function(registry) {
// until no changes were replicated, but at most MAX_ATTEMPTS times // until no changes were replicated, but at most MAX_ATTEMPTS times
// to prevent starvation. In most cases, the second run will find no changes // to prevent starvation. In most cases, the second run will find no changes
// to replicate and we are done. // to replicate and we are done.
var MAX_ATTEMPTS = 3; const MAX_ATTEMPTS = 3;
run(1, since); run(1, since);
return callback.promise; return callback.promise;
@ -1191,7 +1191,7 @@ module.exports = function(registry) {
tryReplicate(sourceModel, targetModel, since, options, next); tryReplicate(sourceModel, targetModel, since, options, next);
function next(err, conflicts, cps, updates) { function next(err, conflicts, cps, updates) {
var finished = err || conflicts.length || const finished = err || conflicts.length ||
!updates || updates.length === 0 || !updates || updates.length === 0 ||
attempt >= MAX_ATTEMPTS; attempt >= MAX_ATTEMPTS;
@ -1203,10 +1203,10 @@ module.exports = function(registry) {
}; };
function tryReplicate(sourceModel, targetModel, since, options, callback) { function tryReplicate(sourceModel, targetModel, since, options, callback) {
var Change = sourceModel.getChangeModel(); const Change = sourceModel.getChangeModel();
var TargetChange = targetModel.getChangeModel(); const TargetChange = targetModel.getChangeModel();
var changeTrackingEnabled = Change && TargetChange; const changeTrackingEnabled = Change && TargetChange;
var replicationChunkSize = REPLICATION_CHUNK_SIZE; let replicationChunkSize = REPLICATION_CHUNK_SIZE;
if (sourceModel.settings && sourceModel.settings.replicationChunkSize) { if (sourceModel.settings && sourceModel.settings.replicationChunkSize) {
replicationChunkSize = sourceModel.settings.replicationChunkSize; replicationChunkSize = sourceModel.settings.replicationChunkSize;
@ -1217,9 +1217,9 @@ module.exports = function(registry) {
'You must enable change tracking before replicating' 'You must enable change tracking before replicating'
); );
var diff, updates, newSourceCp, newTargetCp; let diff, updates, newSourceCp, newTargetCp;
var tasks = [ const tasks = [
checkpoints, checkpoints,
getSourceChanges, getSourceChanges,
getDiffFromTarget, getDiffFromTarget,
@ -1304,7 +1304,7 @@ module.exports = function(registry) {
}); });
}, },
function(notUsed, err) { function(notUsed, err) {
var conflicts = err && err.details && err.details.conflicts; const conflicts = err && err.details && err.details.conflicts;
if (conflicts && err.statusCode == 409) { if (conflicts && err.statusCode == 409) {
diff.conflicts = conflicts; diff.conflicts = conflicts;
// filter out updates that were not applied // filter out updates that were not applied
@ -1321,7 +1321,7 @@ module.exports = function(registry) {
} }
function checkpoints() { function checkpoints() {
var cb = arguments[arguments.length - 1]; const cb = arguments[arguments.length - 1];
sourceModel.checkpoint(function(err, source) { sourceModel.checkpoint(function(err, source) {
if (err) return cb(err); if (err) return cb(err);
newSourceCp = source.seq; newSourceCp = source.seq;
@ -1345,7 +1345,7 @@ module.exports = function(registry) {
debug('\t\tnew checkpoints: { source: %j, target: %j }', debug('\t\tnew checkpoints: { source: %j, target: %j }',
newSourceCp, newTargetCp); newSourceCp, newTargetCp);
var conflicts = diff.conflicts.map(function(change) { const conflicts = diff.conflicts.map(function(change) {
return new Change.Conflict( return new Change.Conflict(
change.modelId, sourceModel, targetModel change.modelId, sourceModel, targetModel
); );
@ -1356,7 +1356,7 @@ module.exports = function(registry) {
} }
if (callback) { if (callback) {
var newCheckpoints = {source: newSourceCp, target: newTargetCp}; const newCheckpoints = {source: newSourceCp, target: newTargetCp};
callback(null, conflicts, newCheckpoints, updates); callback(null, conflicts, newCheckpoints, updates);
} }
} }
@ -1371,15 +1371,15 @@ module.exports = function(registry) {
*/ */
PersistedModel.createUpdates = function(deltas, cb) { PersistedModel.createUpdates = function(deltas, cb) {
var Change = this.getChangeModel(); const Change = this.getChangeModel();
var updates = []; const updates = [];
var Model = this; const Model = this;
var tasks = []; const tasks = [];
deltas.forEach(function(change) { deltas.forEach(function(change) {
change = new Change(change); change = new Change(change);
var type = change.type(); const type = change.type();
var update = {type: type, change: change}; const update = {type: type, change: change};
switch (type) { switch (type) {
case Change.CREATE: case Change.CREATE:
case Change.UPDATE: case Change.UPDATE:
@ -1423,12 +1423,12 @@ module.exports = function(registry) {
*/ */
PersistedModel.bulkUpdate = function(updates, options, callback) { PersistedModel.bulkUpdate = function(updates, options, callback) {
var tasks = []; const tasks = [];
var Model = this; const Model = this;
var Change = this.getChangeModel(); const Change = this.getChangeModel();
var conflicts = []; const conflicts = [];
var lastArg = arguments[arguments.length - 1]; const lastArg = arguments[arguments.length - 1];
if (typeof lastArg === 'function' && arguments.length > 1) { if (typeof lastArg === 'function' && arguments.length > 1) {
callback = lastArg; callback = lastArg;
@ -1444,8 +1444,8 @@ module.exports = function(registry) {
if (err) return callback(err); if (err) return callback(err);
updates.forEach(function(update) { updates.forEach(function(update) {
var id = update.change.modelId; const id = update.change.modelId;
var current = currentMap[id]; const current = currentMap[id];
switch (update.type) { switch (update.type) {
case Change.UPDATE: case Change.UPDATE:
tasks.push(function(cb) { tasks.push(function(cb) {
@ -1480,13 +1480,13 @@ module.exports = function(registry) {
}; };
function buildLookupOfAffectedModelData(Model, updates, callback) { function buildLookupOfAffectedModelData(Model, updates, callback) {
var idName = Model.dataSource.idName(Model.modelName); const idName = Model.dataSource.idName(Model.modelName);
var affectedIds = updates.map(function(u) { return u.change.modelId; }); const affectedIds = updates.map(function(u) { return u.change.modelId; });
var whereAffected = {}; const whereAffected = {};
whereAffected[idName] = {inq: affectedIds}; whereAffected[idName] = {inq: affectedIds};
Model.find({where: whereAffected}, function(err, affectedList) { Model.find({where: whereAffected}, function(err, affectedList) {
if (err) return callback(err); if (err) return callback(err);
var dataLookup = {}; const dataLookup = {};
affectedList.forEach(function(it) { affectedList.forEach(function(it) {
dataLookup[it[idName]] = it; dataLookup[it[idName]] = it;
}); });
@ -1495,8 +1495,8 @@ module.exports = function(registry) {
} }
function applyUpdate(Model, id, current, data, change, conflicts, options, cb) { function applyUpdate(Model, id, current, data, change, conflicts, options, cb) {
var Change = Model.getChangeModel(); const Change = Model.getChangeModel();
var rev = current ? Change.revisionForInst(current) : null; const rev = current ? Change.revisionForInst(current) : null;
if (rev !== change.prev) { if (rev !== change.prev) {
debug('Detected non-rectified change of %s %j', debug('Detected non-rectified change of %s %j',
@ -1515,7 +1515,7 @@ module.exports = function(registry) {
Model.updateAll(current.toObject(), data, options, function(err, result) { Model.updateAll(current.toObject(), data, options, function(err, result) {
if (err) return cb(err); if (err) return cb(err);
var count = result && result.count; const count = result && result.count;
switch (count) { switch (count) {
case 1: case 1:
// The happy path, exactly one record was updated // The happy path, exactly one record was updated
@ -1573,7 +1573,7 @@ module.exports = function(registry) {
Model.modelName, id); Model.modelName, id);
conflicts.push(change); conflicts.push(change);
var Change = Model.getChangeModel(); const Change = Model.getChangeModel();
return Change.rectifyModelChanges(Model.modelName, [id], cb); return Change.rectifyModelChanges(Model.modelName, [id], cb);
} }
} }
@ -1585,8 +1585,8 @@ module.exports = function(registry) {
return cb(); return cb();
} }
var Change = Model.getChangeModel(); const Change = Model.getChangeModel();
var rev = Change.revisionForInst(current); const rev = Change.revisionForInst(current);
if (rev !== change.prev) { if (rev !== change.prev) {
debug('Detected non-rectified change of %s %j', debug('Detected non-rectified change of %s %j',
Model.modelName, id); Model.modelName, id);
@ -1599,7 +1599,7 @@ module.exports = function(registry) {
Model.deleteAll(current.toObject(), options, function(err, result) { Model.deleteAll(current.toObject(), options, function(err, result) {
if (err) return cb(err); if (err) return cb(err);
var count = result && result.count; const count = result && result.count;
switch (count) { switch (count) {
case 1: case 1:
// The happy path, exactly one record was updated // The happy path, exactly one record was updated
@ -1640,8 +1640,8 @@ module.exports = function(registry) {
*/ */
PersistedModel.getChangeModel = function() { PersistedModel.getChangeModel = function() {
var changeModel = this.Change; const changeModel = this.Change;
var isSetup = changeModel && changeModel.dataSource; const isSetup = changeModel && changeModel.dataSource;
assert(isSetup, 'Cannot get a setup Change model for ' + this.modelName); assert(isSetup, 'Cannot get a setup Change model for ' + this.modelName);
@ -1657,7 +1657,7 @@ module.exports = function(registry) {
*/ */
PersistedModel.getSourceId = function(cb) { PersistedModel.getSourceId = function(cb) {
var dataSource = this.dataSource; const dataSource = this.dataSource;
if (!dataSource) { if (!dataSource) {
this.once('dataSourceAttached', this.getSourceId.bind(this, cb)); this.once('dataSourceAttached', this.getSourceId.bind(this, cb));
} }
@ -1665,7 +1665,7 @@ module.exports = function(registry) {
dataSource.connector.name, dataSource.connector.name,
'Model.getSourceId: cannot get id without dataSource.connector.name' 'Model.getSourceId: cannot get id without dataSource.connector.name'
); );
var id = [dataSource.connector.name, this.modelName].join('-'); const id = [dataSource.connector.name, this.modelName].join('-');
cb(null, id); cb(null, id);
}; };
@ -1674,17 +1674,17 @@ module.exports = function(registry) {
*/ */
PersistedModel.enableChangeTracking = function() { PersistedModel.enableChangeTracking = function() {
var Model = this; const Model = this;
var Change = this.Change || this._defineChangeModel(); const Change = this.Change || this._defineChangeModel();
var cleanupInterval = Model.settings.changeCleanupInterval || 30000; const cleanupInterval = Model.settings.changeCleanupInterval || 30000;
assert(this.dataSource, 'Cannot enableChangeTracking(): ' + this.modelName + assert(this.dataSource, 'Cannot enableChangeTracking(): ' + this.modelName +
' is not attached to a dataSource'); ' is not attached to a dataSource');
var idName = this.getIdName(); const idName = this.getIdName();
var idProp = this.definition.properties[idName]; const idProp = this.definition.properties[idName];
var idType = idProp && idProp.type; const idType = idProp && idProp.type;
var idDefn = idProp && idProp.defaultFn; const idDefn = idProp && idProp.defaultFn;
if (idType !== String || !(idDefn === 'uuid' || idDefn === 'guid')) { if (idType !== String || !(idDefn === 'uuid' || idDefn === 'guid')) {
deprecated('The model ' + this.modelName + ' is tracking changes, ' + deprecated('The model ' + this.modelName + ' is tracking changes, ' +
'which requires a string id with GUID/UUID default value.'); 'which requires a string id with GUID/UUID default value.');
@ -1714,8 +1714,8 @@ module.exports = function(registry) {
}; };
function rectifyOnSave(ctx, next) { function rectifyOnSave(ctx, next) {
var instance = ctx.instance || ctx.currentInstance; const instance = ctx.instance || ctx.currentInstance;
var id = instance ? instance.getId() : const id = instance ? instance.getId() :
getIdFromWhereByModelId(ctx.Model, ctx.where); getIdFromWhereByModelId(ctx.Model, ctx.where);
if (debug.enabled) { if (debug.enabled) {
@ -1740,7 +1740,7 @@ module.exports = function(registry) {
} }
function rectifyOnDelete(ctx, next) { function rectifyOnDelete(ctx, next) {
var id = ctx.instance ? ctx.instance.getId() : const id = ctx.instance ? ctx.instance.getId() :
getIdFromWhereByModelId(ctx.Model, ctx.where); getIdFromWhereByModelId(ctx.Model, ctx.where);
if (debug.enabled) { if (debug.enabled) {
@ -1764,10 +1764,10 @@ module.exports = function(registry) {
} }
function getIdFromWhereByModelId(Model, where) { function getIdFromWhereByModelId(Model, where) {
var idName = Model.getIdName(); const idName = Model.getIdName();
if (!(idName in where)) return undefined; if (!(idName in where)) return undefined;
var id = where[idName]; const id = where[idName];
// TODO(bajtos) support object values that are not LB conditions // TODO(bajtos) support object values that are not LB conditions
if (typeof id === 'string' || typeof id === 'number') { if (typeof id === 'string' || typeof id === 'number') {
return id; return id;
@ -1776,7 +1776,7 @@ module.exports = function(registry) {
} }
PersistedModel._defineChangeModel = function() { PersistedModel._defineChangeModel = function() {
var BaseChangeModel = this.registry.getModel('Change'); const BaseChangeModel = this.registry.getModel('Change');
assert(BaseChangeModel, assert(BaseChangeModel,
'Change model must be defined before enabling change replication'); 'Change model must be defined before enabling change replication');
@ -1794,7 +1794,7 @@ module.exports = function(registry) {
} }
// Re-attach related models whenever our datasource is changed. // Re-attach related models whenever our datasource is changed.
var self = this; const self = this;
this.on('dataSourceAttached', function() { this.on('dataSourceAttached', function() {
attachRelatedModels(self); attachRelatedModels(self);
}); });
@ -1832,17 +1832,17 @@ module.exports = function(registry) {
*/ */
PersistedModel.rectifyChange = function(id, callback) { PersistedModel.rectifyChange = function(id, callback) {
var Change = this.getChangeModel(); const Change = this.getChangeModel();
Change.rectifyModelChanges(this.modelName, [id], callback); Change.rectifyModelChanges(this.modelName, [id], callback);
}; };
PersistedModel.findLastChange = function(id, cb) { PersistedModel.findLastChange = function(id, cb) {
var Change = this.getChangeModel(); const Change = this.getChangeModel();
Change.findOne({where: {modelId: id}}, cb); Change.findOne({where: {modelId: id}}, cb);
}; };
PersistedModel.updateLastChange = function(id, data, cb) { PersistedModel.updateLastChange = function(id, data, cb) {
var self = this; const self = this;
this.findLastChange(id, function(err, inst) { this.findLastChange(id, function(err, inst) {
if (err) return cb(err); if (err) return cb(err);
if (!inst) { if (!inst) {
@ -1873,9 +1873,9 @@ module.exports = function(registry) {
} }
cb = cb || utils.createPromiseCallback(); cb = cb || utils.createPromiseCallback();
var idName = this.getIdName(); const idName = this.getIdName();
var Model = this; const Model = this;
var changes = new PassThrough({objectMode: true}); const changes = new PassThrough({objectMode: true});
changes._destroy = function() { changes._destroy = function() {
changes.end(); changes.end();
@ -1900,7 +1900,7 @@ module.exports = function(registry) {
return cb.promise; return cb.promise;
function changeHandler(ctx, next) { function changeHandler(ctx, next) {
var change = createChangeObject(ctx, 'save'); const change = createChangeObject(ctx, 'save');
if (change) { if (change) {
changes.write(change); changes.write(change);
} }
@ -1909,7 +1909,7 @@ module.exports = function(registry) {
} }
function deleteHandler(ctx, next) { function deleteHandler(ctx, next) {
var change = createChangeObject(ctx, 'delete'); const change = createChangeObject(ctx, 'delete');
if (change) { if (change) {
changes.write(change); changes.write(change);
} }
@ -1918,13 +1918,13 @@ module.exports = function(registry) {
} }
function createChangeObject(ctx, type) { function createChangeObject(ctx, type) {
var where = ctx.where; const where = ctx.where;
var data = ctx.instance || ctx.data; let data = ctx.instance || ctx.data;
var whereId = where && where[idName]; const whereId = where && where[idName];
// the data includes the id // the data includes the id
// or the where includes the id // or the where includes the id
var target; let target;
if (data && (data[idName] || data[idName] === 0)) { if (data && (data[idName] || data[idName] === 0)) {
target = data[idName]; target = data[idName];
@ -1932,18 +1932,18 @@ module.exports = function(registry) {
target = where[idName]; target = where[idName];
} }
var hasTarget = target === 0 || !!target; const hasTarget = target === 0 || !!target;
// apply filtering if options is set // apply filtering if options is set
if (options) { if (options) {
var filtered = filterNodes([data], options); const filtered = filterNodes([data], options);
if (filtered.length !== 1) { if (filtered.length !== 1) {
return null; return null;
} }
data = filtered[0]; data = filtered[0];
} }
var change = { const change = {
target: target, target: target,
where: where, where: where,
data: data, data: data,

View File

@ -4,14 +4,14 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var g = require('./globalize'); const g = require('./globalize');
var assert = require('assert'); const assert = require('assert');
var extend = require('util')._extend; const extend = require('util')._extend;
var juggler = require('loopback-datasource-juggler'); const juggler = require('loopback-datasource-juggler');
var debug = require('debug')('loopback:registry'); const debug = require('debug')('loopback:registry');
var DataSource = juggler.DataSource; const DataSource = juggler.DataSource;
var ModelBuilder = juggler.ModelBuilder; const ModelBuilder = juggler.ModelBuilder;
var deprecated = require('depd')('strong-remoting'); const deprecated = require('depd')('strong-remoting');
module.exports = Registry; module.exports = Registry;
@ -97,7 +97,7 @@ function Registry() {
Registry.prototype.createModel = function(name, properties, options) { Registry.prototype.createModel = function(name, properties, options) {
if (arguments.length === 1 && typeof name === 'object') { if (arguments.length === 1 && typeof name === 'object') {
var config = name; const config = name;
name = config.name; name = config.name;
properties = config.properties; properties = config.properties;
options = buildModelOptionsFromConfig(config); options = buildModelOptionsFromConfig(config);
@ -107,10 +107,10 @@ Registry.prototype.createModel = function(name, properties, options) {
} }
options = options || {}; options = options || {};
var BaseModel = options.base || options.super; let BaseModel = options.base || options.super;
if (typeof BaseModel === 'string') { if (typeof BaseModel === 'string') {
var baseName = BaseModel; const baseName = BaseModel;
BaseModel = this.findModel(BaseModel); BaseModel = this.findModel(BaseModel);
if (!BaseModel) { if (!BaseModel) {
throw new Error(g.f('Model not found: model `%s` is extending an unknown model `%s`.', throw new Error(g.f('Model not found: model `%s` is extending an unknown model `%s`.',
@ -119,7 +119,7 @@ Registry.prototype.createModel = function(name, properties, options) {
} }
BaseModel = BaseModel || this.getModel('PersistedModel'); BaseModel = BaseModel || this.getModel('PersistedModel');
var model = BaseModel.extend(name, properties, options); const model = BaseModel.extend(name, properties, options);
model.registry = this; model.registry = this;
this._defineRemoteMethods(model, model.settings.methods); this._defineRemoteMethods(model, model.settings.methods);
@ -128,8 +128,8 @@ Registry.prototype.createModel = function(name, properties, options) {
}; };
function buildModelOptionsFromConfig(config) { function buildModelOptionsFromConfig(config) {
var options = extend({}, config.options); const options = extend({}, config.options);
for (var key in config) { for (const key in config) {
if (['name', 'properties', 'options'].indexOf(key) !== -1) { if (['name', 'properties', 'options'].indexOf(key) !== -1) {
// Skip items which have special meaning // Skip items which have special meaning
continue; continue;
@ -152,7 +152,7 @@ function buildModelOptionsFromConfig(config) {
* @param {Object} acl * @param {Object} acl
*/ */
function addACL(acls, acl) { function addACL(acls, acl) {
for (var i = 0, n = acls.length; i < n; i++) { for (let i = 0, n = acls.length; i < n; i++) {
// Check if there is a matching acl to be overriden // Check if there is a matching acl to be overriden
if (acls[i].property === acl.property && if (acls[i].property === acl.property &&
acls[i].accessType === acl.accessType && acls[i].accessType === acl.accessType &&
@ -176,14 +176,14 @@ function addACL(acls, acl) {
*/ */
Registry.prototype.configureModel = function(ModelCtor, config) { Registry.prototype.configureModel = function(ModelCtor, config) {
var settings = ModelCtor.settings; const settings = ModelCtor.settings;
var modelName = ModelCtor.modelName; const modelName = ModelCtor.modelName;
ModelCtor.config = config; ModelCtor.config = config;
// Relations // Relations
if (typeof config.relations === 'object' && config.relations !== null) { if (typeof config.relations === 'object' && config.relations !== null) {
var relations = settings.relations = settings.relations || {}; const relations = settings.relations = settings.relations || {};
Object.keys(config.relations).forEach(function(key) { Object.keys(config.relations).forEach(function(key) {
// FIXME: [rfeng] We probably should check if the relation exists // FIXME: [rfeng] We probably should check if the relation exists
relations[key] = extend(relations[key] || {}, config.relations[key]); relations[key] = extend(relations[key] || {}, config.relations[key]);
@ -195,7 +195,7 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
// ACLs // ACLs
if (Array.isArray(config.acls)) { if (Array.isArray(config.acls)) {
var acls = settings.acls = settings.acls || []; const acls = settings.acls = settings.acls || [];
config.acls.forEach(function(acl) { config.acls.forEach(function(acl) {
addACL(acls, acl); addACL(acls, acl);
}); });
@ -205,7 +205,7 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
} }
// Settings // Settings
var excludedProperties = { const excludedProperties = {
base: true, base: true,
'super': true, 'super': true,
relations: true, relations: true,
@ -213,7 +213,7 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
dataSource: true, dataSource: true,
}; };
if (typeof config.options === 'object' && config.options !== null) { if (typeof config.options === 'object' && config.options !== null) {
for (var p in config.options) { for (const p in config.options) {
if (!(p in excludedProperties)) { if (!(p in excludedProperties)) {
settings[p] = config.options[p]; settings[p] = config.options[p];
} else { } else {
@ -248,9 +248,9 @@ Registry.prototype.configureModel = function(ModelCtor, config) {
); );
} }
var newMethodNames = config.methods && Object.keys(config.methods); const newMethodNames = config.methods && Object.keys(config.methods);
var hasNewMethods = newMethodNames && newMethodNames.length; const hasNewMethods = newMethodNames && newMethodNames.length;
var hasDescendants = this.getModelByType(ModelCtor) !== ModelCtor; const hasDescendants = this.getModelByType(ModelCtor) !== ModelCtor;
if (hasNewMethods && hasDescendants) { if (hasNewMethods && hasDescendants) {
g.warn( g.warn(
'Child models of `%s` will not inherit newly defined remote methods %s.', 'Child models of `%s` will not inherit newly defined remote methods %s.',
@ -271,9 +271,9 @@ Registry.prototype._defineRemoteMethods = function(ModelCtor, methods) {
} }
Object.keys(methods).forEach(function(key) { Object.keys(methods).forEach(function(key) {
var meta = methods[key]; let meta = methods[key];
var m = key.match(/^prototype\.(.*)$/); const m = key.match(/^prototype\.(.*)$/);
var isStatic = !m; const isStatic = !m;
if (typeof meta.isStatic !== 'boolean') { if (typeof meta.isStatic !== 'boolean') {
key = isStatic ? key : m[1]; key = isStatic ? key : m[1];
@ -313,7 +313,7 @@ Registry.prototype.findModel = function(modelName) {
* @header loopback.getModel(modelName) * @header loopback.getModel(modelName)
*/ */
Registry.prototype.getModel = function(modelName) { Registry.prototype.getModel = function(modelName) {
var model = this.findModel(modelName); const model = this.findModel(modelName);
if (model) return model; if (model) return model;
throw new Error(g.f('Model not found: %s', modelName)); throw new Error(g.f('Model not found: %s', modelName));
@ -329,8 +329,8 @@ Registry.prototype.getModel = function(modelName) {
* @header loopback.getModelByType(modelType) * @header loopback.getModelByType(modelType)
*/ */
Registry.prototype.getModelByType = function(modelType) { Registry.prototype.getModelByType = function(modelType) {
var type = typeof modelType; const type = typeof modelType;
var accepted = ['function', 'string']; const accepted = ['function', 'string'];
assert(accepted.indexOf(type) > -1, assert(accepted.indexOf(type) > -1,
'The model type must be a constructor or model name'); 'The model type must be a constructor or model name');
@ -339,8 +339,8 @@ Registry.prototype.getModelByType = function(modelType) {
modelType = this.getModel(modelType); modelType = this.getModel(modelType);
} }
var models = this.modelBuilder.models; const models = this.modelBuilder.models;
for (var m in models) { for (const m in models) {
if (models[m].prototype instanceof modelType) { if (models[m].prototype instanceof modelType) {
return models[m]; return models[m];
} }
@ -359,15 +359,15 @@ Registry.prototype.getModelByType = function(modelType) {
*/ */
Registry.prototype.createDataSource = function(name, options) { Registry.prototype.createDataSource = function(name, options) {
var self = this; const self = this;
var ds = new DataSource(name, options, self.modelBuilder); const ds = new DataSource(name, options, self.modelBuilder);
ds.createModel = function(name, properties, settings) { ds.createModel = function(name, properties, settings) {
settings = settings || {}; settings = settings || {};
var BaseModel = settings.base || settings.super; let BaseModel = settings.base || settings.super;
if (!BaseModel) { if (!BaseModel) {
// Check the connector types // Check the connector types
var connectorTypes = ds.getTypes(); const connectorTypes = ds.getTypes();
if (Array.isArray(connectorTypes) && connectorTypes.indexOf('db') !== -1) { if (Array.isArray(connectorTypes) && connectorTypes.indexOf('db') !== -1) {
// Only set up the base model to PersistedModel if the connector is DB // Only set up the base model to PersistedModel if the connector is DB
BaseModel = self.PersistedModel; BaseModel = self.PersistedModel;
@ -376,13 +376,13 @@ Registry.prototype.createDataSource = function(name, options) {
} }
settings.base = BaseModel; settings.base = BaseModel;
} }
var ModelCtor = self.createModel(name, properties, settings); const ModelCtor = self.createModel(name, properties, settings);
ModelCtor.attachTo(ds); ModelCtor.attachTo(ds);
return ModelCtor; return ModelCtor;
}; };
if (ds.settings && ds.settings.defaultForType) { if (ds.settings && ds.settings.defaultForType) {
var msg = g.f('{{DataSource}} option {{"defaultForType"}} is no longer supported'); const msg = g.f('{{DataSource}} option {{"defaultForType"}} is no longer supported');
throw new Error(msg); throw new Error(msg);
} }
@ -398,7 +398,7 @@ Registry.prototype.createDataSource = function(name, options) {
Registry.prototype.memory = function(name) { Registry.prototype.memory = function(name) {
name = name || 'default'; name = name || 'default';
var memory = ( let memory = (
this._memoryDataSources || (this._memoryDataSources = {}) this._memoryDataSources || (this._memoryDataSources = {})
)[name]; )[name];

View File

@ -10,7 +10,7 @@
*/ */
'use strict'; 'use strict';
var runtime = exports; const runtime = exports;
/** /**
* True if running in a browser environment; false otherwise. * True if running in a browser environment; false otherwise.

View File

@ -4,20 +4,20 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var g = require('./globalize'); const g = require('./globalize');
var assert = require('assert'); const assert = require('assert');
var express = require('express'); const express = require('express');
var merge = require('util')._extend; const merge = require('util')._extend;
var mergePhaseNameLists = require('loopback-phase').mergePhaseNameLists; const mergePhaseNameLists = require('loopback-phase').mergePhaseNameLists;
var debug = require('debug')('loopback:app'); const debug = require('debug')('loopback:app');
var stableSortInPlace = require('stable').inplace; const stableSortInPlace = require('stable').inplace;
var BUILTIN_MIDDLEWARE = {builtin: true}; const BUILTIN_MIDDLEWARE = {builtin: true};
var proto = {}; const proto = {};
module.exports = function loopbackExpress() { module.exports = function loopbackExpress() {
var app = express(); const app = express();
app.__expressLazyRouter = app.lazyrouter; app.__expressLazyRouter = app.lazyrouter;
merge(app, proto); merge(app, proto);
return app; return app;
@ -64,23 +64,23 @@ proto.middlewareFromConfig = function(factory, config) {
if (config.enabled === false) if (config.enabled === false)
return; return;
var params = config.params; let params = config.params;
if (params === undefined) { if (params === undefined) {
params = []; params = [];
} else if (!Array.isArray(params)) { } else if (!Array.isArray(params)) {
params = [params]; params = [params];
} }
var handler = factory.apply(null, params); let handler = factory.apply(null, params);
// Check if methods/verbs filter exists // Check if methods/verbs filter exists
var verbs = config.methods || config.verbs; let verbs = config.methods || config.verbs;
if (Array.isArray(verbs)) { if (Array.isArray(verbs)) {
verbs = verbs.map(function(verb) { verbs = verbs.map(function(verb) {
return verb && verb.toUpperCase(); return verb && verb.toUpperCase();
}); });
if (verbs.indexOf('ALL') === -1) { if (verbs.indexOf('ALL') === -1) {
var originalHandler = handler; const originalHandler = handler;
if (handler.length <= 3) { if (handler.length <= 3) {
// Regular handler // Regular handler
handler = function(req, res, next) { handler = function(req, res, next) {
@ -145,7 +145,7 @@ proto.defineMiddlewarePhases = function(nameOrArray) {
mergePhaseNameLists(this._requestHandlingPhases, nameOrArray); mergePhaseNameLists(this._requestHandlingPhases, nameOrArray);
} else { } else {
// add the new phase before 'routes' // add the new phase before 'routes'
var routesIx = this._requestHandlingPhases.indexOf('routes'); const routesIx = this._requestHandlingPhases.indexOf('routes');
this._requestHandlingPhases.splice(routesIx - 1, 0, nameOrArray); this._requestHandlingPhases.splice(routesIx - 1, 0, nameOrArray);
} }
@ -181,10 +181,10 @@ proto.middleware = function(name, paths, handler) {
paths = '/'; paths = '/';
} }
var fullPhaseName = name; const fullPhaseName = name;
var handlerName = handler.name || '<anonymous>'; const handlerName = handler.name || '<anonymous>';
var m = name.match(/^(.+):(before|after)$/); const m = name.match(/^(.+):(before|after)$/);
if (m) { if (m) {
name = m[1]; name = m[1];
} }
@ -197,7 +197,7 @@ proto.middleware = function(name, paths, handler) {
this._skipLayerSorting = true; this._skipLayerSorting = true;
this.use(paths, handler); this.use(paths, handler);
var layer = this._findLayerByHandler(handler); const layer = this._findLayerByHandler(handler);
if (layer) { if (layer) {
// Set the phase name for sorting // Set the phase name for sorting
layer.phase = fullPhaseName; layer.phase = fullPhaseName;
@ -223,7 +223,7 @@ proto._findLayerByHandler = function(handler) {
// Other handlers can be added to the stack, for example, // Other handlers can be added to the stack, for example,
// NewRelic adds sentinel handler, and AppDynamics adds // NewRelic adds sentinel handler, and AppDynamics adds
// some additional proxy info. We need to search the stack // some additional proxy info. We need to search the stack
for (var k = this._router.stack.length - 1; k >= 0; k--) { for (let k = this._router.stack.length - 1; k >= 0; k--) {
const isOriginal = this._router.stack[k].handle === handler; const isOriginal = this._router.stack[k].handle === handler;
const isNewRelic = this._router.stack[k].handle['__NR_original'] === handler; const isNewRelic = this._router.stack[k].handle['__NR_original'] === handler;
const isAppDynamics = this._router.stack[k].handle['__appdynamicsProxyInfo__'] && const isAppDynamics = this._router.stack[k].handle['__appdynamicsProxyInfo__'] &&
@ -234,7 +234,7 @@ proto._findLayerByHandler = function(handler) {
} else { } else {
// Aggressively check if the original handler has been wrapped // Aggressively check if the original handler has been wrapped
// into a new function with a property pointing to the original handler // into a new function with a property pointing to the original handler
for (var p in this._router.stack[k].handle) { for (const p in this._router.stack[k].handle) {
if (this._router.stack[k].handle[p] === handler) { if (this._router.stack[k].handle[p] === handler) {
return this._router.stack[k]; return this._router.stack[k];
} }
@ -246,12 +246,12 @@ proto._findLayerByHandler = function(handler) {
// Install our custom PhaseList-based handler into the app // Install our custom PhaseList-based handler into the app
proto.lazyrouter = function() { proto.lazyrouter = function() {
var self = this; const self = this;
if (self._router) return; if (self._router) return;
self.__expressLazyRouter(); self.__expressLazyRouter();
var router = self._router; const router = self._router;
// Mark all middleware added by Router ctor as builtin // Mark all middleware added by Router ctor as builtin
// The sorting algo will keep them at beginning of the list // The sorting algo will keep them at beginning of the list
@ -261,14 +261,14 @@ proto.lazyrouter = function() {
router.__expressUse = router.use; router.__expressUse = router.use;
router.use = function useAndSort() { router.use = function useAndSort() {
var retval = this.__expressUse.apply(this, arguments); const retval = this.__expressUse.apply(this, arguments);
self._sortLayersByPhase(); self._sortLayersByPhase();
return retval; return retval;
}; };
router.__expressRoute = router.route; router.__expressRoute = router.route;
router.route = function routeAndSort() { router.route = function routeAndSort() {
var retval = this.__expressRoute.apply(this, arguments); const retval = this.__expressRoute.apply(this, arguments);
self._sortLayersByPhase(); self._sortLayersByPhase();
return retval; return retval;
}; };
@ -282,19 +282,19 @@ proto.lazyrouter = function() {
proto._sortLayersByPhase = function() { proto._sortLayersByPhase = function() {
if (this._skipLayerSorting) return; if (this._skipLayerSorting) return;
var phaseOrder = {}; const phaseOrder = {};
this._requestHandlingPhases.forEach(function(name, ix) { this._requestHandlingPhases.forEach(function(name, ix) {
phaseOrder[name + ':before'] = ix * 3; phaseOrder[name + ':before'] = ix * 3;
phaseOrder[name] = ix * 3 + 1; phaseOrder[name] = ix * 3 + 1;
phaseOrder[name + ':after'] = ix * 3 + 2; phaseOrder[name + ':after'] = ix * 3 + 2;
}); });
var router = this._router; const router = this._router;
stableSortInPlace(router.stack, compareLayers); stableSortInPlace(router.stack, compareLayers);
function compareLayers(left, right) { function compareLayers(left, right) {
var leftPhase = left.phase; const leftPhase = left.phase;
var rightPhase = right.phase; const rightPhase = right.phase;
if (leftPhase === rightPhase) return 0; if (leftPhase === rightPhase) return 0;

View File

@ -10,12 +10,12 @@ exports.uploadInChunks = uploadInChunks;
exports.downloadInChunks = downloadInChunks; exports.downloadInChunks = downloadInChunks;
exports.concatResults = concatResults; exports.concatResults = concatResults;
var Promise = require('bluebird'); const Promise = require('bluebird');
var async = require('async'); const async = require('async');
function createPromiseCallback() { function createPromiseCallback() {
var cb; let cb;
var promise = new Promise(function(resolve, reject) { const promise = new Promise(function(resolve, reject) {
cb = function(err, data) { cb = function(err, data) {
if (err) return reject(err); if (err) return reject(err);
return resolve(data); return resolve(data);
@ -40,23 +40,23 @@ function throwPromiseNotDefined() {
* @param {Function} cb - the callback * @param {Function} cb - the callback
*/ */
function uploadInChunks(largeArray, chunkSize, processFunction, cb) { function uploadInChunks(largeArray, chunkSize, processFunction, cb) {
var chunkArrays = []; const chunkArrays = [];
if (!chunkSize || chunkSize < 1 || largeArray.length <= chunkSize) { if (!chunkSize || chunkSize < 1 || largeArray.length <= chunkSize) {
// if chunking not required // if chunking not required
processFunction(largeArray, cb); processFunction(largeArray, cb);
} else { } else {
// copying so that the largeArray object does not get affected during splice // copying so that the largeArray object does not get affected during splice
var copyOfLargeArray = [].concat(largeArray); const copyOfLargeArray = [].concat(largeArray);
// chunking to smaller arrays // chunking to smaller arrays
while (copyOfLargeArray.length > 0) { while (copyOfLargeArray.length > 0) {
chunkArrays.push(copyOfLargeArray.splice(0, chunkSize)); chunkArrays.push(copyOfLargeArray.splice(0, chunkSize));
} }
var tasks = chunkArrays.map(function(chunkArray) { const tasks = chunkArrays.map(function(chunkArray) {
return function(previousResults, chunkCallback) { return function(previousResults, chunkCallback) {
var lastArg = arguments[arguments.length - 1]; const lastArg = arguments[arguments.length - 1];
if (typeof lastArg === 'function') { if (typeof lastArg === 'function') {
chunkCallback = lastArg; chunkCallback = lastArg;
@ -92,7 +92,7 @@ function uploadInChunks(largeArray, chunkSize, processFunction, cb) {
* @param {Function} cb - the callback * @param {Function} cb - the callback
*/ */
function downloadInChunks(filter, chunkSize, processFunction, cb) { function downloadInChunks(filter, chunkSize, processFunction, cb) {
var results = []; let results = [];
filter = filter ? JSON.parse(JSON.stringify(filter)) : {}; filter = filter ? JSON.parse(JSON.stringify(filter)) : {};
if (!chunkSize || chunkSize < 1) { if (!chunkSize || chunkSize < 1) {

View File

@ -64,26 +64,25 @@
}, },
"devDependencies": { "devDependencies": {
"browserify": "^16.5.0", "browserify": "^16.5.0",
"chai": "^3.5.0", "chai": "^4.2.0",
"cookie-parser": "^1.3.4", "cookie-parser": "^1.3.4",
"coveralls": "^3.0.2", "coveralls": "^3.0.2",
"dirty-chai": "^1.2.2", "dirty-chai": "^2.0.1",
"eslint": "^5.3.0", "eslint": "^6.5.1",
"eslint-config-loopback": "^12.0.0", "eslint-config-loopback": "^13.1.0",
"eslint-plugin-mocha": "^5.1.0",
"express-session": "^1.14.0", "express-session": "^1.14.0",
"grunt": "^1.0.1", "grunt": "^1.0.1",
"grunt-browserify": "^5.0.0", "grunt-browserify": "^5.0.0",
"grunt-cli": "^1.2.0", "grunt-cli": "^1.2.0",
"grunt-contrib-uglify": "^3.4.0", "grunt-contrib-uglify": "^4.0.1",
"grunt-contrib-watch": "^1.0.0", "grunt-contrib-watch": "^1.0.0",
"grunt-eslint": "^21.0.0", "grunt-eslint": "^22.0.0",
"grunt-karma": "^3.0.2", "grunt-karma": "^3.0.2",
"grunt-mocha-test": "^0.13.3", "grunt-mocha-test": "^0.13.3",
"is-docker": "^2.0.0", "is-docker": "^2.0.0",
"karma": "^4.1.0", "karma": "^4.1.0",
"karma-browserify": "^6.0.0", "karma-browserify": "^6.0.0",
"karma-chrome-launcher": "^2.2.0", "karma-chrome-launcher": "^3.1.0",
"karma-es6-shim": "^1.0.0", "karma-es6-shim": "^1.0.0",
"karma-firefox-launcher": "^1.0.0", "karma-firefox-launcher": "^1.0.0",
"karma-html2js-preprocessor": "^1.0.0", "karma-html2js-preprocessor": "^1.0.0",
@ -92,14 +91,14 @@
"karma-script-launcher": "^1.0.0", "karma-script-launcher": "^1.0.0",
"loopback-boot": "^2.7.0", "loopback-boot": "^2.7.0",
"loopback-context": "^1.0.0", "loopback-context": "^1.0.0",
"mocha": "^5.2.0", "mocha": "^6.2.1",
"nyc": "^14.1.1", "nyc": "^14.1.1",
"sinon": "^6.1.4", "sinon": "^7.5.0",
"sinon-chai": "^3.2.0", "sinon-chai": "^3.2.0",
"strong-error-handler": "^3.0.0", "strong-error-handler": "^3.0.0",
"strong-task-emitter": "^0.0.8", "strong-task-emitter": "^0.0.8",
"supertest": "^3.0.0", "supertest": "^4.0.2",
"which": "^1.3.1" "which": "^2.0.1"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -4,7 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
module.exports = function() { module.exports = function() {
throw new Error(g.f( throw new Error(g.f(

View File

@ -4,8 +4,8 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var favicon = require('serve-favicon'); const favicon = require('serve-favicon');
var path = require('path'); const path = require('path');
/** /**
* Serve the LoopBack favicon. * Serve the LoopBack favicon.

View File

@ -8,9 +8,9 @@
*/ */
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
var loopback = require('../../lib/loopback'); const loopback = require('../../lib/loopback');
var async = require('async'); const async = require('async');
/*! /*!
* Export the middleware. * Export the middleware.
@ -30,17 +30,17 @@ module.exports = rest;
*/ */
function rest() { function rest() {
var handlers; // Cached handlers let handlers; // Cached handlers
return function restApiHandler(req, res, next) { return function restApiHandler(req, res, next) {
var app = req.app; const app = req.app;
var registry = app.registry; const registry = app.registry;
if (!handlers) { if (!handlers) {
handlers = []; handlers = [];
var remotingOptions = app.get('remoting') || {}; const remotingOptions = app.get('remoting') || {};
var contextOptions = remotingOptions.context; const contextOptions = remotingOptions.context;
if (contextOptions !== undefined && contextOptions !== false) { if (contextOptions !== undefined && contextOptions !== false) {
throw new Error(g.f( throw new Error(g.f(
'%s was removed in version 3.0. See %s for more details.', '%s was removed in version 3.0. See %s for more details.',
@ -50,7 +50,7 @@ function rest() {
} }
if (app.isAuthEnabled) { if (app.isAuthEnabled) {
var AccessToken = registry.getModelByType('AccessToken'); const AccessToken = registry.getModelByType('AccessToken');
handlers.push(loopback.token({model: AccessToken, app: app})); handlers.push(loopback.token({model: AccessToken, app: app}));
} }

View File

@ -24,7 +24,7 @@ module.exports = status;
* @header loopback.status() * @header loopback.status()
*/ */
function status() { function status() {
var started = new Date(); const started = new Date();
return function(req, res) { return function(req, res) {
res.send({ res.send({

View File

@ -8,10 +8,10 @@
*/ */
'use strict'; 'use strict';
var g = require('../../lib/globalize'); const g = require('../../lib/globalize');
var loopback = require('../../lib/loopback'); const loopback = require('../../lib/loopback');
var assert = require('assert'); const assert = require('assert');
var debug = require('debug')('loopback:middleware:token'); const debug = require('debug')('loopback:middleware:token');
/*! /*!
* Export the middleware. * Export the middleware.
@ -28,7 +28,7 @@ function rewriteUserLiteral(req, currentUserLiteral, next) {
if (req.accessToken && req.accessToken.userId) { if (req.accessToken && req.accessToken.userId) {
// Replace /me/ with /current-user-id/ // Replace /me/ with /current-user-id/
var urlBeforeRewrite = req.url; const urlBeforeRewrite = req.url;
req.url = req.url.replace(literalRegExp, req.url = req.url.replace(literalRegExp,
'/' + req.accessToken.userId + '$1'); '/' + req.accessToken.userId + '$1');
@ -43,7 +43,7 @@ function rewriteUserLiteral(req, currentUserLiteral, next) {
req.url, currentUserLiteral req.url, currentUserLiteral
); );
var e = new Error(g.f('Authorization Required')); const e = new Error(g.f('Authorization Required'));
e.status = e.statusCode = 401; e.status = e.statusCode = 401;
e.code = 'AUTHORIZATION_REQUIRED'; e.code = 'AUTHORIZATION_REQUIRED';
return next(e); return next(e);
@ -97,9 +97,9 @@ function escapeRegExp(str) {
function token(options) { function token(options) {
options = options || {}; options = options || {};
var TokenModel; let TokenModel;
var currentUserLiteral = options.currentUserLiteral; let currentUserLiteral = options.currentUserLiteral;
if (currentUserLiteral && (typeof currentUserLiteral !== 'string')) { if (currentUserLiteral && (typeof currentUserLiteral !== 'string')) {
debug('Set currentUserLiteral to \'me\' as the value is not a string.'); debug('Set currentUserLiteral to \'me\' as the value is not a string.');
currentUserLiteral = 'me'; currentUserLiteral = 'me';
@ -111,12 +111,12 @@ function token(options) {
if (options.bearerTokenBase64Encoded === undefined) { if (options.bearerTokenBase64Encoded === undefined) {
options.bearerTokenBase64Encoded = true; options.bearerTokenBase64Encoded = true;
} }
var enableDoublecheck = !!options.enableDoublecheck; const enableDoublecheck = !!options.enableDoublecheck;
var overwriteExistingToken = !!options.overwriteExistingToken; const overwriteExistingToken = !!options.overwriteExistingToken;
return function(req, res, next) { return function(req, res, next) {
var app = req.app; const app = req.app;
var registry = app.registry; const registry = app.registry;
if (!TokenModel) { if (!TokenModel) {
TokenModel = registry.getModel(options.model || 'AccessToken'); TokenModel = registry.getModel(options.model || 'AccessToken');
} }
@ -141,7 +141,7 @@ function token(options) {
TokenModel.findForRequest(req, options, function(err, token) { TokenModel.findForRequest(req, options, function(err, token) {
req.accessToken = token || null; req.accessToken = token || null;
var ctx = req.loopbackContext; const ctx = req.loopbackContext;
if (ctx && ctx.active) ctx.set('accessToken', token); if (ctx && ctx.active) ctx.set('accessToken', token);
if (err) return next(err); if (err) return next(err);

View File

@ -18,7 +18,7 @@ module.exports = urlNotFound;
*/ */
function urlNotFound() { function urlNotFound() {
return function raiseUrlNotFoundError(req, res, next) { return function raiseUrlNotFoundError(req, res, next) {
var error = new Error('Cannot ' + req.method + ' ' + req.url); const error = new Error('Cannot ' + req.method + ' ' + req.url);
error.status = 404; error.status = 404;
next(error); next(error);
}; };

View File

@ -4,15 +4,15 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../'); const loopback = require('../');
var lt = require('./helpers/loopback-testing-helper'); const lt = require('./helpers/loopback-testing-helper');
var path = require('path'); const path = require('path');
var ACCESS_CONTROL_APP = path.join(__dirname, 'fixtures', 'access-control'); const ACCESS_CONTROL_APP = path.join(__dirname, 'fixtures', 'access-control');
var app = require(path.join(ACCESS_CONTROL_APP, 'server/server.js')); const app = require(path.join(ACCESS_CONTROL_APP, 'server/server.js'));
var assert = require('assert'); const assert = require('assert');
var USER = {email: 'test@test.test', password: 'test'}; const USER = {email: 'test@test.test', password: 'test'};
var CURRENT_USER = {email: 'current@test.test', password: 'test'}; const CURRENT_USER = {email: 'current@test.test', password: 'test'};
var debug = require('debug')('loopback:test:access-control.integration'); const debug = require('debug')('loopback:test:access-control.integration');
describe('access control - integration', function() { describe('access control - integration', function() {
lt.beforeEach.withApp(app); lt.beforeEach.withApp(app);
@ -110,7 +110,7 @@ describe('access control - integration', function() {
this.res.statusCode, this.res.statusCode,
this.res.headers, this.res.headers,
this.res.text); this.res.text);
var user = this.res.body; const user = this.res.body;
assert.equal(user.password, undefined); assert.equal(user.password, undefined);
}); });
}); });
@ -137,7 +137,7 @@ describe('access control - integration', function() {
return '/api/users/' + this.randomUser.id; return '/api/users/' + this.randomUser.id;
} }
var userCounter; var userCounter; // eslint-disable-line no-var
function newUserData() { function newUserData() {
userCounter = userCounter ? ++userCounter : 1; userCounter = userCounter ? ++userCounter : 1;
@ -149,14 +149,14 @@ describe('access control - integration', function() {
}); });
describe('/banks', function() { describe('/banks', function() {
var SPECIAL_USER = {email: 'special@test.test', password: 'test'}; const SPECIAL_USER = {email: 'special@test.test', password: 'test'};
// define dynamic role that would only grant access when the authenticated user's email is equal to // define dynamic role that would only grant access when the authenticated user's email is equal to
// SPECIAL_USER's email // SPECIAL_USER's email
before(function() { before(function() {
var roleModel = app.registry.getModel('Role'); const roleModel = app.registry.getModel('Role');
var userModel = app.registry.getModel('user'); const userModel = app.registry.getModel('user');
roleModel.registerResolver('$dynamic-role', function(role, context, callback) { roleModel.registerResolver('$dynamic-role', function(role, context, callback) {
if (!(context && context.accessToken && context.accessToken.userId)) { if (!(context && context.accessToken && context.accessToken.userId)) {
@ -164,7 +164,7 @@ describe('access control - integration', function() {
if (callback) callback(null, false); if (callback) callback(null, false);
}); });
} }
var accessToken = context.accessToken; const accessToken = context.accessToken;
userModel.findById(accessToken.userId, function(err, user) { userModel.findById(accessToken.userId, function(err, user) {
if (err) { if (err) {
return callback(err, false); return callback(err, false);
@ -210,9 +210,9 @@ describe('access control - integration', function() {
}); });
describe('/accounts with replaceOnPUT true', function() { describe('/accounts with replaceOnPUT true', function() {
var count = 0; let count = 0;
before(function() { before(function() {
var roleModel = loopback.getModelByType(loopback.Role); const roleModel = loopback.getModelByType(loopback.Role);
roleModel.registerResolver('$dummy', function(role, context, callback) { roleModel.registerResolver('$dummy', function(role, context, callback) {
process.nextTick(function() { process.nextTick(function() {
if (context.remotingContext) { if (context.remotingContext) {
@ -250,9 +250,9 @@ describe('access control - integration', function() {
lt.it.shouldBeDeniedWhenCalledByUser(CURRENT_USER, 'PATCH', urlForAccount); lt.it.shouldBeDeniedWhenCalledByUser(CURRENT_USER, 'PATCH', urlForAccount);
lt.describe.whenLoggedInAsUser(CURRENT_USER, function() { lt.describe.whenLoggedInAsUser(CURRENT_USER, function() {
var actId; let actId;
beforeEach(function(done) { beforeEach(function(done) {
var self = this; const self = this;
// Create an account under the given user // Create an account under the given user
app.models.accountWithReplaceOnPUTtrue.create({ app.models.accountWithReplaceOnPUTtrue.create({
userId: self.user.id, userId: self.user.id,
@ -314,9 +314,9 @@ describe('access control - integration', function() {
lt.it.shouldBeDeniedWhenCalledByUser(CURRENT_USER, 'PATCH', urlForAccount); lt.it.shouldBeDeniedWhenCalledByUser(CURRENT_USER, 'PATCH', urlForAccount);
lt.describe.whenLoggedInAsUser(CURRENT_USER, function() { lt.describe.whenLoggedInAsUser(CURRENT_USER, function() {
var actId; let actId;
beforeEach(function(done) { beforeEach(function(done) {
var self = this; const self = this;
// Create an account under the given user // Create an account under the given user
app.models.accountWithReplaceOnPUTfalse.create({ app.models.accountWithReplaceOnPUTfalse.create({
userId: self.user.id, userId: self.user.id,

View File

@ -4,20 +4,20 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var cookieParser = require('cookie-parser'); const cookieParser = require('cookie-parser');
var LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
var contextMiddleware = require('loopback-context').perRequest; const contextMiddleware = require('loopback-context').perRequest;
var loopback = require('../'); const loopback = require('../');
var extend = require('util')._extend; const extend = require('util')._extend;
var session = require('express-session'); const session = require('express-session');
var request = require('supertest'); const request = require('supertest');
var Token, ACL, User, TestModel; let Token, ACL, User, TestModel;
describe('loopback.token(options)', function() { describe('loopback.token(options)', function() {
var app; let app;
beforeEach(function(done) { beforeEach(function(done) {
app = loopback({localRegistry: true, loadBuiltinModels: true}); app = loopback({localRegistry: true, loadBuiltinModels: true});
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
@ -52,7 +52,7 @@ describe('loopback.token(options)', function() {
}); });
it('defaults to built-in AccessToken model', function() { it('defaults to built-in AccessToken model', function() {
var BuiltInToken = app.registry.getModel('AccessToken'); const BuiltInToken = app.registry.getModel('AccessToken');
app.model(BuiltInToken, {dataSource: 'db'}); app.model(BuiltInToken, {dataSource: 'db'});
app.enableAuth({dataSource: 'db'}); app.enableAuth({dataSource: 'db'});
@ -140,13 +140,13 @@ describe('loopback.token(options)', function() {
it('does not search default keys when searchDefaultTokenKeys is false', it('does not search default keys when searchDefaultTokenKeys is false',
function(done) { function(done) {
var tokenId = this.token.id; const tokenId = this.token.id;
var app = createTestApp( const app = createTestApp(
this.token, this.token,
{token: {searchDefaultTokenKeys: false}}, {token: {searchDefaultTokenKeys: false}},
done done
); );
var agent = request.agent(app); const agent = request.agent(app);
// Set the token cookie // Set the token cookie
agent.get('/token').expect(200).end(function(err, res) { agent.get('/token').expect(200).end(function(err, res) {
@ -165,7 +165,7 @@ describe('loopback.token(options)', function() {
it('populates req.token from an authorization header with bearer token with base64', it('populates req.token from an authorization header with bearer token with base64',
function(done) { function(done) {
var token = this.token.id; let token = this.token.id;
token = 'Bearer ' + new Buffer(token).toString('base64'); token = 'Bearer ' + new Buffer(token).toString('base64');
createTestAppAndRequest(this.token, done) createTestAppAndRequest(this.token, done)
.get('/') .get('/')
@ -175,7 +175,7 @@ describe('loopback.token(options)', function() {
}); });
it('populates req.token from an authorization header with bearer token', function(done) { it('populates req.token from an authorization header with bearer token', function(done) {
var token = this.token.id; let token = this.token.id;
token = 'Bearer ' + token; token = 'Bearer ' + token;
createTestAppAndRequest(this.token, {token: {bearerTokenBase64Encoded: false}}, done) createTestAppAndRequest(this.token, {token: {bearerTokenBase64Encoded: false}}, done)
.get('/') .get('/')
@ -186,7 +186,7 @@ describe('loopback.token(options)', function() {
describe('populating req.token from HTTP Basic Auth formatted authorization header', function() { describe('populating req.token from HTTP Basic Auth formatted authorization header', function() {
it('parses "standalone-token"', function(done) { it('parses "standalone-token"', function(done) {
var token = this.token.id; let token = this.token.id;
token = 'Basic ' + new Buffer(token).toString('base64'); token = 'Basic ' + new Buffer(token).toString('base64');
createTestAppAndRequest(this.token, done) createTestAppAndRequest(this.token, done)
.get('/') .get('/')
@ -196,7 +196,7 @@ describe('loopback.token(options)', function() {
}); });
it('parses "token-and-empty-password:"', function(done) { it('parses "token-and-empty-password:"', function(done) {
var token = this.token.id + ':'; let token = this.token.id + ':';
token = 'Basic ' + new Buffer(token).toString('base64'); token = 'Basic ' + new Buffer(token).toString('base64');
createTestAppAndRequest(this.token, done) createTestAppAndRequest(this.token, done)
.get('/') .get('/')
@ -206,7 +206,7 @@ describe('loopback.token(options)', function() {
}); });
it('parses "ignored-user:token-is-password"', function(done) { it('parses "ignored-user:token-is-password"', function(done) {
var token = 'username:' + this.token.id; let token = 'username:' + this.token.id;
token = 'Basic ' + new Buffer(token).toString('base64'); token = 'Basic ' + new Buffer(token).toString('base64');
createTestAppAndRequest(this.token, done) createTestAppAndRequest(this.token, done)
.get('/') .get('/')
@ -216,7 +216,7 @@ describe('loopback.token(options)', function() {
}); });
it('parses "token-is-username:ignored-password"', function(done) { it('parses "token-is-username:ignored-password"', function(done) {
var token = this.token.id + ':password'; let token = this.token.id + ':password';
token = 'Basic ' + new Buffer(token).toString('base64'); token = 'Basic ' + new Buffer(token).toString('base64');
createTestAppAndRequest(this.token, done) createTestAppAndRequest(this.token, done)
.get('/') .get('/')
@ -227,7 +227,7 @@ describe('loopback.token(options)', function() {
}); });
it('populates req.token from a secure cookie', function(done) { it('populates req.token from a secure cookie', function(done) {
var app = createTestApp(this.token, done); const app = createTestApp(this.token, done);
request(app) request(app)
.get('/token') .get('/token')
@ -240,8 +240,8 @@ describe('loopback.token(options)', function() {
}); });
it('populates req.token from a header or a secure cookie', function(done) { it('populates req.token from a header or a secure cookie', function(done) {
var app = createTestApp(this.token, done); const app = createTestApp(this.token, done);
var id = this.token.id; const id = this.token.id;
request(app) request(app)
.get('/token') .get('/token')
.end(function(err, res) { .end(function(err, res) {
@ -255,9 +255,9 @@ describe('loopback.token(options)', function() {
it('rewrites url for the current user literal at the end without query', it('rewrites url for the current user literal at the end without query',
function(done) { function(done) {
var app = createTestApp(this.token, done); const app = createTestApp(this.token, done);
var id = this.token.id; const id = this.token.id;
var userId = this.token.userId; const userId = this.token.userId;
request(app) request(app)
.get('/users/me') .get('/users/me')
.set('authorization', id) .set('authorization', id)
@ -271,9 +271,9 @@ describe('loopback.token(options)', function() {
it('rewrites url for the current user literal at the end with query', it('rewrites url for the current user literal at the end with query',
function(done) { function(done) {
var app = createTestApp(this.token, done); const app = createTestApp(this.token, done);
var id = this.token.id; const id = this.token.id;
var userId = this.token.userId; const userId = this.token.userId;
request(app) request(app)
.get('/users/me?state=1') .get('/users/me?state=1')
.set('authorization', id) .set('authorization', id)
@ -287,9 +287,9 @@ describe('loopback.token(options)', function() {
it('rewrites url for the current user literal in the middle', it('rewrites url for the current user literal in the middle',
function(done) { function(done) {
var app = createTestApp(this.token, done); const app = createTestApp(this.token, done);
var id = this.token.id; const id = this.token.id;
var userId = this.token.userId; const userId = this.token.userId;
request(app) request(app)
.get('/users/me/1') .get('/users/me/1')
.set('authorization', id) .set('authorization', id)
@ -303,7 +303,7 @@ describe('loopback.token(options)', function() {
it('generates a 401 on a current user literal route without an authToken', it('generates a 401 on a current user literal route without an authToken',
function(done) { function(done) {
var app = createTestApp(null, done); const app = createTestApp(null, done);
request(app) request(app)
.get('/users/me') .get('/users/me')
.set('authorization', null) .set('authorization', null)
@ -313,7 +313,7 @@ describe('loopback.token(options)', function() {
it('generates a 401 on a current user literal route with empty authToken', it('generates a 401 on a current user literal route with empty authToken',
function(done) { function(done) {
var app = createTestApp(null, done); const app = createTestApp(null, done);
request(app) request(app)
.get('/users/me') .get('/users/me')
.set('authorization', '') .set('authorization', '')
@ -323,7 +323,7 @@ describe('loopback.token(options)', function() {
it('generates a 401 on a current user literal route with invalid authToken', it('generates a 401 on a current user literal route with invalid authToken',
function(done) { function(done) {
var app = createTestApp(this.token, done); const app = createTestApp(this.token, done);
request(app) request(app)
.get('/users/me') .get('/users/me')
.set('Authorization', 'invald-token-id') .set('Authorization', 'invald-token-id')
@ -332,7 +332,7 @@ describe('loopback.token(options)', function() {
}); });
it('skips when req.token is already present', function(done) { it('skips when req.token is already present', function(done) {
var tokenStub = {id: 'stub id'}; const tokenStub = {id: 'stub id'};
app.use(function(req, res, next) { app.use(function(req, res, next) {
req.accessToken = tokenStub; req.accessToken = tokenStub;
@ -358,7 +358,7 @@ describe('loopback.token(options)', function() {
describe('loading multiple instances of token middleware', function() { describe('loading multiple instances of token middleware', function() {
it('skips when req.token is already present and no further options are set', it('skips when req.token is already present and no further options are set',
function(done) { function(done) {
var tokenStub = {id: 'stub id'}; const tokenStub = {id: 'stub id'};
app.use(function(req, res, next) { app.use(function(req, res, next) {
req.accessToken = tokenStub; req.accessToken = tokenStub;
@ -384,7 +384,7 @@ describe('loopback.token(options)', function() {
it('does not overwrite valid existing token (has "id" property) ' + it('does not overwrite valid existing token (has "id" property) ' +
' when overwriteExistingToken is falsy', ' when overwriteExistingToken is falsy',
function(done) { function(done) {
var tokenStub = {id: 'stub id'}; const tokenStub = {id: 'stub id'};
app.use(function(req, res, next) { app.use(function(req, res, next) {
req.accessToken = tokenStub; req.accessToken = tokenStub;
@ -413,7 +413,7 @@ describe('loopback.token(options)', function() {
it('overwrites invalid existing token (is !== undefined and has no "id" property) ' + it('overwrites invalid existing token (is !== undefined and has no "id" property) ' +
' when enableDoublecheck is true', ' when enableDoublecheck is true',
function(done) { function(done) {
var token = this.token; const token = this.token;
app.use(function(req, res, next) { app.use(function(req, res, next) {
req.accessToken = null; req.accessToken = null;
next(); next();
@ -446,8 +446,8 @@ describe('loopback.token(options)', function() {
it('overwrites existing token when enableDoublecheck ' + it('overwrites existing token when enableDoublecheck ' +
'and overwriteExistingToken options are truthy', 'and overwriteExistingToken options are truthy',
function(done) { function(done) {
var token = this.token; const token = this.token;
var tokenStub = {id: 'stub id'}; const tokenStub = {id: 'stub id'};
app.use(function(req, res, next) { app.use(function(req, res, next) {
req.accessToken = tokenStub; req.accessToken = tokenStub;
@ -521,7 +521,7 @@ describe('AccessToken', function() {
it('allows eternal tokens when enabled by User.allowEternalTokens', it('allows eternal tokens when enabled by User.allowEternalTokens',
function(done) { function(done) {
var Token = givenLocalTokenModel(); const Token = givenLocalTokenModel();
// Overwrite User settings - enable eternal tokens // Overwrite User settings - enable eternal tokens
Token.app.models.User.settings.allowEternalTokens = true; Token.app.models.User.settings.allowEternalTokens = true;
@ -541,8 +541,8 @@ describe('AccessToken', function() {
beforeEach(createTestingToken); beforeEach(createTestingToken);
it('supports two-arg variant with no options', function(done) { it('supports two-arg variant with no options', function(done) {
var expectedTokenId = this.token.id; const expectedTokenId = this.token.id;
var req = mockRequest({ const req = mockRequest({
headers: {'authorization': expectedTokenId}, headers: {'authorization': expectedTokenId},
}); });
@ -556,14 +556,14 @@ describe('AccessToken', function() {
}); });
it('allows getIdForRequest() to be overridden', function(done) { it('allows getIdForRequest() to be overridden', function(done) {
var expectedTokenId = this.token.id; const expectedTokenId = this.token.id;
var current = Token.getIdForRequest; const current = Token.getIdForRequest;
var called = false; let called = false;
Token.getIdForRequest = function(req, options) { Token.getIdForRequest = function(req, options) {
called = true; called = true;
return expectedTokenId; return expectedTokenId;
}; };
var req = mockRequest({ const req = mockRequest({
headers: {'authorization': 'dummy'}, headers: {'authorization': 'dummy'},
}); });
@ -579,16 +579,16 @@ describe('AccessToken', function() {
}); });
it('allows resolve() to be overridden', function(done) { it('allows resolve() to be overridden', function(done) {
var expectedTokenId = this.token.id; const expectedTokenId = this.token.id;
var current = Token.resolve; const current = Token.resolve;
var called = false; let called = false;
Token.resolve = function(id, cb) { Token.resolve = function(id, cb) {
called = true; called = true;
process.nextTick(function() { process.nextTick(function() {
cb(null, {id: expectedTokenId}); cb(null, {id: expectedTokenId});
}); });
}; };
var req = mockRequest({ const req = mockRequest({
headers: {'authorization': expectedTokenId}, headers: {'authorization': expectedTokenId},
}); });
@ -622,7 +622,7 @@ describe('AccessToken', function() {
}); });
describe('app.enableAuth()', function() { describe('app.enableAuth()', function() {
var app; let app;
beforeEach(function setupAuthWithModels() { beforeEach(function setupAuthWithModels() {
app = loopback({localRegistry: true, loadBuiltinModels: true}); app = loopback({localRegistry: true, loadBuiltinModels: true});
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
@ -653,7 +653,7 @@ describe('app.enableAuth()', function() {
return done(err); return done(err);
} }
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert(errorResponse); assert(errorResponse);
assert.equal(errorResponse.code, 'AUTHORIZATION_REQUIRED'); assert.equal(errorResponse.code, 'AUTHORIZATION_REQUIRED');
@ -671,7 +671,7 @@ describe('app.enableAuth()', function() {
return done(err); return done(err);
} }
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert(errorResponse); assert(errorResponse);
assert.equal(errorResponse.code, 'ACCESS_DENIED'); assert.equal(errorResponse.code, 'ACCESS_DENIED');
@ -689,7 +689,7 @@ describe('app.enableAuth()', function() {
return done(err); return done(err);
} }
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert(errorResponse); assert(errorResponse);
assert.equal(errorResponse.code, 'MODEL_NOT_FOUND'); assert.equal(errorResponse.code, 'MODEL_NOT_FOUND');
@ -707,7 +707,7 @@ describe('app.enableAuth()', function() {
return done(err); return done(err);
} }
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert(errorResponse); assert(errorResponse);
assert.equal(errorResponse.code, 'AUTHORIZATION_REQUIRED'); assert.equal(errorResponse.code, 'AUTHORIZATION_REQUIRED');
@ -716,9 +716,9 @@ describe('app.enableAuth()', function() {
}); });
it('stores token in the context', function(done) { it('stores token in the context', function(done) {
var TestModel = app.registry.createModel('TestModel', {base: 'Model'}); const TestModel = app.registry.createModel('TestModel', {base: 'Model'});
TestModel.getToken = function(cb) { TestModel.getToken = function(cb) {
var ctx = LoopBackContext.getCurrentContext(); const ctx = LoopBackContext.getCurrentContext();
cb(null, ctx && ctx.get('accessToken') || null); cb(null, ctx && ctx.get('accessToken') || null);
}; };
TestModel.remoteMethod('getToken', { TestModel.remoteMethod('getToken', {
@ -733,7 +733,7 @@ describe('app.enableAuth()', function() {
app.use(loopback.token({model: Token})); app.use(loopback.token({model: Token}));
app.use(loopback.rest()); app.use(loopback.rest());
var token = this.token; const token = this.token;
request(app) request(app)
.get('/TestModels/token?_format=json') .get('/TestModels/token?_format=json')
.set('authorization', token.id) .set('authorization', token.id)
@ -772,7 +772,7 @@ describe('app.enableAuth()', function() {
}); });
function createTestingToken(done) { function createTestingToken(done) {
var test = this; const test = this;
Token.create({userId: '123'}, function(err, token) { Token.create({userId: '123'}, function(err, token) {
if (err) return done(err); if (err) return done(err);
@ -783,7 +783,7 @@ function createTestingToken(done) {
} }
function createTestAppAndRequest(testToken, settings, done) { function createTestAppAndRequest(testToken, settings, done) {
var app = createTestApp(testToken, settings, done); const app = createTestApp(testToken, settings, done);
return request(app); return request(app);
} }
@ -793,14 +793,14 @@ function createTestApp(testToken, settings, done) {
settings = {}; settings = {};
} }
var appSettings = settings.app || {}; const appSettings = settings.app || {};
var modelSettings = settings.model || {}; const modelSettings = settings.model || {};
var tokenSettings = extend({ const tokenSettings = extend({
model: Token, model: Token,
currentUserLiteral: 'me', currentUserLiteral: 'me',
}, settings.token); }, settings.token);
var app = loopback({localRegistry: true, loadBuiltinModels: true}); const app = loopback({localRegistry: true, loadBuiltinModels: true});
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
app.use(cookieParser('secret')); app.use(cookieParser('secret'));
@ -824,7 +824,7 @@ function createTestApp(testToken, settings, done) {
res.status(req.accessToken ? 200 : 401).end(); res.status(req.accessToken ? 200 : 401).end();
}); });
app.use('/users/:uid', function(req, res) { app.use('/users/:uid', function(req, res) {
var result = {userId: req.params.uid}; const result = {userId: req.params.uid};
if (req.query.state) { if (req.query.state) {
result.state = req.query.state; result.state = req.query.state;
} else if (req.url !== '/') { } else if (req.url !== '/') {
@ -839,7 +839,7 @@ function createTestApp(testToken, settings, done) {
app.set(key, appSettings[key]); app.set(key, appSettings[key]);
}); });
var modelOptions = { const modelOptions = {
acls: [ acls: [
{ {
principalType: 'ROLE', principalType: 'ROLE',
@ -855,20 +855,20 @@ function createTestApp(testToken, settings, done) {
modelOptions[key] = modelSettings[key]; modelOptions[key] = modelSettings[key];
}); });
var TestModel = app.registry.createModel('test', {}, modelOptions); const TestModel = app.registry.createModel('test', {}, modelOptions);
app.model(TestModel, {dataSource: 'db'}); app.model(TestModel, {dataSource: 'db'});
return app; return app;
} }
function givenLocalTokenModel() { function givenLocalTokenModel() {
var app = loopback({localRegistry: true, loadBuiltinModels: true}); const app = loopback({localRegistry: true, loadBuiltinModels: true});
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
var User = app.registry.getModel('User'); const User = app.registry.getModel('User');
app.model(User, {dataSource: 'db'}); app.model(User, {dataSource: 'db'});
var Token = app.registry.getModel('AccessToken'); const Token = app.registry.getModel('AccessToken');
app.model(Token, {dataSource: 'db'}); app.model(Token, {dataSource: 'db'});
return Token; return Token;

View File

@ -4,24 +4,24 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var loopback = require('../index'); const loopback = require('../index');
var Scope = loopback.Scope; const Scope = loopback.Scope;
var ACL = loopback.ACL; const ACL = loopback.ACL;
var request = require('supertest'); const request = require('supertest');
var Promise = require('bluebird'); const Promise = require('bluebird');
var supertest = require('supertest'); const supertest = require('supertest');
var Role = loopback.Role; const Role = loopback.Role;
var RoleMapping = loopback.RoleMapping; const RoleMapping = loopback.RoleMapping;
var User = loopback.User; const User = loopback.User;
var async = require('async'); const async = require('async');
// Speed up the password hashing algorithm for tests // Speed up the password hashing algorithm for tests
User.settings.saltWorkFactor = 4; User.settings.saltWorkFactor = 4;
var ds = null; let ds = null;
var testModel; let testModel;
describe('ACL model', function() { describe('ACL model', function() {
it('provides DEFAULT_SCOPE constant', () => { it('provides DEFAULT_SCOPE constant', () => {
@ -144,7 +144,7 @@ describe('security ACLs', function() {
}); });
it('supports checkAccessForContext() returning a promise', function() { it('supports checkAccessForContext() returning a promise', function() {
var testModel = ds.createModel('testModel', { const testModel = ds.createModel('testModel', {
acls: [ acls: [
{principalType: ACL.USER, principalId: 'u001', {principalType: ACL.USER, principalId: 'u001',
accessType: ACL.ALL, permission: ACL.ALLOW}, accessType: ACL.ALL, permission: ACL.ALLOW},
@ -162,7 +162,7 @@ describe('security ACLs', function() {
}); });
it('should order ACL entries based on the matching score', function() { it('should order ACL entries based on the matching score', function() {
var acls = [ let acls = [
{ {
'model': 'account', 'model': 'account',
'accessType': '*', 'accessType': '*',
@ -184,7 +184,7 @@ describe('security ACLs', function() {
'principalType': 'ROLE', 'principalType': 'ROLE',
'principalId': '$everyone', 'principalId': '$everyone',
}]; }];
var req = { const req = {
model: 'account', model: 'account',
property: 'find', property: 'find',
accessType: 'WRITE', accessType: 'WRITE',
@ -192,7 +192,7 @@ describe('security ACLs', function() {
acls = acls.map(function(a) { return new ACL(a); }); acls = acls.map(function(a) { return new ACL(a); });
var perm = ACL.resolvePermission(acls, req); const perm = ACL.resolvePermission(acls, req);
// remove the registry from AccessRequest instance to ease asserting // remove the registry from AccessRequest instance to ease asserting
delete perm.registry; delete perm.registry;
assert.deepEqual(perm, {model: 'account', assert.deepEqual(perm, {model: 'account',
@ -214,7 +214,7 @@ describe('security ACLs', function() {
}); });
it('should order ACL entries based on the matching score even with wildcard req', function() { it('should order ACL entries based on the matching score even with wildcard req', function() {
var acls = [ let acls = [
{ {
'model': 'account', 'model': 'account',
'accessType': '*', 'accessType': '*',
@ -229,7 +229,7 @@ describe('security ACLs', function() {
'principalType': 'ROLE', 'principalType': 'ROLE',
'principalId': '$owner', 'principalId': '$owner',
}]; }];
var req = { const req = {
model: 'account', model: 'account',
property: '*', property: '*',
accessType: 'WRITE', accessType: 'WRITE',
@ -237,7 +237,7 @@ describe('security ACLs', function() {
acls = acls.map(function(a) { return new ACL(a); }); acls = acls.map(function(a) { return new ACL(a); });
var perm = ACL.resolvePermission(acls, req); const perm = ACL.resolvePermission(acls, req);
// remove the registry from AccessRequest instance to ease asserting. // remove the registry from AccessRequest instance to ease asserting.
// Check the above test case for more info. // Check the above test case for more info.
delete perm.registry; delete perm.registry;
@ -311,7 +311,7 @@ describe('security ACLs', function() {
}); });
it('should honor defaultPermission from the model', function(done) { it('should honor defaultPermission from the model', function(done) {
var Customer = ds.createModel('Customer', { const Customer = ds.createModel('Customer', {
name: { name: {
type: String, type: String,
acls: [ acls: [
@ -347,7 +347,7 @@ describe('security ACLs', function() {
}); });
it('should honor static ACLs from the model', function(done) { it('should honor static ACLs from the model', function(done) {
var Customer = ds.createModel('Customer', { const Customer = ds.createModel('Customer', {
name: { name: {
type: String, type: String,
acls: [ acls: [
@ -394,7 +394,7 @@ describe('security ACLs', function() {
}); });
it('should filter static ACLs by model/property', function() { it('should filter static ACLs by model/property', function() {
var Model1 = ds.createModel('Model1', { const Model1 = ds.createModel('Model1', {
name: { name: {
type: String, type: String,
acls: [ acls: [
@ -415,7 +415,7 @@ describe('security ACLs', function() {
], ],
}); });
var staticACLs = ACL.getStaticACLs('Model1', 'name'); let staticACLs = ACL.getStaticACLs('Model1', 'name');
assert(staticACLs.length === 3); assert(staticACLs.length === 3);
staticACLs = ACL.getStaticACLs('Model1', 'findOne'); staticACLs = ACL.getStaticACLs('Model1', 'findOne');
@ -427,16 +427,16 @@ describe('security ACLs', function() {
}); });
it('should check access against LDL, ACL, and Role', function(done) { it('should check access against LDL, ACL, and Role', function(done) {
var log = function() {}; const log = function() {};
// Create // Create
User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function(err, user) { User.create({name: 'Raymond', email: 'x@y.com', password: 'foobar'}, function(err, user) {
log('User: ', user.toObject()); log('User: ', user.toObject());
var userId = user.id; const userId = user.id;
// Define a model with static ACLs // Define a model with static ACLs
var Customer = ds.createModel('Customer', { const Customer = ds.createModel('Customer', {
name: { name: {
type: String, type: String,
acls: [ acls: [
@ -514,10 +514,10 @@ describe('security ACLs', function() {
describe('access check', function() { describe('access check', function() {
it('should occur before other remote hooks', function(done) { it('should occur before other remote hooks', function(done) {
var app = loopback(); const app = loopback();
var MyTestModel = app.registry.createModel('MyTestModel'); const MyTestModel = app.registry.createModel('MyTestModel');
var checkAccessCalled = false; let checkAccessCalled = false;
var beforeHookCalled = false; let beforeHookCalled = false;
app.use(loopback.rest()); app.use(loopback.rest());
app.set('remoting', {errorHandler: {debug: true, log: false}}); app.set('remoting', {errorHandler: {debug: true, log: false}});
@ -527,9 +527,9 @@ describe('access check', function() {
// fake / spy on the checkAccess method // fake / spy on the checkAccess method
MyTestModel.checkAccess = function() { MyTestModel.checkAccess = function() {
var cb = arguments[arguments.length - 1]; const cb = arguments[arguments.length - 1];
checkAccessCalled = true; checkAccessCalled = true;
var allowed = true; const allowed = true;
cb(null, allowed); cb(null, allowed);
}; };
@ -554,8 +554,8 @@ describe('access check', function() {
}); });
describe('authorized roles propagation in RemotingContext', function() { describe('authorized roles propagation in RemotingContext', function() {
var app, request, accessToken; let app, request, accessToken;
var models = {}; let models = {};
beforeEach(setupAppAndRequest); beforeEach(setupAppAndRequest);
@ -567,7 +567,7 @@ describe('authorized roles propagation in RemotingContext', function() {
]) ])
.then(makeAuthorizedHttpRequestOnMyTestModel) .then(makeAuthorizedHttpRequestOnMyTestModel)
.then(function() { .then(function() {
var ctx = models.MyTestModel.lastRemotingContext; const ctx = models.MyTestModel.lastRemotingContext;
expect(ctx.args.options.authorizedRoles).to.eql( expect(ctx.args.options.authorizedRoles).to.eql(
{ {
$everyone: true, $everyone: true,
@ -586,7 +586,7 @@ describe('authorized roles propagation in RemotingContext', function() {
]) ])
.then(makeAuthorizedHttpRequestOnMyTestModel) .then(makeAuthorizedHttpRequestOnMyTestModel)
.then(function() { .then(function() {
var ctx = models.MyTestModel.lastRemotingContext; const ctx = models.MyTestModel.lastRemotingContext;
expect(ctx.args.options.authorizedRoles).to.eql( expect(ctx.args.options.authorizedRoles).to.eql(
{ {
$everyone: true, $everyone: true,
@ -607,7 +607,7 @@ describe('authorized roles propagation in RemotingContext', function() {
]) ])
.then(makeAuthorizedHttpRequestOnMyTestModel) .then(makeAuthorizedHttpRequestOnMyTestModel)
.then(function() { .then(function() {
var ctx = models.MyTestModel.lastRemotingContext; const ctx = models.MyTestModel.lastRemotingContext;
expect(ctx.args.options.authorizedRoles).to.eql( expect(ctx.args.options.authorizedRoles).to.eql(
// '$everyone' is not expected as default permission is DENY // '$everyone' is not expected as default permission is DENY
{myRole: true} {myRole: true}

View File

@ -4,36 +4,36 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var async = require('async'); const async = require('async');
var path = require('path'); const path = require('path');
var http = require('http'); const http = require('http');
var express = require('express'); const express = require('express');
var loopback = require('../'); const loopback = require('../');
var PersistedModel = loopback.PersistedModel; const PersistedModel = loopback.PersistedModel;
var describe = require('./util/describe'); const describe = require('./util/describe');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var it = require('./util/it'); const it = require('./util/it');
var request = require('supertest'); const request = require('supertest');
const sinon = require('sinon'); const sinon = require('sinon');
describe('app', function() { describe('app', function() {
var app; let app;
beforeEach(function() { beforeEach(function() {
app = loopback({localRegistry: true, loadBuiltinModels: true}); app = loopback({localRegistry: true, loadBuiltinModels: true});
}); });
describe.onServer('.middleware(phase, handler)', function() { describe.onServer('.middleware(phase, handler)', function() {
var steps; let steps;
beforeEach(function setup() { beforeEach(function setup() {
steps = []; steps = [];
}); });
it('runs middleware in phases', function(done) { it('runs middleware in phases', function(done) {
var PHASES = [ const PHASES = [
'initial', 'session', 'auth', 'parse', 'initial', 'session', 'auth', 'parse',
'routes', 'files', 'final', 'routes', 'files', 'final',
]; ];
@ -88,10 +88,10 @@ describe('app', function() {
return namedHandler(name); return namedHandler(name);
} }
var myHandler; let myHandler;
app.middleware('routes:before', app.middleware('routes:before',
myHandler = handlerThatAddsHandler('my-handler')); myHandler = handlerThatAddsHandler('my-handler'));
var found = app._findLayerByHandler(myHandler); const found = app._findLayerByHandler(myHandler);
expect(found).to.be.an('object'); expect(found).to.be.an('object');
expect(myHandler).to.equal(found.handle); expect(myHandler).to.equal(found.handle);
expect(found).have.property('phase', 'routes:before'); expect(found).have.property('phase', 'routes:before');
@ -106,13 +106,13 @@ describe('app', function() {
it('allows handlers to be wrapped as __NR_handler on express stack', it('allows handlers to be wrapped as __NR_handler on express stack',
function(done) { function(done) {
var myHandler = namedHandler('my-handler'); const myHandler = namedHandler('my-handler');
var wrappedHandler = function(req, res, next) { const wrappedHandler = function(req, res, next) {
myHandler(req, res, next); myHandler(req, res, next);
}; };
wrappedHandler['__NR_handler'] = myHandler; wrappedHandler['__NR_handler'] = myHandler;
app.middleware('routes:before', wrappedHandler); app.middleware('routes:before', wrappedHandler);
var found = app._findLayerByHandler(myHandler); const found = app._findLayerByHandler(myHandler);
expect(found).to.be.an('object'); expect(found).to.be.an('object');
expect(found).have.property('phase', 'routes:before'); expect(found).have.property('phase', 'routes:before');
executeMiddlewareHandlers(app, function(err) { executeMiddlewareHandlers(app, function(err) {
@ -126,15 +126,15 @@ describe('app', function() {
it('allows handlers to be wrapped as __appdynamicsProxyInfo__ on express stack', it('allows handlers to be wrapped as __appdynamicsProxyInfo__ on express stack',
function(done) { function(done) {
var myHandler = namedHandler('my-handler'); const myHandler = namedHandler('my-handler');
var wrappedHandler = function(req, res, next) { const wrappedHandler = function(req, res, next) {
myHandler(req, res, next); myHandler(req, res, next);
}; };
wrappedHandler['__appdynamicsProxyInfo__'] = { wrappedHandler['__appdynamicsProxyInfo__'] = {
orig: myHandler, orig: myHandler,
}; };
app.middleware('routes:before', wrappedHandler); app.middleware('routes:before', wrappedHandler);
var found = app._findLayerByHandler(myHandler); const found = app._findLayerByHandler(myHandler);
expect(found).to.be.an('object'); expect(found).to.be.an('object');
expect(found).have.property('phase', 'routes:before'); expect(found).have.property('phase', 'routes:before');
executeMiddlewareHandlers(app, function(err) { executeMiddlewareHandlers(app, function(err) {
@ -148,13 +148,13 @@ describe('app', function() {
it('allows handlers to be wrapped as a property on express stack', it('allows handlers to be wrapped as a property on express stack',
function(done) { function(done) {
var myHandler = namedHandler('my-handler'); const myHandler = namedHandler('my-handler');
var wrappedHandler = function(req, res, next) { const wrappedHandler = function(req, res, next) {
myHandler(req, res, next); myHandler(req, res, next);
}; };
wrappedHandler['__handler'] = myHandler; wrappedHandler['__handler'] = myHandler;
app.middleware('routes:before', wrappedHandler); app.middleware('routes:before', wrappedHandler);
var found = app._findLayerByHandler(myHandler); const found = app._findLayerByHandler(myHandler);
expect(found).to.be.an('object'); expect(found).to.be.an('object');
expect(found).have.property('phase', 'routes:before'); expect(found).have.property('phase', 'routes:before');
executeMiddlewareHandlers(app, function(err) { executeMiddlewareHandlers(app, function(err) {
@ -167,7 +167,7 @@ describe('app', function() {
}); });
it('injects error from previous phases into the router', function(done) { it('injects error from previous phases into the router', function(done) {
var expectedError = new Error('expected error'); const expectedError = new Error('expected error');
app.middleware('initial', function(req, res, next) { app.middleware('initial', function(req, res, next) {
steps.push('initial'); steps.push('initial');
@ -193,7 +193,7 @@ describe('app', function() {
}); });
it('passes unhandled error to callback', function(done) { it('passes unhandled error to callback', function(done) {
var expectedError = new Error('expected error'); const expectedError = new Error('expected error');
app.middleware('initial', function(req, res, next) { app.middleware('initial', function(req, res, next) {
next(expectedError); next(expectedError);
@ -207,8 +207,8 @@ describe('app', function() {
}); });
it('passes errors to error handlers in the same phase', function(done) { it('passes errors to error handlers in the same phase', function(done) {
var expectedError = new Error('this should be handled by middleware'); const expectedError = new Error('this should be handled by middleware');
var handledError; let handledError;
app.middleware('initial', function(req, res, next) { app.middleware('initial', function(req, res, next) {
// continue in the next tick, this verifies that the next // continue in the next tick, this verifies that the next
@ -298,7 +298,7 @@ describe('app', function() {
}); });
it('exposes express helpers on req and res objects', function(done) { it('exposes express helpers on req and res objects', function(done) {
var req, res; let req, res;
app.middleware('initial', function(rq, rs, next) { app.middleware('initial', function(rq, rs, next) {
req = rq; req = rq;
@ -336,7 +336,7 @@ describe('app', function() {
}); });
it('sets req.baseUrl and req.originalUrl', function(done) { it('sets req.baseUrl and req.originalUrl', function(done) {
var reqProps; let reqProps;
app.middleware('initial', function(req, res, next) { app.middleware('initial', function(req, res, next) {
reqProps = {baseUrl: req.baseUrl, originalUrl: req.originalUrl}; reqProps = {baseUrl: req.baseUrl, originalUrl: req.originalUrl};
@ -374,7 +374,7 @@ describe('app', function() {
// we need at least 9 elements to expose non-stability // we need at least 9 elements to expose non-stability
// of the built-in sort function // of the built-in sort function
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]; const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
numbers.forEach(function(n) { numbers.forEach(function(n) {
app.middleware('routes', namedHandler(n)); app.middleware('routes', namedHandler(n));
}); });
@ -389,8 +389,8 @@ describe('app', function() {
}); });
it('correctly mounts express apps', function(done) { it('correctly mounts express apps', function(done) {
var data, mountWasEmitted; let data, mountWasEmitted;
var subapp = express(); const subapp = express();
subapp.use(function(req, res, next) { subapp.use(function(req, res, next) {
data = { data = {
mountpath: req.app.mountpath, mountpath: req.app.mountpath,
@ -417,10 +417,10 @@ describe('app', function() {
}); });
it('restores req & res on return from mounted express app', function(done) { it('restores req & res on return from mounted express app', function(done) {
var expected = {}; const expected = {};
var actual = {}; const actual = {};
var subapp = express(); const subapp = express();
subapp.use(function verifyTestAssumptions(req, res, next) { subapp.use(function verifyTestAssumptions(req, res, next) {
expect(req.__proto__).to.not.equal(expected.req); expect(req.__proto__).to.not.equal(expected.req);
expect(res.__proto__).to.not.equal(expected.res); expect(res.__proto__).to.not.equal(expected.res);
@ -468,8 +468,8 @@ describe('app', function() {
} }
function getObjectAndPrototypeKeys(obj) { function getObjectAndPrototypeKeys(obj) {
var result = []; const result = [];
for (var k in obj) { for (const k in obj) {
result.push(k); result.push(k);
} }
result.sort(); result.sort();
@ -479,11 +479,11 @@ describe('app', function() {
describe.onServer('.middlewareFromConfig', function() { describe.onServer('.middlewareFromConfig', function() {
it('provides API for loading middleware from JSON config', function(done) { it('provides API for loading middleware from JSON config', function(done) {
var steps = []; const steps = [];
var expectedConfig = {key: 'value'}; const expectedConfig = {key: 'value'};
var handlerFactory = function() { const handlerFactory = function() {
var args = Array.prototype.slice.apply(arguments); const args = Array.prototype.slice.apply(arguments);
return function(req, res, next) { return function(req, res, next) {
steps.push(args); steps.push(args);
@ -550,7 +550,7 @@ describe('app', function() {
}); });
it('scopes middleware from config to a list of scopes', function(done) { it('scopes middleware from config to a list of scopes', function(done) {
var steps = []; const steps = [];
app.middlewareFromConfig( app.middlewareFromConfig(
function factory() { function factory() {
return function(req, res, next) { return function(req, res, next) {
@ -580,7 +580,7 @@ describe('app', function() {
}); });
describe.onServer('.defineMiddlewarePhases(nameOrArray)', function() { describe.onServer('.defineMiddlewarePhases(nameOrArray)', function() {
var app; let app;
beforeEach(function() { beforeEach(function() {
app = loopback(); app = loopback();
}); });
@ -626,7 +626,7 @@ describe('app', function() {
}); });
function verifyMiddlewarePhases(names, done) { function verifyMiddlewarePhases(names, done) {
var steps = []; const steps = [];
names.forEach(function(it) { names.forEach(function(it) {
app.middleware(it, function(req, res, next) { app.middleware(it, function(req, res, next) {
steps.push(it); steps.push(it);
@ -646,7 +646,7 @@ describe('app', function() {
}); });
describe('app.model(Model)', function() { describe('app.model(Model)', function() {
var app, db, MyTestModel; let app, db, MyTestModel;
beforeEach(function() { beforeEach(function() {
app = loopback(); app = loopback();
app.set('remoting', {errorHandler: {debug: true, log: false}}); app.set('remoting', {errorHandler: {debug: true, log: false}});
@ -655,7 +655,7 @@ describe('app', function() {
}); });
it('Expose a `Model` to remote clients', function() { it('Expose a `Model` to remote clients', function() {
var Color = PersistedModel.extend('color', {name: String}); const Color = PersistedModel.extend('color', {name: String});
app.model(Color); app.model(Color);
Color.attachTo(db); Color.attachTo(db);
@ -663,22 +663,22 @@ describe('app', function() {
}); });
it('uses singular name as app.remoteObjects() key', function() { it('uses singular name as app.remoteObjects() key', function() {
var Color = PersistedModel.extend('color', {name: String}); const Color = PersistedModel.extend('color', {name: String});
app.model(Color); app.model(Color);
Color.attachTo(db); Color.attachTo(db);
expect(app.remoteObjects()).to.eql({color: Color}); expect(app.remoteObjects()).to.eql({color: Color});
}); });
it('uses singular name as shared class name', function() { it('uses singular name as shared class name', function() {
var Color = PersistedModel.extend('color', {name: String}); const Color = PersistedModel.extend('color', {name: String});
app.model(Color); app.model(Color);
Color.attachTo(db); Color.attachTo(db);
var classes = app.remotes().classes().map(function(c) { return c.name; }); const classes = app.remotes().classes().map(function(c) { return c.name; });
expect(classes).to.contain('color'); expect(classes).to.contain('color');
}); });
it('registers existing models to app.models', function() { it('registers existing models to app.models', function() {
var Color = db.createModel('color', {name: String}); const Color = db.createModel('color', {name: String});
app.model(Color); app.model(Color);
expect(Color.app).to.be.equal(app); expect(Color.app).to.be.equal(app);
expect(Color.shared).to.equal(true); expect(Color.shared).to.equal(true);
@ -687,9 +687,9 @@ describe('app', function() {
}); });
it('emits a `modelRemoted` event', function() { it('emits a `modelRemoted` event', function() {
var Color = PersistedModel.extend('color', {name: String}); const Color = PersistedModel.extend('color', {name: String});
Color.shared = true; Color.shared = true;
var remotedClass; let remotedClass;
app.on('modelRemoted', function(sharedClass) { app.on('modelRemoted', function(sharedClass) {
remotedClass = sharedClass; remotedClass = sharedClass;
}); });
@ -699,9 +699,9 @@ describe('app', function() {
}); });
it('emits a `remoteMethodDisabled` event', function() { it('emits a `remoteMethodDisabled` event', function() {
var Color = PersistedModel.extend('color', {name: String}); const Color = PersistedModel.extend('color', {name: String});
Color.shared = true; Color.shared = true;
var remoteMethodDisabledClass, disabledRemoteMethod; let remoteMethodDisabledClass, disabledRemoteMethod;
app.on('remoteMethodDisabled', function(sharedClass, methodName) { app.on('remoteMethodDisabled', function(sharedClass, methodName) {
remoteMethodDisabledClass = sharedClass; remoteMethodDisabledClass = sharedClass;
disabledRemoteMethod = methodName; disabledRemoteMethod = methodName;
@ -716,14 +716,14 @@ describe('app', function() {
it('emits a `remoteMethodAdded` event', function() { it('emits a `remoteMethodAdded` event', function() {
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
var Book = app.registry.createModel( const Book = app.registry.createModel(
'Book', 'Book',
{name: 'string'}, {name: 'string'},
{plural: 'books'} {plural: 'books'}
); );
app.model(Book, {dataSource: 'db'}); app.model(Book, {dataSource: 'db'});
var Page = app.registry.createModel( const Page = app.registry.createModel(
'Page', 'Page',
{name: 'string'}, {name: 'string'},
{plural: 'pages'} {plural: 'pages'}
@ -732,7 +732,7 @@ describe('app', function() {
Book.hasMany(Page); Book.hasMany(Page);
var remoteMethodAddedClass; let remoteMethodAddedClass;
app.on('remoteMethodAdded', function(sharedClass) { app.on('remoteMethodAdded', function(sharedClass) {
remoteMethodAddedClass = sharedClass; remoteMethodAddedClass = sharedClass;
}); });
@ -759,14 +759,14 @@ describe('app', function() {
}); });
it('throws error if model typeof string is passed', function() { it('throws error if model typeof string is passed', function() {
var fn = function() { app.model('MyTestModel'); }; const fn = function() { app.model('MyTestModel'); };
expect(fn).to.throw(/app(\.model|\.registry)/); expect(fn).to.throw(/app(\.model|\.registry)/);
}); });
}); });
describe('app.model(ModelCtor, config)', function() { describe('app.model(ModelCtor, config)', function() {
it('attaches the model to a datasource', function() { it('attaches the model to a datasource', function() {
var previousModel = loopback.registry.findModel('TestModel'); const previousModel = loopback.registry.findModel('TestModel');
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
if (previousModel) { if (previousModel) {
@ -774,7 +774,7 @@ describe('app', function() {
} }
assert(!previousModel || !previousModel.dataSource); assert(!previousModel || !previousModel.dataSource);
var TestModel = app.registry.createModel('TestModel'); const TestModel = app.registry.createModel('TestModel');
app.model(TestModel, {dataSource: 'db'}); app.model(TestModel, {dataSource: 'db'});
expect(app.models.TestModel.dataSource).to.equal(app.dataSources.db); expect(app.models.TestModel.dataSource).to.equal(app.dataSources.db);
}); });
@ -843,10 +843,10 @@ describe('app', function() {
describe('app.models', function() { describe('app.models', function() {
it('is unique per app instance', function() { it('is unique per app instance', function() {
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
var Color = app.registry.createModel('Color'); const Color = app.registry.createModel('Color');
app.model(Color, {dataSource: 'db'}); app.model(Color, {dataSource: 'db'});
expect(app.models.Color).to.equal(Color); expect(app.models.Color).to.equal(Color);
var anotherApp = loopback(); const anotherApp = loopback();
expect(anotherApp.models.Color).to.equal(undefined); expect(anotherApp.models.Color).to.equal(undefined);
}); });
}); });
@ -855,7 +855,7 @@ describe('app', function() {
it('is unique per app instance', function() { it('is unique per app instance', function() {
app.dataSource('ds', {connector: 'memory'}); app.dataSource('ds', {connector: 'memory'});
expect(app.datasources.ds).to.not.equal(undefined); expect(app.datasources.ds).to.not.equal(undefined);
var anotherApp = loopback(); const anotherApp = loopback();
expect(anotherApp.datasources.ds).to.equal(undefined); expect(anotherApp.datasources.ds).to.equal(undefined);
}); });
}); });
@ -886,11 +886,11 @@ describe('app', function() {
describe.onServer('listen()', function() { describe.onServer('listen()', function() {
it('starts http server', function(done) { it('starts http server', function(done) {
var app = loopback(); const app = loopback();
app.set('port', 0); app.set('port', 0);
app.get('/', function(req, res) { res.status(200).send('OK'); }); app.get('/', function(req, res) { res.status(200).send('OK'); });
var server = app.listen(); const server = app.listen();
expect(server).to.be.an.instanceOf(require('http').Server); expect(server).to.be.an.instanceOf(require('http').Server);
@ -900,7 +900,7 @@ describe('app', function() {
}); });
it('updates port on `listening` event', function(done) { it('updates port on `listening` event', function(done) {
var app = loopback(); const app = loopback();
app.set('port', 0); app.set('port', 0);
app.listen(function() { app.listen(function() {
@ -911,12 +911,12 @@ describe('app', function() {
}); });
it('updates `url` on `listening` event', function(done) { it('updates `url` on `listening` event', function(done) {
var app = loopback(); const app = loopback();
app.set('port', 0); app.set('port', 0);
app.set('host', undefined); app.set('host', undefined);
app.listen(function() { app.listen(function() {
var expectedUrl = 'http://localhost:' + app.get('port') + '/'; const expectedUrl = 'http://localhost:' + app.get('port') + '/';
expect(app.get('url'), 'url').to.equal(expectedUrl); expect(app.get('url'), 'url').to.equal(expectedUrl);
done(); done();
@ -924,7 +924,7 @@ describe('app', function() {
}); });
it('forwards to http.Server.listen on more than one arg', function(done) { it('forwards to http.Server.listen on more than one arg', function(done) {
var app = loopback(); const app = loopback();
app.set('port', 1); app.set('port', 1);
app.listen(0, '127.0.0.1', function() { app.listen(0, '127.0.0.1', function() {
expect(app.get('port'), 'port').to.not.equal(0).and.not.equal(1); expect(app.get('port'), 'port').to.not.equal(0).and.not.equal(1);
@ -935,7 +935,7 @@ describe('app', function() {
}); });
it('forwards to http.Server.listen when the single arg is not a function', function(done) { it('forwards to http.Server.listen when the single arg is not a function', function(done) {
var app = loopback(); const app = loopback();
app.set('port', 1); app.set('port', 1);
app.listen(0).on('listening', function() { app.listen(0).on('listening', function() {
expect(app.get('port'), 'port') .to.not.equal(0).and.not.equal(1); expect(app.get('port'), 'port') .to.not.equal(0).and.not.equal(1);
@ -945,7 +945,7 @@ describe('app', function() {
}); });
it('uses app config when no parameter is supplied', function(done) { it('uses app config when no parameter is supplied', function(done) {
var app = loopback(); const app = loopback();
// Http listens on all interfaces by default // Http listens on all interfaces by default
// Custom host serves as an indicator whether // Custom host serves as an indicator whether
// the value was used by app.listen // the value was used by app.listen
@ -967,26 +967,26 @@ describe('app', function() {
}); });
it('auto-configures required models to provided dataSource', function() { it('auto-configures required models to provided dataSource', function() {
var AUTH_MODELS = ['User', 'ACL', 'AccessToken', 'Role', 'RoleMapping']; const AUTH_MODELS = ['User', 'ACL', 'AccessToken', 'Role', 'RoleMapping'];
var app = loopback({localRegistry: true, loadBuiltinModels: true}); const app = loopback({localRegistry: true, loadBuiltinModels: true});
require('../lib/builtin-models')(app.registry); require('../lib/builtin-models')(app.registry);
var db = app.dataSource('db', {connector: 'memory'}); const db = app.dataSource('db', {connector: 'memory'});
app.enableAuth({dataSource: 'db'}); app.enableAuth({dataSource: 'db'});
expect(Object.keys(app.models)).to.include.members(AUTH_MODELS); expect(Object.keys(app.models)).to.include.members(AUTH_MODELS);
AUTH_MODELS.forEach(function(m) { AUTH_MODELS.forEach(function(m) {
var Model = app.models[m]; const Model = app.models[m];
expect(Model.dataSource, m + '.dataSource').to.equal(db); expect(Model.dataSource, m + '.dataSource').to.equal(db);
expect(Model.shared, m + '.shared').to.equal(m === 'User'); expect(Model.shared, m + '.shared').to.equal(m === 'User');
}); });
}); });
it('detects already configured subclass of a required model', function() { it('detects already configured subclass of a required model', function() {
var app = loopback({localRegistry: true, loadBuiltinModels: true}); const app = loopback({localRegistry: true, loadBuiltinModels: true});
var db = app.dataSource('db', {connector: 'memory'}); const db = app.dataSource('db', {connector: 'memory'});
var Customer = app.registry.createModel('Customer', {}, {base: 'User'}); const Customer = app.registry.createModel('Customer', {}, {base: 'User'});
app.model(Customer, {dataSource: 'db'}); app.model(Customer, {dataSource: 'db'});
// Fix AccessToken's "belongsTo user" relation to use our new Customer model // Fix AccessToken's "belongsTo user" relation to use our new Customer model
@ -1001,7 +1001,7 @@ describe('app', function() {
describe.onServer('app.get(\'/\', loopback.status())', function() { describe.onServer('app.get(\'/\', loopback.status())', function() {
it('should return the status of the application', function(done) { it('should return the status of the application', function(done) {
var app = loopback(); const app = loopback();
app.get('/', loopback.status()); app.get('/', loopback.status());
request(app) request(app)
.get('/') .get('/')
@ -1013,7 +1013,7 @@ describe('app', function() {
expect(res.body).to.have.property('started'); expect(res.body).to.have.property('started');
expect(res.body.uptime, 'uptime').to.be.gte(0); expect(res.body.uptime, 'uptime').to.be.gte(0);
var elapsed = Date.now() - Number(new Date(res.body.started)); const elapsed = Date.now() - Number(new Date(res.body.started));
// elapsed should be a small positive number... // elapsed should be a small positive number...
expect(elapsed, 'elapsed').to.be.within(0, 300); expect(elapsed, 'elapsed').to.be.within(0, 300);
@ -1026,7 +1026,7 @@ describe('app', function() {
describe('app.connectors', function() { describe('app.connectors', function() {
it('is unique per app instance', function() { it('is unique per app instance', function() {
app.connectors.foo = 'bar'; app.connectors.foo = 'bar';
var anotherApp = loopback(); const anotherApp = loopback();
expect(anotherApp.connectors.foo).to.equal(undefined); expect(anotherApp.connectors.foo).to.equal(undefined);
}); });
@ -1069,8 +1069,8 @@ describe('app', function() {
}); });
it('is unique per app instance', function() { it('is unique per app instance', function() {
var app1 = loopback(); const app1 = loopback();
var app2 = loopback(); const app2 = loopback();
expect(app1.settings).to.not.equal(app2.settings); expect(app1.settings).to.not.equal(app2.settings);
@ -1080,18 +1080,18 @@ describe('app', function() {
}); });
it('exposes loopback as a property', function() { it('exposes loopback as a property', function() {
var app = loopback(); const app = loopback();
expect(app.loopback).to.equal(loopback); expect(app.loopback).to.equal(loopback);
}); });
function setupUserModels(app, options, done) { function setupUserModels(app, options, done) {
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
var UserAccount = app.registry.createModel( const UserAccount = app.registry.createModel(
'UserAccount', 'UserAccount',
{name: 'string'}, {name: 'string'},
options options
); );
var UserRole = app.registry.createModel( const UserRole = app.registry.createModel(
'UserRole', 'UserRole',
{name: 'string'} {name: 'string'}
); );
@ -1108,7 +1108,7 @@ describe('app', function() {
} }
describe('Model-level normalizeHttpPath option', function() { describe('Model-level normalizeHttpPath option', function() {
var app; let app;
beforeEach(function() { beforeEach(function() {
app = loopback(); app = loopback();
}); });
@ -1144,7 +1144,7 @@ describe('app', function() {
}); });
}); });
describe('app-level normalizeHttpPath option', function() { describe('app-level normalizeHttpPath option', function() {
var app; let app;
beforeEach(function() { beforeEach(function() {
app = loopback(); app = loopback();
}); });
@ -1179,7 +1179,7 @@ describe('app', function() {
}); });
describe('Model-level and app-level normalizeHttpPath options', function() { describe('Model-level and app-level normalizeHttpPath options', function() {
var app; let app;
beforeEach(function() { beforeEach(function() {
app = loopback(); app = loopback();
}); });
@ -1203,8 +1203,8 @@ describe('app', function() {
}); });
function executeMiddlewareHandlers(app, urlPath, callback) { function executeMiddlewareHandlers(app, urlPath, callback) {
var handlerError = undefined; let handlerError = undefined;
var server = http.createServer(function(req, res) { const server = http.createServer(function(req, res) {
app.handle(req, res, function(err) { app.handle(req, res, function(err) {
if (err) { if (err) {
handlerError = err; handlerError = err;

View File

@ -4,17 +4,17 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var sinon = require('sinon'); const sinon = require('sinon');
var loopback = require('../'); const loopback = require('../');
describe('PersistedModel.createChangeStream()', function() { describe('PersistedModel.createChangeStream()', function() {
describe('configured to source changes locally', function() { describe('configured to source changes locally', function() {
before(function() { before(function() {
var test = this; const test = this;
var app = loopback({localRegistry: true}); const app = loopback({localRegistry: true});
var ds = app.dataSource('ds', {connector: 'memory'}); const ds = app.dataSource('ds', {connector: 'memory'});
var Score = app.registry.createModel('Score'); const Score = app.registry.createModel('Score');
this.Score = app.model(Score, { this.Score = app.model(Score, {
dataSource: 'ds', dataSource: 'ds',
changeDataSource: false, // use only local observers changeDataSource: false, // use only local observers
@ -24,7 +24,7 @@ describe('PersistedModel.createChangeStream()', function() {
afterEach(verifyObserversRemoval); afterEach(verifyObserversRemoval);
it('should detect create', function(done) { it('should detect create', function(done) {
var Score = this.Score; const Score = this.Score;
Score.createChangeStream(function(err, changes) { Score.createChangeStream(function(err, changes) {
changes.on('data', function(change) { changes.on('data', function(change) {
@ -38,7 +38,7 @@ describe('PersistedModel.createChangeStream()', function() {
}); });
it('should detect update', function(done) { it('should detect update', function(done) {
var Score = this.Score; const Score = this.Score;
Score.create({team: 'foo'}, function(err, newScore) { Score.create({team: 'foo'}, function(err, newScore) {
Score.createChangeStream(function(err, changes) { Score.createChangeStream(function(err, changes) {
changes.on('data', function(change) { changes.on('data', function(change) {
@ -55,7 +55,7 @@ describe('PersistedModel.createChangeStream()', function() {
}); });
it('should detect delete', function(done) { it('should detect delete', function(done) {
var Score = this.Score; const Score = this.Score;
Score.create({team: 'foo'}, function(err, newScore) { Score.create({team: 'foo'}, function(err, newScore) {
Score.createChangeStream(function(err, changes) { Score.createChangeStream(function(err, changes) {
changes.on('data', function(change) { changes.on('data', function(change) {
@ -103,9 +103,9 @@ describe('PersistedModel.createChangeStream()', function() {
}); });
it('should not emit changes after destroy', function(done) { it('should not emit changes after destroy', function(done) {
var Score = this.Score; const Score = this.Score;
var spy = sinon.spy(); const spy = sinon.spy();
Score.createChangeStream(function(err, changes) { Score.createChangeStream(function(err, changes) {
changes.on('data', function() { changes.on('data', function() {
@ -123,7 +123,7 @@ describe('PersistedModel.createChangeStream()', function() {
}); });
function verifyObserversRemoval() { function verifyObserversRemoval() {
var Score = this.Score; const Score = this.Score;
expect(Score._observers['after save']).to.be.empty(); expect(Score._observers['after save']).to.be.empty();
expect(Score._observers['after delete']).to.be.empty(); expect(Score._observers['after delete']).to.be.empty();
} }
@ -132,10 +132,10 @@ describe('PersistedModel.createChangeStream()', function() {
// TODO(ritch) implement multi-server support // TODO(ritch) implement multi-server support
describe.skip('configured to source changes using pubsub', function() { describe.skip('configured to source changes using pubsub', function() {
before(function() { before(function() {
var test = this; const test = this;
var app = loopback({localRegistry: true}); const app = loopback({localRegistry: true});
var db = app.dataSource('ds', {connector: 'memory'}); const db = app.dataSource('ds', {connector: 'memory'});
var ps = app.dataSource('ps', { const ps = app.dataSource('ps', {
host: 'localhost', host: 'localhost',
port: '12345', port: '12345',
connector: 'pubsub', connector: 'pubsub',
@ -148,7 +148,7 @@ describe('PersistedModel.createChangeStream()', function() {
}); });
it('should detect a change', function(done) { it('should detect a change', function(done) {
var Score = this.Score; const Score = this.Score;
Score.createChangeStream(function(err, changes) { Score.createChangeStream(function(err, changes) {
changes.on('data', function(change) { changes.on('data', function(change) {

View File

@ -4,16 +4,16 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var async = require('async'); const async = require('async');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var loopback = require('../'); const loopback = require('../');
describe('Change', function() { describe('Change', function() {
let Change, TestModel; let Change, TestModel;
beforeEach(function() { beforeEach(function() {
var memory = loopback.createDataSource({ const memory = loopback.createDataSource({
connector: loopback.Memory, connector: loopback.Memory,
}); });
TestModel = loopback.PersistedModel.extend('ChangeTestModel', TestModel = loopback.PersistedModel.extend('ChangeTestModel',
@ -29,7 +29,7 @@ describe('Change', function() {
}); });
beforeEach(function(done) { beforeEach(function(done) {
var test = this; const test = this;
test.data = { test.data = {
foo: 'bar', foo: 'bar',
}; };
@ -52,13 +52,13 @@ describe('Change', function() {
describe('change.id', function() { describe('change.id', function() {
it('should be a hash of the modelName and modelId', function() { it('should be a hash of the modelName and modelId', function() {
var change = new Change({ const change = new Change({
rev: 'abc', rev: 'abc',
modelName: 'foo', modelName: 'foo',
modelId: 'bar', modelId: 'bar',
}); });
var hash = Change.hash([change.modelName, change.modelId].join('-')); const hash = Change.hash([change.modelName, change.modelId].join('-'));
assert.equal(change.id, hash); assert.equal(change.id, hash);
}); });
@ -67,7 +67,7 @@ describe('Change', function() {
describe('Change.rectifyModelChanges(modelName, modelIds, callback)', function() { describe('Change.rectifyModelChanges(modelName, modelIds, callback)', function() {
describe('using an existing untracked model', function() { describe('using an existing untracked model', function() {
beforeEach(function(done) { beforeEach(function(done) {
var test = this; const test = this;
Change.rectifyModelChanges(this.modelName, [this.modelId], function(err, trackedChanges) { Change.rectifyModelChanges(this.modelName, [this.modelId], function(err, trackedChanges) {
if (err) return done(err); if (err) return done(err);
@ -76,7 +76,7 @@ describe('Change', function() {
}); });
it('should create an entry', function(done) { it('should create an entry', function(done) {
var test = this; const test = this;
Change.find(function(err, trackedChanges) { Change.find(function(err, trackedChanges) {
assert.equal(trackedChanges[0].modelId, test.modelId.toString()); assert.equal(trackedChanges[0].modelId, test.modelId.toString());
@ -97,7 +97,7 @@ describe('Change', function() {
describe('Change.rectifyModelChanges - promise variant', function() { describe('Change.rectifyModelChanges - promise variant', function() {
describe('using an existing untracked model', function() { describe('using an existing untracked model', function() {
beforeEach(function(done) { beforeEach(function(done) {
var test = this; const test = this;
Change.rectifyModelChanges(this.modelName, [this.modelId]) Change.rectifyModelChanges(this.modelName, [this.modelId])
.then(function(trackedChanges) { .then(function(trackedChanges) {
done(); done();
@ -106,7 +106,7 @@ describe('Change', function() {
}); });
it('should create an entry', function(done) { it('should create an entry', function(done) {
var test = this; const test = this;
Change.find() Change.find()
.then(function(trackedChanges) { .then(function(trackedChanges) {
assert.equal(trackedChanges[0].modelId, test.modelId.toString()); assert.equal(trackedChanges[0].modelId, test.modelId.toString());
@ -131,7 +131,7 @@ describe('Change', function() {
describe('Change.findOrCreateChange(modelName, modelId, callback)', function() { describe('Change.findOrCreateChange(modelName, modelId, callback)', function() {
describe('when a change doesnt exist', function() { describe('when a change doesnt exist', function() {
beforeEach(function(done) { beforeEach(function(done) {
var test = this; const test = this;
Change.findOrCreateChange(this.modelName, this.modelId, function(err, result) { Change.findOrCreateChange(this.modelName, this.modelId, function(err, result) {
if (err) return done(err); if (err) return done(err);
@ -142,7 +142,7 @@ describe('Change', function() {
}); });
it('should create an entry', function(done) { it('should create an entry', function(done) {
var test = this; const test = this;
Change.findById(this.result.id, function(err, change) { Change.findById(this.result.id, function(err, change) {
if (err) return done(err); if (err) return done(err);
@ -155,7 +155,7 @@ describe('Change', function() {
describe('when a change doesnt exist - promise variant', function() { describe('when a change doesnt exist - promise variant', function() {
beforeEach(function(done) { beforeEach(function(done) {
var test = this; const test = this;
Change.findOrCreateChange(this.modelName, this.modelId) Change.findOrCreateChange(this.modelName, this.modelId)
.then(function(result) { .then(function(result) {
test.result = result; test.result = result;
@ -166,7 +166,7 @@ describe('Change', function() {
}); });
it('should create an entry', function(done) { it('should create an entry', function(done) {
var test = this; const test = this;
Change.findById(this.result.id, function(err, change) { Change.findById(this.result.id, function(err, change) {
if (err) return done(err); if (err) return done(err);
@ -179,7 +179,7 @@ describe('Change', function() {
describe('when a change does exist', function() { describe('when a change does exist', function() {
beforeEach(function(done) { beforeEach(function(done) {
var test = this; const test = this;
Change.create({ Change.create({
modelName: test.modelName, modelName: test.modelName,
modelId: test.modelId, modelId: test.modelId,
@ -191,7 +191,7 @@ describe('Change', function() {
}); });
beforeEach(function(done) { beforeEach(function(done) {
var test = this; const test = this;
Change.findOrCreateChange(this.modelName, this.modelId, function(err, result) { Change.findOrCreateChange(this.modelName, this.modelId, function(err, result) {
if (err) return done(err); if (err) return done(err);
@ -202,7 +202,7 @@ describe('Change', function() {
}); });
it('should find the entry', function(done) { it('should find the entry', function(done) {
var test = this; const test = this;
assert.equal(test.existingChange.id, test.result.id); assert.equal(test.existingChange.id, test.result.id);
done(); done();
@ -211,7 +211,7 @@ describe('Change', function() {
}); });
describe('change.rectify(callback)', function() { describe('change.rectify(callback)', function() {
var change; let change;
beforeEach(function(done) { beforeEach(function(done) {
Change.findOrCreate( Change.findOrCreate(
{ {
@ -227,7 +227,7 @@ describe('Change', function() {
}); });
it('should create a new change with the correct revision', function(done) { it('should create a new change with the correct revision', function(done) {
var test = this; const test = this;
change.rectify(function(err, ch) { change.rectify(function(err, ch) {
assert.equal(ch.rev, test.revisionForModel); assert.equal(ch.rev, test.revisionForModel);
@ -238,9 +238,9 @@ describe('Change', function() {
// This test is a low-level equivalent of the test in replication.test.js // This test is a low-level equivalent of the test in replication.test.js
// called "replicates multiple updates within the same CP" // called "replicates multiple updates within the same CP"
it('should merge updates within the same checkpoint', function(done) { it('should merge updates within the same checkpoint', function(done) {
var test = this; const test = this;
var originalRev = this.revisionForModel; const originalRev = this.revisionForModel;
var cp; let cp;
async.series([ async.series([
rectify, rectify,
@ -274,7 +274,7 @@ describe('Change', function() {
} }
function update(next) { function update(next) {
var model = test.model; const model = test.model;
model.name += 'updated'; model.name += 'updated';
model.save(function(err) { model.save(function(err) {
@ -286,9 +286,9 @@ describe('Change', function() {
}); });
it('should not change checkpoint when rev is the same', function(done) { it('should not change checkpoint when rev is the same', function(done) {
var test = this; const test = this;
var originalCheckpoint = change.checkpoint; const originalCheckpoint = change.checkpoint;
var originalRev = change.rev; const originalRev = change.rev;
TestModel.checkpoint(function(err, inst) { TestModel.checkpoint(function(err, inst) {
if (err) return done(err); if (err) return done(err);
@ -306,7 +306,7 @@ describe('Change', function() {
}); });
describe('change.rectify - promise variant', function() { describe('change.rectify - promise variant', function() {
var change; let change;
beforeEach(function(done) { beforeEach(function(done) {
Change.findOrCreateChange(this.modelName, this.modelId) Change.findOrCreateChange(this.modelName, this.modelId)
.then(function(ch) { .then(function(ch) {
@ -318,7 +318,7 @@ describe('Change', function() {
}); });
it('should create a new change with the correct revision', function(done) { it('should create a new change with the correct revision', function(done) {
var test = this; const test = this;
change.rectify() change.rectify()
.then(function(ch) { .then(function(ch) {
assert.equal(ch.rev, test.revisionForModel); assert.equal(ch.rev, test.revisionForModel);
@ -330,8 +330,8 @@ describe('Change', function() {
describe('change.currentRevision(callback)', function() { describe('change.currentRevision(callback)', function() {
it('should get the correct revision', function(done) { it('should get the correct revision', function(done) {
var test = this; const test = this;
var change = new Change({ const change = new Change({
modelName: this.modelName, modelName: this.modelName,
modelId: this.modelId, modelId: this.modelId,
}); });
@ -346,8 +346,8 @@ describe('Change', function() {
describe('change.currentRevision - promise variant', function() { describe('change.currentRevision - promise variant', function() {
it('should get the correct revision', function(done) { it('should get the correct revision', function(done) {
var test = this; const test = this;
var change = new Change({ const change = new Change({
modelName: this.modelName, modelName: this.modelName,
modelId: this.modelId, modelId: this.modelId,
}); });
@ -365,8 +365,8 @@ describe('Change', function() {
describe('Change.hash(str)', function() { describe('Change.hash(str)', function() {
// todo(ritch) test other hashing algorithms // todo(ritch) test other hashing algorithms
it('should hash the given string', function() { it('should hash the given string', function() {
var str = 'foo'; const str = 'foo';
var hash = Change.hash(str); const hash = Change.hash(str);
assert(hash !== str); assert(hash !== str);
assert(typeof hash === 'string'); assert(typeof hash === 'string');
}); });
@ -374,54 +374,54 @@ describe('Change', function() {
describe('Change.revisionForInst(inst)', function() { describe('Change.revisionForInst(inst)', function() {
it('should return the same revision for the same data', function() { it('should return the same revision for the same data', function() {
var a = { const a = {
b: { b: {
b: ['c', 'd'], b: ['c', 'd'],
c: ['d', 'e'], c: ['d', 'e'],
}, },
}; };
var b = { const b = {
b: { b: {
c: ['d', 'e'], c: ['d', 'e'],
b: ['c', 'd'], b: ['c', 'd'],
}, },
}; };
var aRev = Change.revisionForInst(a); const aRev = Change.revisionForInst(a);
var bRev = Change.revisionForInst(b); const bRev = Change.revisionForInst(b);
assert.equal(aRev, bRev); assert.equal(aRev, bRev);
}); });
}); });
describe('change.type()', function() { describe('change.type()', function() {
it('CREATE', function() { it('CREATE', function() {
var change = new Change({ const change = new Change({
rev: this.revisionForModel, rev: this.revisionForModel,
}); });
assert.equal(Change.CREATE, change.type()); assert.equal(Change.CREATE, change.type());
}); });
it('UPDATE', function() { it('UPDATE', function() {
var change = new Change({ const change = new Change({
rev: this.revisionForModel, rev: this.revisionForModel,
prev: this.revisionForModel, prev: this.revisionForModel,
}); });
assert.equal(Change.UPDATE, change.type()); assert.equal(Change.UPDATE, change.type());
}); });
it('DELETE', function() { it('DELETE', function() {
var change = new Change({ const change = new Change({
prev: this.revisionForModel, prev: this.revisionForModel,
}); });
assert.equal(Change.DELETE, change.type()); assert.equal(Change.DELETE, change.type());
}); });
it('UNKNOWN', function() { it('UNKNOWN', function() {
var change = new Change(); const change = new Change();
assert.equal(Change.UNKNOWN, change.type()); assert.equal(Change.UNKNOWN, change.type());
}); });
}); });
describe('change.getModelCtor()', function() { describe('change.getModelCtor()', function() {
it('should get the correct model class', function() { it('should get the correct model class', function() {
var change = new Change({ const change = new Change({
modelName: this.modelName, modelName: this.modelName,
}); });
@ -431,11 +431,11 @@ describe('Change', function() {
describe('change.equals(otherChange)', function() { describe('change.equals(otherChange)', function() {
it('should return true when the change is equal', function() { it('should return true when the change is equal', function() {
var change = new Change({ const change = new Change({
rev: this.revisionForModel, rev: this.revisionForModel,
}); });
var otherChange = new Change({ const otherChange = new Change({
rev: this.revisionForModel, rev: this.revisionForModel,
}); });
@ -443,13 +443,13 @@ describe('Change', function() {
}); });
it('should return true when both changes are deletes', function() { it('should return true when both changes are deletes', function() {
var REV = 'foo'; const REV = 'foo';
var change = new Change({ const change = new Change({
rev: null, rev: null,
prev: REV, prev: REV,
}); });
var otherChange = new Change({ const otherChange = new Change({
rev: undefined, rev: undefined,
prev: REV, prev: REV,
}); });
@ -463,11 +463,11 @@ describe('Change', function() {
describe('change.isBasedOn(otherChange)', function() { describe('change.isBasedOn(otherChange)', function() {
it('should return true when the change is based on the other', function() { it('should return true when the change is based on the other', function() {
var change = new Change({ const change = new Change({
prev: this.revisionForModel, prev: this.revisionForModel,
}); });
var otherChange = new Change({ const otherChange = new Change({
rev: this.revisionForModel, rev: this.revisionForModel,
}); });
@ -485,7 +485,7 @@ describe('Change', function() {
}); });
it('should return delta and conflict lists', function(done) { it('should return delta and conflict lists', function(done) {
var remoteChanges = [ const remoteChanges = [
// an update => should result in a delta // an update => should result in a delta
{rev: 'foo2', prev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1}, {rev: 'foo2', prev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1},
// no change => should not result in a delta / conflict // no change => should not result in a delta / conflict
@ -505,7 +505,7 @@ describe('Change', function() {
}); });
it('should return delta and conflict lists - promise variant', function(done) { it('should return delta and conflict lists - promise variant', function(done) {
var remoteChanges = [ const remoteChanges = [
// an update => should result in a delta // an update => should result in a delta
{rev: 'foo2', prev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1}, {rev: 'foo2', prev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1},
// no change => should not result in a delta / conflict // no change => should not result in a delta / conflict
@ -525,7 +525,7 @@ describe('Change', function() {
}); });
it('should set "prev" to local revision in non-conflicting delta', function(done) { it('should set "prev" to local revision in non-conflicting delta', function(done) {
var updateRecord = { const updateRecord = {
rev: 'foo-new', rev: 'foo-new',
prev: 'foo', prev: 'foo',
modelName: this.modelName, modelName: this.modelName,
@ -537,7 +537,7 @@ describe('Change', function() {
expect(diff.conflicts, 'conflicts').to.have.length(0); expect(diff.conflicts, 'conflicts').to.have.length(0);
expect(diff.deltas, 'deltas').to.have.length(1); expect(diff.deltas, 'deltas').to.have.length(1);
var actual = diff.deltas[0].toObject(); const actual = diff.deltas[0].toObject();
delete actual.id; delete actual.id;
expect(actual).to.eql({ expect(actual).to.eql({
checkpoint: 2, checkpoint: 2,
@ -552,7 +552,7 @@ describe('Change', function() {
}); });
it('should set "prev" to local revision in remote-only delta', function(done) { it('should set "prev" to local revision in remote-only delta', function(done) {
var updateRecord = { const updateRecord = {
rev: 'foo-new', rev: 'foo-new',
prev: 'foo-prev', prev: 'foo-prev',
modelName: this.modelName, modelName: this.modelName,
@ -566,7 +566,7 @@ describe('Change', function() {
expect(diff.conflicts, 'conflicts').to.have.length(0); expect(diff.conflicts, 'conflicts').to.have.length(0);
expect(diff.deltas, 'deltas').to.have.length(1); expect(diff.deltas, 'deltas').to.have.length(1);
var actual = diff.deltas[0].toObject(); const actual = diff.deltas[0].toObject();
delete actual.id; delete actual.id;
expect(actual).to.eql({ expect(actual).to.eql({
checkpoint: 2, checkpoint: 2,
@ -581,7 +581,7 @@ describe('Change', function() {
}); });
it('should set "prev" to null for a new instance', function(done) { it('should set "prev" to null for a new instance', function(done) {
var updateRecord = { const updateRecord = {
rev: 'new-rev', rev: 'new-rev',
prev: 'new-prev', prev: 'new-prev',
modelName: this.modelName, modelName: this.modelName,
@ -594,7 +594,7 @@ describe('Change', function() {
expect(diff.conflicts).to.have.length(0); expect(diff.conflicts).to.have.length(0);
expect(diff.deltas).to.have.length(1); expect(diff.deltas).to.have.length(1);
var actual = diff.deltas[0].toObject(); const actual = diff.deltas[0].toObject();
delete actual.id; delete actual.id;
expect(actual).to.eql({ expect(actual).to.eql({
checkpoint: 2, checkpoint: 2,
@ -614,7 +614,7 @@ describe('Change with with custom properties', function() {
let Change, TestModel; let Change, TestModel;
beforeEach(function() { beforeEach(function() {
let memory = loopback.createDataSource({ const memory = loopback.createDataSource({
connector: loopback.Memory, connector: loopback.Memory,
}); });
@ -630,7 +630,7 @@ describe('Change with with custom properties', function() {
this.modelName = TestModel.modelName; this.modelName = TestModel.modelName;
TestModel.prototype.fillCustomChangeProperties = function(change, cb) { TestModel.prototype.fillCustomChangeProperties = function(change, cb) {
var inst = this; const inst = this;
if (inst && inst.tenantId) { if (inst && inst.tenantId) {
change.tenantId = inst.tenantId; change.tenantId = inst.tenantId;

View File

@ -4,16 +4,16 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var async = require('async'); const async = require('async');
var loopback = require('../'); const loopback = require('../');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var Checkpoint = loopback.Checkpoint.extend('TestCheckpoint'); const Checkpoint = loopback.Checkpoint.extend('TestCheckpoint');
describe('Checkpoint', function() { describe('Checkpoint', function() {
describe('bumpLastSeq() and current()', function() { describe('bumpLastSeq() and current()', function() {
beforeEach(function() { beforeEach(function() {
var memory = loopback.createDataSource({ const memory = loopback.createDataSource({
connector: loopback.Memory, connector: loopback.Memory,
}); });
Checkpoint.attachTo(memory); Checkpoint.attachTo(memory);

View File

@ -5,12 +5,12 @@
'use strict'; 'use strict';
var expect = require('chai').expect; const expect = require('chai').expect;
var loopback = require('..'); const loopback = require('..');
var supertest = require('supertest'); const supertest = require('supertest');
describe('OptionsFromRemotingContext', function() { describe('OptionsFromRemotingContext', function() {
var app, request, accessToken, userId, Product, actualOptions; let app, request, accessToken, userId, Product, actualOptions;
beforeEach(setupAppAndRequest); beforeEach(setupAppAndRequest);
beforeEach(resetActualOptions); beforeEach(resetActualOptions);
@ -133,7 +133,7 @@ describe('OptionsFromRemotingContext', function() {
// despite the fact that under the hood a method on "modelTo" is called. // despite the fact that under the hood a method on "modelTo" is called.
context('hasManyThrough', function() { context('hasManyThrough', function() {
var Category, ThroughModel; let Category, ThroughModel;
beforeEach(givenCategoryHasManyProductsThroughAnotherModel); beforeEach(givenCategoryHasManyProductsThroughAnotherModel);
beforeEach(givenCategoryAndProduct); beforeEach(givenCategoryAndProduct);
@ -242,7 +242,7 @@ describe('OptionsFromRemotingContext', function() {
}); });
context('hasOne', function() { context('hasOne', function() {
var Category; let Category;
beforeEach(givenCategoryHasOneProduct); beforeEach(givenCategoryHasOneProduct);
beforeEach(givenCategoryId1); beforeEach(givenCategoryId1);
@ -313,7 +313,7 @@ describe('OptionsFromRemotingContext', function() {
}); });
context('belongsTo', function() { context('belongsTo', function() {
var Category; let Category;
beforeEach(givenCategoryBelongsToProduct); beforeEach(givenCategoryBelongsToProduct);
@ -382,7 +382,7 @@ describe('OptionsFromRemotingContext', function() {
} }
function observeOptionsBeforeSave() { function observeOptionsBeforeSave() {
var Model = arguments[0] || Product; const Model = arguments[0] || Product;
Model.observe('before save', function(ctx, next) { Model.observe('before save', function(ctx, next) {
actualOptions = ctx.options; actualOptions = ctx.options;
next(); next();
@ -390,7 +390,7 @@ describe('OptionsFromRemotingContext', function() {
} }
function observeOptionsBeforeDelete() { function observeOptionsBeforeDelete() {
var Model = arguments[0] || Product; const Model = arguments[0] || Product;
Model.observe('before delete', function(ctx, next) { Model.observe('before delete', function(ctx, next) {
actualOptions = ctx.options; actualOptions = ctx.options;
next(); next();
@ -398,7 +398,7 @@ describe('OptionsFromRemotingContext', function() {
} }
function observeOptionsOnAccess() { function observeOptionsOnAccess() {
var Model = arguments[0] || Product; const Model = arguments[0] || Product;
Model.observe('access', function(ctx, next) { Model.observe('access', function(ctx, next) {
actualOptions = ctx.options; actualOptions = ctx.options;
next(); next();

View File

@ -4,11 +4,11 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var loopback = require('../'); const loopback = require('../');
describe('DataSource', function() { describe('DataSource', function() {
var memory; let memory;
beforeEach(function() { beforeEach(function() {
memory = loopback.createDataSource({ memory = loopback.createDataSource({
@ -20,7 +20,7 @@ describe('DataSource', function() {
describe('dataSource.createModel(name, properties, settings)', function() { describe('dataSource.createModel(name, properties, settings)', function() {
it('Define a model and attach it to a `DataSource`', function() { it('Define a model and attach it to a `DataSource`', function() {
var Color = memory.createModel('color', {name: String}); const Color = memory.createModel('color', {name: String});
assert.isFunc(Color, 'find'); assert.isFunc(Color, 'find');
assert.isFunc(Color, 'findById'); assert.isFunc(Color, 'findById');
assert.isFunc(Color, 'findOne'); assert.isFunc(Color, 'findOne');
@ -45,31 +45,31 @@ describe('DataSource', function() {
}); });
it('should honor settings.base', function() { it('should honor settings.base', function() {
var Base = memory.createModel('base'); const Base = memory.createModel('base');
var Color = memory.createModel('color', {name: String}, {base: Base}); const Color = memory.createModel('color', {name: String}, {base: Base});
assert(Color.prototype instanceof Base); assert(Color.prototype instanceof Base);
assert.equal(Color.base, Base); assert.equal(Color.base, Base);
}); });
it('should use loopback.PersistedModel as the base for DBs', function() { it('should use loopback.PersistedModel as the base for DBs', function() {
var Color = memory.createModel('color', {name: String}); const Color = memory.createModel('color', {name: String});
assert(Color.prototype instanceof loopback.PersistedModel); assert(Color.prototype instanceof loopback.PersistedModel);
assert.equal(Color.base, loopback.PersistedModel); assert.equal(Color.base, loopback.PersistedModel);
}); });
it('should use loopback.Model as the base for non DBs', function() { it('should use loopback.Model as the base for non DBs', function() {
// Mock up a non-DB connector // Mock up a non-DB connector
var Connector = function() { const Connector = function() {
}; };
Connector.prototype.getTypes = function() { Connector.prototype.getTypes = function() {
return ['rest']; return ['rest'];
}; };
var ds = loopback.createDataSource({ const ds = loopback.createDataSource({
connector: new Connector(), connector: new Connector(),
}); });
var Color = ds.createModel('color', {name: String}); const Color = ds.createModel('color', {name: String});
assert(Color.prototype instanceof Color.registry.getModel('Model')); assert(Color.prototype instanceof Color.registry.getModel('Model'));
assert.equal(Color.base.modelName, 'PersistedModel'); assert.equal(Color.base.modelName, 'PersistedModel');
}); });
@ -77,7 +77,7 @@ describe('DataSource', function() {
describe.skip('PersistedModel Methods', function() { describe.skip('PersistedModel Methods', function() {
it('List the enabled and disabled methods', function() { it('List the enabled and disabled methods', function() {
var TestModel = loopback.PersistedModel.extend('TestPersistedModel'); const TestModel = loopback.PersistedModel.extend('TestPersistedModel');
TestModel.attachTo(loopback.memory()); TestModel.attachTo(loopback.memory());
// assert the defaults // assert the defaults
@ -109,9 +109,9 @@ describe('DataSource', function() {
existsAndShared('reload', false); existsAndShared('reload', false);
function existsAndShared(Model, name, isRemoteEnabled, isProto) { function existsAndShared(Model, name, isRemoteEnabled, isProto) {
var scope = isProto ? Model.prototype : Model; const scope = isProto ? Model.prototype : Model;
var fn = scope[name]; const fn = scope[name];
var actuallyEnabled = Model.getRemoteMethod(name); const actuallyEnabled = Model.getRemoteMethod(name);
assert(fn, name + ' should be defined!'); assert(fn, name + ' should be defined!');
assert(actuallyEnabled === isRemoteEnabled, assert(actuallyEnabled === isRemoteEnabled,
name + ' ' + (isRemoteEnabled ? 'should' : 'should not') + name + ' ' + (isRemoteEnabled ? 'should' : 'should not') +
@ -121,7 +121,7 @@ describe('DataSource', function() {
}); });
}); });
var assertValidDataSource = function(dataSource) { function assertValidDataSource(dataSource) {
// has methods // has methods
assert.isFunc(dataSource, 'createModel'); assert.isFunc(dataSource, 'createModel');
assert.isFunc(dataSource, 'discoverModelDefinitions'); assert.isFunc(dataSource, 'discoverModelDefinitions');
@ -130,7 +130,7 @@ var assertValidDataSource = function(dataSource) {
assert.isFunc(dataSource, 'disableRemote'); assert.isFunc(dataSource, 'disableRemote');
assert.isFunc(dataSource, 'defineOperation'); assert.isFunc(dataSource, 'defineOperation');
assert.isFunc(dataSource, 'operations'); assert.isFunc(dataSource, 'operations');
}; }
assert.isFunc = function(obj, name) { assert.isFunc = function(obj, name) {
assert(obj, 'cannot assert function ' + name + ' on object that doesnt exist'); assert(obj, 'cannot assert function ' + name + ' on object that doesnt exist');

View File

@ -4,16 +4,16 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var path = require('path'); const path = require('path');
var loopback = require('../../'); const loopback = require('../../');
var models = require('../fixtures/e2e/models'); const models = require('../fixtures/e2e/models');
var TestModel = models.TestModel; const TestModel = models.TestModel;
var assert = require('assert'); const assert = require('assert');
describe('RemoteConnector', function() { describe('RemoteConnector', function() {
before(function() { before(function() {
// setup the remote connector // setup the remote connector
var ds = loopback.createDataSource({ const ds = loopback.createDataSource({
url: 'http://127.0.0.1:3000/api', url: 'http://127.0.0.1:3000/api',
connector: loopback.Remote, connector: loopback.Remote,
}); });
@ -33,7 +33,7 @@ describe('RemoteConnector', function() {
}); });
it('should be able to call save', function(done) { it('should be able to call save', function(done) {
var m = new TestModel({ const m = new TestModel({
foo: 'bar', foo: 'bar',
}); });
m.save(function(err, data) { m.save(function(err, data) {

View File

@ -4,29 +4,29 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var path = require('path'); const path = require('path');
var loopback = require('../../'); const loopback = require('../../');
var models = require('../fixtures/e2e/models'); const models = require('../fixtures/e2e/models');
var TestModel = models.TestModel; const TestModel = models.TestModel;
var LocalTestModel = TestModel.extend('LocalTestModel', {}, { const LocalTestModel = TestModel.extend('LocalTestModel', {}, {
trackChanges: true, trackChanges: true,
}); });
var assert = require('assert'); const assert = require('assert');
describe('Replication', function() { describe('Replication', function() {
before(function() { before(function() {
// setup the remote connector // setup the remote connector
var ds = loopback.createDataSource({ const ds = loopback.createDataSource({
url: 'http://127.0.0.1:3000/api', url: 'http://127.0.0.1:3000/api',
connector: loopback.Remote, connector: loopback.Remote,
}); });
TestModel.attachTo(ds); TestModel.attachTo(ds);
var memory = loopback.memory(); const memory = loopback.memory();
LocalTestModel.attachTo(memory); LocalTestModel.attachTo(memory);
}); });
it('should replicate local data to the remote', function(done) { it('should replicate local data to the remote', function(done) {
var RANDOM = Math.random(); const RANDOM = Math.random();
LocalTestModel.create({ LocalTestModel.create({
n: RANDOM, n: RANDOM,

View File

@ -4,35 +4,35 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../'); const loopback = require('../');
var MyEmail; let MyEmail;
var assert = require('assert'); const assert = require('assert');
var MailConnector = require('../lib/connectors/mail'); const MailConnector = require('../lib/connectors/mail');
describe('Email connector', function() { describe('Email connector', function() {
it('should set up SMTP', function() { it('should set up SMTP', function() {
var connector = new MailConnector({transports: [ const connector = new MailConnector({transports: [
{type: 'smtp', service: 'gmail'}, {type: 'smtp', service: 'gmail'},
]}); ]});
assert(connector.transportForName('smtp')); assert(connector.transportForName('smtp'));
}); });
it('should set up DIRECT', function() { it('should set up DIRECT', function() {
var connector = new MailConnector({transports: [ const connector = new MailConnector({transports: [
{type: 'direct', name: 'localhost'}, {type: 'direct', name: 'localhost'},
]}); ]});
assert(connector.transportForName('direct')); assert(connector.transportForName('direct'));
}); });
it('should set up STUB', function() { it('should set up STUB', function() {
var connector = new MailConnector({transports: [ const connector = new MailConnector({transports: [
{type: 'stub', service: 'gmail'}, {type: 'stub', service: 'gmail'},
]}); ]});
assert(connector.transportForName('stub')); assert(connector.transportForName('stub'));
}); });
it('should set up a single transport for SMTP', function() { it('should set up a single transport for SMTP', function() {
var connector = new MailConnector({transport: const connector = new MailConnector({transport:
{type: 'smtp', service: 'gmail'}, {type: 'smtp', service: 'gmail'},
}); });
@ -40,7 +40,7 @@ describe('Email connector', function() {
}); });
it('should set up a aliased transport for SMTP', function() { it('should set up a aliased transport for SMTP', function() {
var connector = new MailConnector({transport: const connector = new MailConnector({transport:
{type: 'smtp', service: 'ses-us-east-1', alias: 'ses-smtp'}, {type: 'smtp', service: 'ses-us-east-1', alias: 'ses-smtp'},
}); });
@ -51,7 +51,7 @@ describe('Email connector', function() {
describe('Email and SMTP', function() { describe('Email and SMTP', function() {
beforeEach(function() { beforeEach(function() {
MyEmail = loopback.Email.extend('my-email'); MyEmail = loopback.Email.extend('my-email');
var ds = loopback.createDataSource('email', { const ds = loopback.createDataSource('email', {
connector: loopback.Mail, connector: loopback.Mail,
transports: [{type: 'STUB'}], transports: [{type: 'STUB'}],
}); });
@ -65,7 +65,7 @@ describe('Email and SMTP', function() {
describe('MyEmail', function() { describe('MyEmail', function() {
it('MyEmail.send(options, callback)', function(done) { it('MyEmail.send(options, callback)', function(done) {
var options = { const options = {
to: 'to@to.com', to: 'to@to.com',
from: 'from@from.com', from: 'from@from.com',
subject: 'subject', subject: 'subject',
@ -84,7 +84,7 @@ describe('Email and SMTP', function() {
}); });
it('myEmail.send(callback)', function(done) { it('myEmail.send(callback)', function(done) {
var message = new MyEmail({ const message = new MyEmail({
to: 'to@to.com', to: 'to@to.com',
from: 'from@from.com', from: 'from@from.com',
subject: 'subject', subject: 'subject',

View File

@ -4,11 +4,11 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../'); const loopback = require('../');
var app; let app;
var assert = require('assert'); const assert = require('assert');
var request = require('supertest'); const request = require('supertest');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
describe('loopback.errorHandler(options)', function() { describe('loopback.errorHandler(options)', function() {
it('should throw a descriptive error', function() { it('should throw a descriptive error', function() {

View File

@ -4,17 +4,17 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../../..'); const loopback = require('../../../..');
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var app = module.exports = loopback({ const app = module.exports = loopback({
localRegistry: true, localRegistry: true,
loadBuiltinModels: true, loadBuiltinModels: true,
}); });
var errorHandler = require('strong-error-handler'); const errorHandler = require('strong-error-handler');
boot(app, __dirname); boot(app, __dirname);
var apiPath = '/api'; const apiPath = '/api';
app.use(loopback.token({model: app.models.accessToken})); app.use(loopback.token({model: app.models.accessToken}));
app.use(apiPath, loopback.rest()); app.use(apiPath, loopback.rest());

View File

@ -4,8 +4,8 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../../../index'); const loopback = require('../../../../index');
var PersistedModel = loopback.PersistedModel; const PersistedModel = loopback.PersistedModel;
exports.TestModel = PersistedModel.extend('TestModel', {}, { exports.TestModel = PersistedModel.extend('TestModel', {}, {
trackChanges: true, trackChanges: true,

View File

@ -4,12 +4,12 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../../../index'); const loopback = require('../../../../index');
var app = module.exports = loopback({localRegistry: true}); const app = module.exports = loopback({localRegistry: true});
var models = require('./models'); const models = require('./models');
var TestModel = models.TestModel; const TestModel = models.TestModel;
var apiPath = '/api'; const apiPath = '/api';
app.use(apiPath, loopback.rest()); app.use(apiPath, loopback.rest());
TestModel.attachTo(loopback.memory()); TestModel.attachTo(loopback.memory());

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var loopback = require('../../../../../index'); const loopback = require('../../../../../index');
var app = module.exports = loopback(); const app = module.exports = loopback();
boot(app, __dirname); boot(app, __dirname);
app.use(loopback.rest()); app.use(loopback.rest());

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var loopback = require('../../../../../index'); const loopback = require('../../../../../index');
var app = module.exports = loopback(); const app = module.exports = loopback();
boot(app, __dirname); boot(app, __dirname);
app.use(loopback.rest()); app.use(loopback.rest());

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var loopback = require('../../../../../index'); const loopback = require('../../../../../index');
var app = module.exports = loopback(); const app = module.exports = loopback();
boot(app, __dirname); boot(app, __dirname);
app.use(loopback.rest()); app.use(loopback.rest());

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var loopback = require('../../../../../index'); const loopback = require('../../../../../index');
var app = module.exports = loopback(); const app = module.exports = loopback();
boot(app, __dirname); boot(app, __dirname);
app.use(loopback.rest()); app.use(loopback.rest());

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var loopback = require('../../../../../index'); const loopback = require('../../../../../index');
var app = module.exports = loopback(); const app = module.exports = loopback();
boot(app, __dirname); boot(app, __dirname);
app.use(loopback.rest()); app.use(loopback.rest());

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var loopback = require('../../../../../index'); const loopback = require('../../../../../index');
var app = module.exports = loopback(); const app = module.exports = loopback();
boot(app, __dirname); boot(app, __dirname);
app.use(loopback.rest()); app.use(loopback.rest());

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var loopback = require('../../../../../index'); const loopback = require('../../../../../index');
var app = module.exports = loopback(); const app = module.exports = loopback();
boot(app, __dirname); boot(app, __dirname);
app.use(loopback.rest()); app.use(loopback.rest());

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var loopback = require('../../../../../index'); const loopback = require('../../../../../index');
var app = module.exports = loopback(); const app = module.exports = loopback();
boot(app, __dirname); boot(app, __dirname);
app.use(loopback.rest()); app.use(loopback.rest());

View File

@ -4,9 +4,9 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var loopback = require('../../../../../index'); const loopback = require('../../../../../index');
var app = module.exports = loopback(); const app = module.exports = loopback();
boot(app, __dirname); boot(app, __dirname);
app.use(loopback.rest()); app.use(loopback.rest());

View File

@ -4,13 +4,13 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../../../index'); const loopback = require('../../../../index');
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var app = module.exports = loopback({localRegistry: true}); const app = module.exports = loopback({localRegistry: true});
var errorHandler = require('strong-error-handler'); const errorHandler = require('strong-error-handler');
boot(app, __dirname); boot(app, __dirname);
var apiPath = '/api'; const apiPath = '/api';
app.use(apiPath, loopback.rest()); app.use(apiPath, loopback.rest());
app.use(loopback.urlNotFound()); app.use(loopback.urlNotFound());
app.use(errorHandler()); app.use(errorHandler());

View File

@ -4,18 +4,18 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../../../index'); const loopback = require('../../../../index');
var boot = require('loopback-boot'); const boot = require('loopback-boot');
var app = module.exports = loopback({ const app = module.exports = loopback({
localRegistry: true, localRegistry: true,
loadBuiltinModels: true, loadBuiltinModels: true,
}); });
var errorHandler = require('strong-error-handler'); const errorHandler = require('strong-error-handler');
app.enableAuth(); app.enableAuth();
boot(app, __dirname); boot(app, __dirname);
app.use(loopback.token({model: app.models.AccessToken})); app.use(loopback.token({model: app.models.AccessToken}));
var apiPath = '/api'; const apiPath = '/api';
app.use(apiPath, loopback.rest()); app.use(apiPath, loopback.rest());
app.use(loopback.urlNotFound()); app.use(loopback.urlNotFound());
app.use(errorHandler()); app.use(errorHandler());

View File

@ -4,16 +4,16 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var loopback = require('../'); const loopback = require('../');
var GeoPoint = loopback.GeoPoint; const GeoPoint = loopback.GeoPoint;
describe('GeoPoint', function() { describe('GeoPoint', function() {
describe('geoPoint.distanceTo(geoPoint, options)', function() { describe('geoPoint.distanceTo(geoPoint, options)', function() {
it('Get the distance to another `GeoPoint`', function() { it('Get the distance to another `GeoPoint`', function() {
var here = new GeoPoint({lat: 10, lng: 10}); const here = new GeoPoint({lat: 10, lng: 10});
var there = new GeoPoint({lat: 5, lng: 5}); const there = new GeoPoint({lat: 5, lng: 5});
var distance = here.distanceTo(there, {type: 'meters'}); const distance = here.distanceTo(there, {type: 'meters'});
assert.equal(Math.floor(distance), 782777); assert.equal(Math.floor(distance), 782777);
}); });
@ -21,9 +21,9 @@ describe('GeoPoint', function() {
describe('GeoPoint.distanceBetween(a, b, options)', function() { describe('GeoPoint.distanceBetween(a, b, options)', function() {
it('Get the distance between two points', function() { it('Get the distance between two points', function() {
var here = new GeoPoint({lat: 10, lng: 10}); const here = new GeoPoint({lat: 10, lng: 10});
var there = new GeoPoint({lat: 5, lng: 5}); const there = new GeoPoint({lat: 5, lng: 5});
var distance = GeoPoint.distanceBetween(here, there, {type: 'feet'}); const distance = GeoPoint.distanceBetween(here, there, {type: 'feet'});
assert.equal(Math.floor(distance), 2568169); assert.equal(Math.floor(distance), 2568169);
}); });
@ -31,32 +31,32 @@ describe('GeoPoint', function() {
describe('GeoPoint()', function() { describe('GeoPoint()', function() {
it('Create from string', function() { it('Create from string', function() {
var point = new GeoPoint('1.234,5.678'); const point = new GeoPoint('1.234,5.678');
assert.equal(point.lat, 1.234); assert.equal(point.lat, 1.234);
assert.equal(point.lng, 5.678); assert.equal(point.lng, 5.678);
var point2 = new GeoPoint('1.222, 5.333'); const point2 = new GeoPoint('1.222, 5.333');
assert.equal(point2.lat, 1.222); assert.equal(point2.lat, 1.222);
assert.equal(point2.lng, 5.333); assert.equal(point2.lng, 5.333);
var point3 = new GeoPoint('1.333, 5.111'); const point3 = new GeoPoint('1.333, 5.111');
assert.equal(point3.lat, 1.333); assert.equal(point3.lat, 1.333);
assert.equal(point3.lng, 5.111); assert.equal(point3.lng, 5.111);
}); });
it('Serialize as string', function() { it('Serialize as string', function() {
var str = '1.234,5.678'; const str = '1.234,5.678';
var point = new GeoPoint(str); const point = new GeoPoint(str);
assert.equal(point.toString(), str); assert.equal(point.toString(), str);
}); });
it('Create from array', function() { it('Create from array', function() {
var point = new GeoPoint([5.555, 6.777]); const point = new GeoPoint([5.555, 6.777]);
assert.equal(point.lat, 5.555); assert.equal(point.lat, 5.555);
assert.equal(point.lng, 6.777); assert.equal(point.lng, 6.777);
}); });
it('Create as Model property', function() { it('Create as Model property', function() {
var Model = loopback.createModel('geo-model', { const Model = loopback.createModel('geo-model', {
geo: {type: 'GeoPoint'}, geo: {type: 'GeoPoint'},
}); });
var m = new Model({ const m = new Model({
geo: '1.222,3.444', geo: '1.222,3.444',
}); });

View File

@ -5,7 +5,7 @@
'use strict'; 'use strict';
var chai = require('chai'); const chai = require('chai');
chai.use(require('dirty-chai')); chai.use(require('dirty-chai'));
chai.use(require('sinon-chai')); chai.use(require('sinon-chai'));

View File

@ -4,21 +4,21 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var _describe = {}; const _describe = {};
var _it = {}; const _it = {};
var _beforeEach = {}; const _beforeEach = {};
var helpers = { const helpers = {
describe: _describe, describe: _describe,
it: _it, it: _it,
beforeEach: _beforeEach, beforeEach: _beforeEach,
}; };
module.exports = helpers; module.exports = helpers;
var assert = require('assert'); const assert = require('assert');
var request = require('supertest'); const request = require('supertest');
var chai = require('chai'); const chai = require('chai');
var expect = chai.expect; const expect = chai.expect;
var sinon = require('sinon'); const sinon = require('sinon');
chai.use(require('sinon-chai')); chai.use(require('sinon-chai'));
_beforeEach.withApp = function(app) { _beforeEach.withApp = function(app) {
@ -29,7 +29,7 @@ _beforeEach.withApp = function(app) {
beforeEach(function(done) { beforeEach(function(done) {
this.app = app; this.app = app;
var _request = this.request = request(app); const _request = this.request = request(app);
this.post = _request.post; this.post = _request.post;
this.get = _request.get; this.get = _request.get;
this.put = _request.put; this.put = _request.put;
@ -45,14 +45,14 @@ _beforeEach.withApp = function(app) {
}; };
_beforeEach.withArgs = function() { _beforeEach.withArgs = function() {
var args = Array.prototype.slice.call(arguments, 0); const args = Array.prototype.slice.call(arguments, 0);
beforeEach(function() { beforeEach(function() {
this.args = args; this.args = args;
}); });
}; };
_beforeEach.givenModel = function(modelName, attrs, optionalHandler) { _beforeEach.givenModel = function(modelName, attrs, optionalHandler) {
var modelKey = modelName; let modelKey = modelName;
if (typeof attrs === 'function') { if (typeof attrs === 'function') {
optionalHandler = attrs; optionalHandler = attrs;
@ -66,9 +66,9 @@ _beforeEach.givenModel = function(modelName, attrs, optionalHandler) {
attrs = attrs || {}; attrs = attrs || {};
beforeEach(function(done) { beforeEach(function(done) {
var test = this; const test = this;
var app = this.app; const app = this.app;
var model = app.models[modelName]; const model = app.models[modelName];
app.set('remoting', {errorHandler: {debug: true, log: false}}); app.set('remoting', {errorHandler: {debug: true, log: false}});
assert(model, 'cannot get model of name ' + modelName + ' from app.models'); assert(model, 'cannot get model of name ' + modelName + ' from app.models');
@ -108,7 +108,7 @@ _beforeEach.givenUser = function(attrs, optionalHandler) {
_beforeEach.givenLoggedInUser = function(credentials, optionalHandler) { _beforeEach.givenLoggedInUser = function(credentials, optionalHandler) {
_beforeEach.givenUser(credentials, function(done) { _beforeEach.givenUser(credentials, function(done) {
var test = this; const test = this;
this.user.constructor.login(credentials, function(err, token) { this.user.constructor.login(credentials, function(err, token) {
if (err) { if (err) {
done(err); done(err);
@ -121,7 +121,7 @@ _beforeEach.givenLoggedInUser = function(credentials, optionalHandler) {
}); });
afterEach(function(done) { afterEach(function(done) {
var test = this; const test = this;
this.loggedInAccessToken.destroy(function(err) { this.loggedInAccessToken.destroy(function(err) {
if (err) return done(err); if (err) return done(err);
@ -146,7 +146,7 @@ _describe.whenCalledRemotely = function(verb, url, data, cb) {
data = null; data = null;
} }
var urlStr = url; let urlStr = url;
if (typeof url === 'function') { if (typeof url === 'function') {
urlStr = '/<dynamic>'; urlStr = '/<dynamic>';
} }
@ -159,11 +159,11 @@ _describe.whenCalledRemotely = function(verb, url, data, cb) {
this.remotely = true; this.remotely = true;
this.verb = verb.toUpperCase(); this.verb = verb.toUpperCase();
this.url = this.url || url; this.url = this.url || url;
var methodForVerb = verb.toLowerCase(); let methodForVerb = verb.toLowerCase();
if (methodForVerb === 'delete') methodForVerb = 'del'; if (methodForVerb === 'delete') methodForVerb = 'del';
if (this.request === undefined) { if (this.request === undefined) {
var msg = 'App is not specified. ' + const msg = 'App is not specified. ' +
'Please use lt.beforeEach.withApp to specify the app.'; 'Please use lt.beforeEach.withApp to specify the app.';
throw new Error(msg); throw new Error(msg);
} }
@ -175,13 +175,13 @@ _describe.whenCalledRemotely = function(verb, url, data, cb) {
this.http.set('authorization', this.loggedInAccessToken.id); this.http.set('authorization', this.loggedInAccessToken.id);
} }
if (data) { if (data) {
var payload = data; let payload = data;
if (typeof data === 'function') if (typeof data === 'function')
payload = data.call(this); payload = data.call(this);
this.http.send(payload); this.http.send(payload);
} }
this.req = this.http.req; this.req = this.http.req;
var test = this; const test = this;
this.http.end(function(err) { this.http.end(function(err) {
test.req = test.http.req; test.req = test.http.req;
test.res = test.http.response; test.res = test.http.response;
@ -236,7 +236,7 @@ _it.shouldBeAllowed = function() {
_it.shouldBeDenied = function() { _it.shouldBeDenied = function() {
it('should not be allowed', function() { it('should not be allowed', function() {
assert(this.res); assert(this.res);
var expectedStatus = this.aclErrorStatus || const expectedStatus = this.aclErrorStatus ||
this.app && this.app.get('aclErrorStatus') || this.app && this.app.get('aclErrorStatus') ||
401; 401;
expect(this.res.statusCode).to.equal(expectedStatus); expect(this.res.statusCode).to.equal(expectedStatus);

View File

@ -5,7 +5,7 @@
'use strict'; 'use strict';
var env = process.env; const env = process.env;
// delete any user-provided language settings // delete any user-provided language settings
delete env.LC_ALL; delete env.LC_ALL;

View File

@ -4,21 +4,21 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var loopback = require('../'); const loopback = require('../');
var request = require('supertest'); const request = require('supertest');
describe('hidden properties', function() { describe('hidden properties', function() {
beforeEach(function(done) { beforeEach(function(done) {
var app = this.app = loopback(); const app = this.app = loopback();
var Product = this.Product = loopback.PersistedModel.extend( const Product = this.Product = loopback.PersistedModel.extend(
'product', 'product',
{}, {},
{hidden: ['secret']} {hidden: ['secret']}
); );
Product.attachTo(loopback.memory()); Product.attachTo(loopback.memory());
var Category = this.Category = loopback.PersistedModel.extend('category'); const Category = this.Category = loopback.PersistedModel.extend('category');
Category.attachTo(loopback.memory()); Category.attachTo(loopback.memory());
Category.hasMany(Product); Category.hasMany(Product);
@ -37,7 +37,7 @@ describe('hidden properties', function() {
}); });
afterEach(function(done) { afterEach(function(done) {
var Product = this.Product; const Product = this.Product;
this.Category.destroyAll(function() { this.Category.destroyAll(function() {
Product.destroyAll(done); Product.destroyAll(done);
}); });
@ -51,7 +51,7 @@ describe('hidden properties', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var product = res.body[0]; const product = res.body[0];
assert.equal(product.secret, undefined); assert.equal(product.secret, undefined);
done(); done();
@ -59,7 +59,7 @@ describe('hidden properties', function() {
}); });
it('should hide a property of nested models', function(done) { it('should hide a property of nested models', function(done) {
var app = this.app; const app = this.app;
request(app) request(app)
.get('/categories?filter[include]=products') .get('/categories?filter[include]=products')
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -67,8 +67,8 @@ describe('hidden properties', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var category = res.body[0]; const category = res.body[0];
var product = category.products[0]; const product = category.products[0];
assert.equal(product.secret, undefined); assert.equal(product.secret, undefined);
done(); done();

View File

@ -4,15 +4,15 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var loopback = require('../'); const loopback = require('../');
var net = require('net'); const net = require('net');
describe('loopback application', function() { describe('loopback application', function() {
it('pauses request stream during authentication', function(done) { it('pauses request stream during authentication', function(done) {
// This test reproduces the issue reported in // This test reproduces the issue reported in
// https://github.com/strongloop/loopback-storage-service/issues/7 // https://github.com/strongloop/loopback-storage-service/issues/7
var app = loopback(); const app = loopback();
setupAppWithStreamingMethod(); setupAppWithStreamingMethod();
app.listen(0, function() { app.listen(0, function() {
@ -37,7 +37,7 @@ describe('loopback application', function() {
app.dataSource('db', { app.dataSource('db', {
connector: loopback.Memory, connector: loopback.Memory,
}); });
var db = app.datasources.db; const db = app.datasources.db;
loopback.User.attachTo(db); loopback.User.attachTo(db);
loopback.AccessToken.attachTo(db); loopback.AccessToken.attachTo(db);
@ -45,10 +45,10 @@ describe('loopback application', function() {
loopback.ACL.attachTo(db); loopback.ACL.attachTo(db);
loopback.User.hasMany(loopback.AccessToken, {as: 'accessTokens'}); loopback.User.hasMany(loopback.AccessToken, {as: 'accessTokens'});
var Streamer = app.registry.createModel('Streamer'); const Streamer = app.registry.createModel('Streamer');
app.model(Streamer, {dataSource: 'db'}); app.model(Streamer, {dataSource: 'db'});
Streamer.read = function(req, res, cb) { Streamer.read = function(req, res, cb) {
var body = new Buffer(0); let body = new Buffer(0);
req.on('data', function(chunk) { req.on('data', function(chunk) {
body += chunk; body += chunk;
}); });
@ -75,8 +75,8 @@ describe('loopback application', function() {
} }
function sendHttpRequestInOnePacket(port, reqString, cb) { function sendHttpRequestInOnePacket(port, reqString, cb) {
var socket = net.createConnection(port); const socket = net.createConnection(port);
var response = new Buffer(0); let response = new Buffer(0);
socket.on('data', function(chunk) { socket.on('data', function(chunk) {
response += chunk; response += chunk;

View File

@ -4,15 +4,15 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var http = require('http'); const http = require('http');
var loopback = require('..'); const loopback = require('..');
var supertest = require('supertest'); const supertest = require('supertest');
var AN_OBJECT_VALUE = {name: 'an-object'}; const AN_OBJECT_VALUE = {name: 'an-object'};
describe('KeyValueModel', function() { describe('KeyValueModel', function() {
var request, app, CacheItem; let request, app, CacheItem;
beforeEach(setupAppAndCacheItem); beforeEach(setupAppAndCacheItem);
describe('REST API', function() { describe('REST API', function() {
@ -156,7 +156,7 @@ describe('KeyValueModel', function() {
app.model(CacheItem, {dataSource: 'kv'}); app.model(CacheItem, {dataSource: 'kv'});
} }
var _server, _requestHandler; // eslint-disable-line one-var let _server, _requestHandler; // eslint-disable-line one-var
function setupSharedHttpServer(done) { function setupSharedHttpServer(done) {
_server = http.createServer(function(req, res) { _server = http.createServer(function(req, res) {
app(req, res); app(req, res);

View File

@ -4,17 +4,17 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var it = require('./util/it'); const it = require('./util/it');
var describe = require('./util/describe'); const describe = require('./util/describe');
var Domain = require('domain'); const Domain = require('domain');
var EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter;
var loopback = require('../'); const loopback = require('../');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var assert = require('assert'); const assert = require('assert');
describe('loopback', function() { describe('loopback', function() {
var nameCounter = 0; let nameCounter = 0;
var uniqueModelName; let uniqueModelName;
beforeEach(function() { beforeEach(function() {
uniqueModelName = 'TestModel-' + (++nameCounter); uniqueModelName = 'TestModel-' + (++nameCounter);
@ -27,7 +27,7 @@ describe('loopback', function() {
}); });
it.onServer('includes `faviconFile`', function() { it.onServer('includes `faviconFile`', function() {
var file = loopback.faviconFile; const file = loopback.faviconFile;
expect(file, 'faviconFile').to.not.equal(undefined); expect(file, 'faviconFile').to.not.equal(undefined);
expect(require('fs').existsSync(loopback.faviconFile), 'file exists') expect(require('fs').existsSync(loopback.faviconFile), 'file exists')
.to.equal(true); .to.equal(true);
@ -38,7 +38,7 @@ describe('loopback', function() {
}); });
it.onServer('exports all expected properties', function() { it.onServer('exports all expected properties', function() {
var EXPECTED = [ const EXPECTED = [
'ACL', 'ACL',
'AccessToken', 'AccessToken',
'Application', 'Application',
@ -98,7 +98,7 @@ describe('loopback', function() {
'version', 'version',
]; ];
var actual = Object.getOwnPropertyNames(loopback); const actual = Object.getOwnPropertyNames(loopback);
actual.sort(); actual.sort();
expect(actual).to.include.members(EXPECTED); expect(actual).to.include.members(EXPECTED);
}); });
@ -106,17 +106,17 @@ describe('loopback', function() {
describe('loopback(options)', function() { describe('loopback(options)', function() {
it('supports localRegistry:true', function() { it('supports localRegistry:true', function() {
var app = loopback({localRegistry: true}); const app = loopback({localRegistry: true});
expect(app.registry).to.not.equal(loopback.registry); expect(app.registry).to.not.equal(loopback.registry);
}); });
it('does not load builtin models into the local registry', function() { it('does not load builtin models into the local registry', function() {
var app = loopback({localRegistry: true}); const app = loopback({localRegistry: true});
expect(app.registry.findModel('User')).to.equal(undefined); expect(app.registry.findModel('User')).to.equal(undefined);
}); });
it('supports loadBuiltinModels:true', function() { it('supports loadBuiltinModels:true', function() {
var app = loopback({localRegistry: true, loadBuiltinModels: true}); const app = loopback({localRegistry: true, loadBuiltinModels: true});
expect(app.registry.findModel('User')) expect(app.registry.findModel('User'))
.to.have.property('modelName', 'User'); .to.have.property('modelName', 'User');
}); });
@ -124,7 +124,7 @@ describe('loopback', function() {
describe('loopback.createDataSource(options)', function() { describe('loopback.createDataSource(options)', function() {
it('Create a data source with a connector.', function() { it('Create a data source with a connector.', function() {
var dataSource = loopback.createDataSource({ const dataSource = loopback.createDataSource({
connector: loopback.Memory, connector: loopback.Memory,
}); });
assert(dataSource.connector); assert(dataSource.connector);
@ -133,24 +133,24 @@ describe('loopback', function() {
describe('data source created by loopback', function() { describe('data source created by loopback', function() {
it('should create model extending Model by default', function() { it('should create model extending Model by default', function() {
var dataSource = loopback.createDataSource({ const dataSource = loopback.createDataSource({
connector: loopback.Memory, connector: loopback.Memory,
}); });
var m1 = dataSource.createModel('m1', {}); const m1 = dataSource.createModel('m1', {});
assert(m1.prototype instanceof loopback.Model); assert(m1.prototype instanceof loopback.Model);
}); });
}); });
describe('model created by loopback', function() { describe('model created by loopback', function() {
it('should extend from Model by default', function() { it('should extend from Model by default', function() {
var m1 = loopback.createModel('m1', {}); const m1 = loopback.createModel('m1', {});
assert(m1.prototype instanceof loopback.Model); assert(m1.prototype instanceof loopback.Model);
}); });
}); });
describe('loopback.remoteMethod(Model, fn, [options]);', function() { describe('loopback.remoteMethod(Model, fn, [options]);', function() {
it('Setup a remote method.', function() { it('Setup a remote method.', function() {
var Product = loopback.createModel('product', {price: Number}); const Product = loopback.createModel('product', {price: Number});
Product.stats = function(fn) { Product.stats = function(fn) {
// ... // ...
@ -175,12 +175,12 @@ describe('loopback', function() {
describe('loopback.createModel(name, properties, options)', function() { describe('loopback.createModel(name, properties, options)', function() {
describe('options.base', function() { describe('options.base', function() {
it('should extend from options.base', function() { it('should extend from options.base', function() {
var MyModel = loopback.createModel('MyModel', {}, { const MyModel = loopback.createModel('MyModel', {}, {
foo: { foo: {
bar: 'bat', bar: 'bat',
}, },
}); });
var MyCustomModel = loopback.createModel('MyCustomModel', {}, { const MyCustomModel = loopback.createModel('MyCustomModel', {}, {
base: 'MyModel', base: 'MyModel',
foo: { foo: {
bat: 'baz', bat: 'baz',
@ -194,12 +194,12 @@ describe('loopback', function() {
describe('loopback.getModel and getModelByType', function() { describe('loopback.getModel and getModelByType', function() {
it('should be able to get model by name', function() { it('should be able to get model by name', function() {
var MyModel = loopback.createModel('MyModel', {}, { const MyModel = loopback.createModel('MyModel', {}, {
foo: { foo: {
bar: 'bat', bar: 'bat',
}, },
}); });
var MyCustomModel = loopback.createModel('MyCustomModel', {}, { const MyCustomModel = loopback.createModel('MyCustomModel', {}, {
base: 'MyModel', base: 'MyModel',
foo: { foo: {
bat: 'baz', bat: 'baz',
@ -211,12 +211,12 @@ describe('loopback', function() {
assert(loopback.getModel(MyModel) === MyModel); assert(loopback.getModel(MyModel) === MyModel);
}); });
it('should be able to get model by type', function() { it('should be able to get model by type', function() {
var MyModel = loopback.createModel('MyModel', {}, { const MyModel = loopback.createModel('MyModel', {}, {
foo: { foo: {
bar: 'bat', bar: 'bat',
}, },
}); });
var MyCustomModel = loopback.createModel('MyCustomModel', {}, { const MyCustomModel = loopback.createModel('MyCustomModel', {}, {
base: 'MyModel', base: 'MyModel',
foo: { foo: {
bat: 'baz', bat: 'baz',
@ -233,7 +233,7 @@ describe('loopback', function() {
}); });
it('configures remote methods', function() { it('configures remote methods', function() {
var TestModel = loopback.createModel(uniqueModelName, {}, { const TestModel = loopback.createModel(uniqueModelName, {}, {
methods: { methods: {
staticMethod: { staticMethod: {
isStatic: true, isStatic: true,
@ -246,7 +246,7 @@ describe('loopback', function() {
}, },
}); });
var methodNames = TestModel.sharedClass.methods().map(function(m) { const methodNames = TestModel.sharedClass.methods().map(function(m) {
return m.stringName.replace(/^[^.]+\./, ''); // drop the class name return m.stringName.replace(/^[^.]+\./, ''); // drop the class name
}); });
@ -259,7 +259,7 @@ describe('loopback', function() {
describe('loopback.createModel(config)', function() { describe('loopback.createModel(config)', function() {
it('creates the model', function() { it('creates the model', function() {
var model = loopback.createModel({ const model = loopback.createModel({
name: uniqueModelName, name: uniqueModelName,
}); });
@ -267,7 +267,7 @@ describe('loopback', function() {
}); });
it('interprets extra first-level keys as options', function() { it('interprets extra first-level keys as options', function() {
var model = loopback.createModel({ const model = loopback.createModel({
name: uniqueModelName, name: uniqueModelName,
base: 'User', base: 'User',
}); });
@ -276,7 +276,7 @@ describe('loopback', function() {
}); });
it('prefers config.options.key over config.key', function() { it('prefers config.options.key over config.key', function() {
var model = loopback.createModel({ const model = loopback.createModel({
name: uniqueModelName, name: uniqueModelName,
base: 'User', base: 'User',
options: { options: {
@ -290,7 +290,7 @@ describe('loopback', function() {
describe('loopback.configureModel(ModelCtor, config)', function() { describe('loopback.configureModel(ModelCtor, config)', function() {
it('adds new relations', function() { it('adds new relations', function() {
var model = loopback.Model.extend(uniqueModelName); const model = loopback.Model.extend(uniqueModelName);
loopback.configureModel(model, { loopback.configureModel(model, {
dataSource: null, dataSource: null,
@ -306,7 +306,7 @@ describe('loopback', function() {
}); });
it('updates existing relations', function() { it('updates existing relations', function() {
var model = loopback.Model.extend(uniqueModelName, {}, { const model = loopback.Model.extend(uniqueModelName, {}, {
relations: { relations: {
owner: { owner: {
type: 'belongsTo', type: 'belongsTo',
@ -331,8 +331,8 @@ describe('loopback', function() {
}); });
it('updates relations before attaching to a dataSource', function() { it('updates relations before attaching to a dataSource', function() {
var db = loopback.createDataSource({connector: loopback.Memory}); const db = loopback.createDataSource({connector: loopback.Memory});
var model = loopback.Model.extend(uniqueModelName); const model = loopback.Model.extend(uniqueModelName);
// This test used to work because User model was already attached // This test used to work because User model was already attached
// by other tests via `loopback.autoAttach()` // by other tests via `loopback.autoAttach()`
@ -352,13 +352,13 @@ describe('loopback', function() {
}, },
}); });
var owner = model.prototype.owner; const owner = model.prototype.owner;
expect(owner, 'model.prototype.owner').to.be.a('function'); expect(owner, 'model.prototype.owner').to.be.a('function');
expect(owner._targetClass).to.equal('User'); expect(owner._targetClass).to.equal('User');
}); });
it('adds new acls', function() { it('adds new acls', function() {
var model = loopback.Model.extend(uniqueModelName, {}, { const model = loopback.Model.extend(uniqueModelName, {}, {
acls: [ acls: [
{ {
property: 'find', property: 'find',
@ -402,7 +402,7 @@ describe('loopback', function() {
}); });
it('updates existing acls', function() { it('updates existing acls', function() {
var model = loopback.Model.extend(uniqueModelName, {}, { const model = loopback.Model.extend(uniqueModelName, {}, {
acls: [ acls: [
{ {
property: 'find', property: 'find',
@ -439,12 +439,12 @@ describe('loopback', function() {
}); });
it('updates existing settings', function() { it('updates existing settings', function() {
var model = loopback.Model.extend(uniqueModelName, {}, { const model = loopback.Model.extend(uniqueModelName, {}, {
ttl: 10, ttl: 10,
emailVerificationRequired: false, emailVerificationRequired: false,
}); });
var baseName = model.settings.base.name; const baseName = model.settings.base.name;
loopback.configureModel(model, { loopback.configureModel(model, {
dataSource: null, dataSource: null,
@ -465,7 +465,7 @@ describe('loopback', function() {
}); });
it('configures remote methods', function() { it('configures remote methods', function() {
var TestModel = loopback.createModel(uniqueModelName); const TestModel = loopback.createModel(uniqueModelName);
loopback.configureModel(TestModel, { loopback.configureModel(TestModel, {
dataSource: null, dataSource: null,
methods: { methods: {
@ -480,7 +480,7 @@ describe('loopback', function() {
}, },
}); });
var methodNames = TestModel.sharedClass.methods().map(function(m) { const methodNames = TestModel.sharedClass.methods().map(function(m) {
return m.stringName.replace(/^[^.]+\./, ''); // drop the class name return m.stringName.replace(/^[^.]+\./, ''); // drop the class name
}); });
@ -493,14 +493,14 @@ describe('loopback', function() {
describe('loopback object', function() { describe('loopback object', function() {
it('inherits properties from express', function() { it('inherits properties from express', function() {
var express = require('express'); const express = require('express');
for (var i in express) { for (const i in express) {
expect(loopback).to.have.property(i, express[i]); expect(loopback).to.have.property(i, express[i]);
} }
}); });
it('exports all built-in models', function() { it('exports all built-in models', function() {
var expectedModelNames = [ const expectedModelNames = [
'Email', 'Email',
'User', 'User',
'Application', 'Application',
@ -530,7 +530,7 @@ describe('loopback', function() {
} }
it('treats method names that don\'t start with "prototype." as "isStatic:true"', function() { it('treats method names that don\'t start with "prototype." as "isStatic:true"', function() {
var TestModel = loopback.createModel(uniqueModelName); const TestModel = loopback.createModel(uniqueModelName);
loopback.configureModel(TestModel, { loopback.configureModel(TestModel, {
dataSource: null, dataSource: null,
methods: { methods: {
@ -540,13 +540,13 @@ describe('loopback', function() {
}, },
}); });
var methodNames = getAllMethodNamesWithoutClassName(TestModel); const methodNames = getAllMethodNamesWithoutClassName(TestModel);
expect(methodNames).to.include('staticMethod'); expect(methodNames).to.include('staticMethod');
}); });
it('treats method names starting with "prototype." as "isStatic:false"', function() { it('treats method names starting with "prototype." as "isStatic:false"', function() {
var TestModel = loopback.createModel(uniqueModelName); const TestModel = loopback.createModel(uniqueModelName);
loopback.configureModel(TestModel, { loopback.configureModel(TestModel, {
dataSource: null, dataSource: null,
methods: { methods: {
@ -556,13 +556,15 @@ describe('loopback', function() {
}, },
}); });
var methodNames = getAllMethodNamesWithoutClassName(TestModel); const methodNames = getAllMethodNamesWithoutClassName(TestModel);
expect(methodNames).to.include('prototype.instanceMethod'); expect(methodNames).to.include('prototype.instanceMethod');
}); });
it('throws an error when "isStatic:true" and method name starts with "prototype."', function() { // Skip this test in browsers because strong-globalize is not removing
var TestModel = loopback.createModel(uniqueModelName); // `{{` and `}}` control characters from the string.
it.onServer('throws when "isStatic:true" and method name starts with "prototype."', function() {
const TestModel = loopback.createModel(uniqueModelName);
expect(function() { expect(function() {
loopback.configureModel(TestModel, { loopback.configureModel(TestModel, {
dataSource: null, dataSource: null,
@ -573,12 +575,12 @@ describe('loopback', function() {
}, },
}, },
}); });
}).to.throw(Error, new Error('Remoting metadata for' + TestModel.modelName + }).to.throw(Error, 'Remoting metadata for ' + TestModel.modelName +
' "isStatic" does not match new method name-based style.')); '.prototype.instanceMethod "isStatic" does not match new method name-based style.');
}); });
it('use "isStatic:true" if method name does not start with "prototype."', function() { it('use "isStatic:true" if method name does not start with "prototype."', function() {
var TestModel = loopback.createModel(uniqueModelName); const TestModel = loopback.createModel(uniqueModelName);
loopback.configureModel(TestModel, { loopback.configureModel(TestModel, {
dataSource: null, dataSource: null,
methods: { methods: {
@ -589,13 +591,13 @@ describe('loopback', function() {
}, },
}); });
var methodNames = getAllMethodNamesWithoutClassName(TestModel); const methodNames = getAllMethodNamesWithoutClassName(TestModel);
expect(methodNames).to.include('staticMethod'); expect(methodNames).to.include('staticMethod');
}); });
it('use "isStatic:false" if method name starts with "prototype."', function() { it('use "isStatic:false" if method name starts with "prototype."', function() {
var TestModel = loopback.createModel(uniqueModelName); const TestModel = loopback.createModel(uniqueModelName);
loopback.configureModel(TestModel, { loopback.configureModel(TestModel, {
dataSource: null, dataSource: null,
methods: { methods: {
@ -606,19 +608,19 @@ describe('loopback', function() {
}, },
}); });
var methodNames = getAllMethodNamesWithoutClassName(TestModel); const methodNames = getAllMethodNamesWithoutClassName(TestModel);
expect(methodNames).to.include('prototype.instanceMethod'); expect(methodNames).to.include('prototype.instanceMethod');
}); });
}); });
describe('Remote method inheritance', function() { describe('Remote method inheritance', function() {
var app; let app;
beforeEach(setupLoopback); beforeEach(setupLoopback);
it('inherits remote methods defined via createModel', function() { it('inherits remote methods defined via createModel', function() {
var Base = app.registry.createModel('Base', {}, { const Base = app.registry.createModel('Base', {}, {
methods: { methods: {
greet: { greet: {
http: {path: '/greet'}, http: {path: '/greet'},
@ -626,7 +628,7 @@ describe('loopback', function() {
}, },
}); });
var MyCustomModel = app.registry.createModel('MyCustomModel', {}, { const MyCustomModel = app.registry.createModel('MyCustomModel', {}, {
base: 'Base', base: 'Base',
methods: { methods: {
hello: { hello: {
@ -634,14 +636,14 @@ describe('loopback', function() {
}, },
}, },
}); });
var methodNames = getAllMethodNamesWithoutClassName(MyCustomModel); const methodNames = getAllMethodNamesWithoutClassName(MyCustomModel);
expect(methodNames).to.include('greet'); expect(methodNames).to.include('greet');
expect(methodNames).to.include('hello'); expect(methodNames).to.include('hello');
}); });
it('same remote method with different metadata should override parent', function() { it('same remote method with different metadata should override parent', function() {
var Base = app.registry.createModel('Base', {}, { const Base = app.registry.createModel('Base', {}, {
methods: { methods: {
greet: { greet: {
http: {path: '/greet'}, http: {path: '/greet'},
@ -649,7 +651,7 @@ describe('loopback', function() {
}, },
}); });
var MyCustomModel = app.registry.createModel('MyCustomModel', {}, { const MyCustomModel = app.registry.createModel('MyCustomModel', {}, {
base: 'Base', base: 'Base',
methods: { methods: {
greet: { greet: {
@ -657,9 +659,9 @@ describe('loopback', function() {
}, },
}, },
}); });
var methodNames = getAllMethodNamesWithoutClassName(MyCustomModel); const methodNames = getAllMethodNamesWithoutClassName(MyCustomModel);
var baseMethod = Base.sharedClass.findMethodByName('greet'); const baseMethod = Base.sharedClass.findMethodByName('greet');
var customMethod = MyCustomModel.sharedClass.findMethodByName('greet'); const customMethod = MyCustomModel.sharedClass.findMethodByName('greet');
// Base Method // Base Method
expect(baseMethod.http).to.eql({path: '/greet'}); expect(baseMethod.http).to.eql({path: '/greet'});
@ -674,7 +676,7 @@ describe('loopback', function() {
}); });
it('does not inherit remote methods defined via configureModel', function() { it('does not inherit remote methods defined via configureModel', function() {
var Base = app.registry.createModel('Base'); const Base = app.registry.createModel('Base');
app.registry.configureModel(Base, { app.registry.configureModel(Base, {
dataSource: null, dataSource: null,
methods: { methods: {
@ -684,7 +686,7 @@ describe('loopback', function() {
}, },
}); });
var MyCustomModel = app.registry.createModel('MyCustomModel', {}, { const MyCustomModel = app.registry.createModel('MyCustomModel', {}, {
base: 'Base', base: 'Base',
methods: { methods: {
hello: { hello: {
@ -692,7 +694,7 @@ describe('loopback', function() {
}, },
}, },
}); });
var methodNames = getAllMethodNamesWithoutClassName(MyCustomModel); const methodNames = getAllMethodNamesWithoutClassName(MyCustomModel);
expect(methodNames).to.not.include('greet'); expect(methodNames).to.not.include('greet');
expect(methodNames).to.include('hello'); expect(methodNames).to.include('hello');
@ -700,8 +702,8 @@ describe('loopback', function() {
it('does not inherit remote methods defined via configureModel after child model ' + it('does not inherit remote methods defined via configureModel after child model ' +
'was created', function() { 'was created', function() {
var Base = app.registry.createModel('Base'); const Base = app.registry.createModel('Base');
var MyCustomModel = app.registry.createModel('MyCustomModel', {}, { const MyCustomModel = app.registry.createModel('MyCustomModel', {}, {
base: 'Base', base: 'Base',
}); });
@ -722,8 +724,8 @@ describe('loopback', function() {
}, },
}, },
}); });
var baseMethodNames = getAllMethodNamesWithoutClassName(Base); const baseMethodNames = getAllMethodNamesWithoutClassName(Base);
var methodNames = getAllMethodNamesWithoutClassName(MyCustomModel); const methodNames = getAllMethodNamesWithoutClassName(MyCustomModel);
expect(baseMethodNames).to.include('greet'); expect(baseMethodNames).to.include('greet');
expect(methodNames).to.not.include('greet'); expect(methodNames).to.not.include('greet');
@ -742,12 +744,12 @@ describe('loopback', function() {
}); });
describe('Hiding shared methods', function() { describe('Hiding shared methods', function() {
var app; let app;
beforeEach(setupLoopback); beforeEach(setupLoopback);
it('hides remote methods using fixed method names', function() { it('hides remote methods using fixed method names', function() {
var TestModel = app.registry.createModel(uniqueModelName); const TestModel = app.registry.createModel(uniqueModelName);
app.model(TestModel, { app.model(TestModel, {
dataSource: null, dataSource: null,
methods: { methods: {
@ -765,7 +767,7 @@ describe('loopback', function() {
}, },
}); });
var publicMethods = getSharedMethods(TestModel); const publicMethods = getSharedMethods(TestModel);
expect(publicMethods).not.to.include.members([ expect(publicMethods).not.to.include.members([
'staticMethod', 'staticMethod',
@ -773,7 +775,7 @@ describe('loopback', function() {
}); });
it('hides remote methods using a glob pattern', function() { it('hides remote methods using a glob pattern', function() {
var TestModel = app.registry.createModel(uniqueModelName); const TestModel = app.registry.createModel(uniqueModelName);
app.model(TestModel, { app.model(TestModel, {
dataSource: null, dataSource: null,
methods: { methods: {
@ -795,7 +797,7 @@ describe('loopback', function() {
}, },
}); });
var publicMethods = getSharedMethods(TestModel); const publicMethods = getSharedMethods(TestModel);
expect(publicMethods).to.include.members([ expect(publicMethods).to.include.members([
'staticMethod', 'staticMethod',
@ -806,7 +808,7 @@ describe('loopback', function() {
}); });
it('hides all remote methods using *', function() { it('hides all remote methods using *', function() {
var TestModel = app.registry.createModel(uniqueModelName); const TestModel = app.registry.createModel(uniqueModelName);
app.model(TestModel, { app.model(TestModel, {
dataSource: null, dataSource: null,
methods: { methods: {
@ -828,7 +830,7 @@ describe('loopback', function() {
}, },
}); });
var publicMethods = getSharedMethods(TestModel); const publicMethods = getSharedMethods(TestModel);
expect(publicMethods).to.be.empty(); expect(publicMethods).to.be.empty();
}); });

View File

@ -4,14 +4,14 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var loopback = require('../'); const loopback = require('../');
describe('Memory Connector', function() { describe('Memory Connector', function() {
it('Create a model using the memory connector', function(done) { it('Create a model using the memory connector', function(done) {
// use the built in memory function // use the built in memory function
// to create a memory data source // to create a memory data source
var memory = loopback.memory(); let memory = loopback.memory();
// or create it using the standard // or create it using the standard
// data source creation api // data source creation api
@ -21,12 +21,12 @@ describe('Memory Connector', function() {
// create a model using the // create a model using the
// memory data source // memory data source
var properties = { const properties = {
name: String, name: String,
price: Number, price: Number,
}; };
var Product = memory.createModel('product', properties); const Product = memory.createModel('product', properties);
Product.create([ Product.create([
{name: 'apple', price: 0.79}, {name: 'apple', price: 0.79},

View File

@ -4,12 +4,12 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require(('../')); const loopback = require(('../'));
var assert = require('assert'); const assert = require('assert');
var Application = loopback.Application; const Application = loopback.Application;
describe('Application', function() { describe('Application', function() {
var registeredApp = null; let registeredApp = null;
before(function attachToMemory() { before(function attachToMemory() {
Application.attachTo(loopback.memory()); Application.attachTo(loopback.memory());
@ -18,7 +18,7 @@ describe('Application', function() {
it('honors `application.register` - callback variant', function(done) { it('honors `application.register` - callback variant', function(done) {
Application.register('rfeng', 'MyTestApp', Application.register('rfeng', 'MyTestApp',
{description: 'My test application'}, function(err, result) { {description: 'My test application'}, function(err, result) {
var app = result; const app = result;
assert.equal(app.owner, 'rfeng'); assert.equal(app.owner, 'rfeng');
assert.equal(app.name, 'MyTestApp'); assert.equal(app.name, 'MyTestApp');
assert.equal(app.description, 'My test application'); assert.equal(app.description, 'My test application');
@ -31,7 +31,7 @@ describe('Application', function() {
Application.register('rfeng', 'MyTestApp', Application.register('rfeng', 'MyTestApp',
{description: 'My test application'}) {description: 'My test application'})
.then(function(result) { .then(function(result) {
var app = result; const app = result;
assert.equal(app.owner, 'rfeng'); assert.equal(app.owner, 'rfeng');
assert.equal(app.name, 'MyTestApp'); assert.equal(app.name, 'MyTestApp');
assert.equal(app.description, 'My test application'); assert.equal(app.description, 'My test application');
@ -47,7 +47,7 @@ describe('Application', function() {
Application.create({owner: 'rfeng', Application.create({owner: 'rfeng',
name: 'MyApp1', name: 'MyApp1',
description: 'My first mobile application'}, function(err, result) { description: 'My first mobile application'}, function(err, result) {
var app = result; const app = result;
assert.equal(app.owner, 'rfeng'); assert.equal(app.owner, 'rfeng');
assert.equal(app.name, 'MyApp1'); assert.equal(app.name, 'MyApp1');
assert.equal(app.description, 'My first mobile application'); assert.equal(app.description, 'My first mobile application');
@ -90,7 +90,7 @@ describe('Application', function() {
}, },
}}, }},
function(err, result) { function(err, result) {
var app = result; const app = result;
assert.deepEqual(app.pushSettings.toObject(), { assert.deepEqual(app.pushSettings.toObject(), {
apns: { apns: {
production: false, production: false,
@ -119,7 +119,7 @@ describe('Application', function() {
beforeEach(function(done) { beforeEach(function(done) {
Application.register('rfeng', 'MyApp2', Application.register('rfeng', 'MyApp2',
{description: 'My second mobile application'}, function(err, result) { {description: 'My second mobile application'}, function(err, result) {
var app = result; const app = result;
assert.equal(app.owner, 'rfeng'); assert.equal(app.owner, 'rfeng');
assert.equal(app.name, 'MyApp2'); assert.equal(app.name, 'MyApp2');
assert.equal(app.description, 'My second mobile application'); assert.equal(app.description, 'My second mobile application');
@ -138,7 +138,7 @@ describe('Application', function() {
it('Reset keys', function(done) { it('Reset keys', function(done) {
Application.resetKeys(registeredApp.id, function(err, result) { Application.resetKeys(registeredApp.id, function(err, result) {
var app = result; const app = result;
assert.equal(app.owner, 'rfeng'); assert.equal(app.owner, 'rfeng');
assert.equal(app.name, 'MyApp2'); assert.equal(app.name, 'MyApp2');
assert.equal(app.description, 'My second mobile application'); assert.equal(app.description, 'My second mobile application');
@ -165,7 +165,7 @@ describe('Application', function() {
it('Reset keys - promise variant', function(done) { it('Reset keys - promise variant', function(done) {
Application.resetKeys(registeredApp.id) Application.resetKeys(registeredApp.id)
.then(function(result) { .then(function(result) {
var app = result; const app = result;
assert.equal(app.owner, 'rfeng'); assert.equal(app.owner, 'rfeng');
assert.equal(app.name, 'MyApp2'); assert.equal(app.name, 'MyApp2');
assert.equal(app.description, 'My second mobile application'); assert.equal(app.description, 'My second mobile application');
@ -194,7 +194,7 @@ describe('Application', function() {
it('Reset keys without create a new instance', function(done) { it('Reset keys without create a new instance', function(done) {
Application.resetKeys(registeredApp.id, function(err, result) { Application.resetKeys(registeredApp.id, function(err, result) {
var app = result; const app = result;
assert(app.id); assert(app.id);
assert(app.id === registeredApp.id); assert(app.id === registeredApp.id);
registeredApp = app; registeredApp = app;
@ -206,7 +206,7 @@ describe('Application', function() {
it('Reset keys without create a new instance - promise variant', function(done) { it('Reset keys without create a new instance - promise variant', function(done) {
Application.resetKeys(registeredApp.id) Application.resetKeys(registeredApp.id)
.then(function(result) { .then(function(result) {
var app = result; const app = result;
assert(app.id); assert(app.id);
assert(app.id === registeredApp.id); assert(app.id === registeredApp.id);
registeredApp = app; registeredApp = app;
@ -307,12 +307,12 @@ describe('Application', function() {
describe('Application subclass', function() { describe('Application subclass', function() {
it('should use subclass model name', function(done) { it('should use subclass model name', function(done) {
var MyApp = Application.extend('MyApp'); const MyApp = Application.extend('MyApp');
var ds = loopback.createDataSource({connector: loopback.Memory}); const ds = loopback.createDataSource({connector: loopback.Memory});
MyApp.attachTo(ds); MyApp.attachTo(ds);
MyApp.register('rfeng', 'MyApp123', MyApp.register('rfeng', 'MyApp123',
{description: 'My 123 mobile application'}, function(err, result) { {description: 'My 123 mobile application'}, function(err, result) {
var app = result; const app = result;
assert.equal(app.owner, 'rfeng'); assert.equal(app.owner, 'rfeng');
assert.equal(app.name, 'MyApp123'); assert.equal(app.name, 'MyApp123');
assert.equal(app.description, 'My 123 mobile application'); assert.equal(app.description, 'My 123 mobile application');

View File

@ -4,18 +4,18 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var async = require('async'); const async = require('async');
var describe = require('./util/describe'); const describe = require('./util/describe');
var loopback = require('../'); const loopback = require('../');
var ACL = loopback.ACL; const ACL = loopback.ACL;
var defineModelTestsWithDataSource = require('./util/model-tests'); const defineModelTestsWithDataSource = require('./util/model-tests');
var PersistedModel = loopback.PersistedModel; const PersistedModel = loopback.PersistedModel;
var Promise = require('bluebird'); const Promise = require('bluebird');
var TaskEmitter = require('strong-task-emitter'); const TaskEmitter = require('strong-task-emitter');
var request = require('supertest'); const request = require('supertest');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
describe('Model / PersistedModel', function() { describe('Model / PersistedModel', function() {
defineModelTestsWithDataSource({ defineModelTestsWithDataSource({
@ -26,7 +26,7 @@ describe('Model / PersistedModel', function() {
describe('Model.validatesUniquenessOf(property, options)', function() { describe('Model.validatesUniquenessOf(property, options)', function() {
it('Ensure the value for `property` is unique', function(done) { it('Ensure the value for `property` is unique', function(done) {
var User = PersistedModel.extend('ValidatedUser', { const User = PersistedModel.extend('ValidatedUser', {
'first': String, 'first': String,
'last': String, 'last': String,
'age': Number, 'age': Number,
@ -36,7 +36,7 @@ describe('Model / PersistedModel', function() {
'email': String, 'email': String,
}); });
var dataSource = loopback.createDataSource({ const dataSource = loopback.createDataSource({
connector: loopback.Memory, connector: loopback.Memory,
}); });
@ -44,8 +44,8 @@ describe('Model / PersistedModel', function() {
User.validatesUniquenessOf('email', {message: 'email is not unique'}); User.validatesUniquenessOf('email', {message: 'email is not unique'});
var joe = new User({email: 'joe@joe.com'}); const joe = new User({email: 'joe@joe.com'});
var joe2 = new User({email: 'joe@joe.com'}); const joe2 = new User({email: 'joe@joe.com'});
joe.save(function() { joe.save(function() {
joe2.save(function(err) { joe2.save(function(err) {
@ -60,8 +60,8 @@ describe('Model / PersistedModel', function() {
describe('Model.attachTo(dataSource)', function() { describe('Model.attachTo(dataSource)', function() {
it('Attach a model to a [DataSource](#data-source)', function() { it('Attach a model to a [DataSource](#data-source)', function() {
var MyModel = loopback.createModel('my-model', {name: String}); const MyModel = loopback.createModel('my-model', {name: String});
var dataSource = loopback.createDataSource({ const dataSource = loopback.createDataSource({
connector: loopback.Memory, connector: loopback.Memory,
}); });
@ -76,7 +76,7 @@ describe('Model / PersistedModel', function() {
}); });
describe.onServer('Remote Methods', function() { describe.onServer('Remote Methods', function() {
var User, Post, dataSource, app; let User, Post, dataSource, app;
beforeEach(function() { beforeEach(function() {
app = loopback({localRegistry: true, loadBuiltinModels: true}); app = loopback({localRegistry: true, loadBuiltinModels: true});
@ -132,7 +132,7 @@ describe.onServer('Remote Methods', function() {
describe('Model.create(data, callback)', function() { describe('Model.create(data, callback)', function() {
it('creates model', function(done) { it('creates model', function(done) {
var anObject = {first: 'June'}; const anObject = {first: 'June'};
request(app) request(app)
.post('/users') .post('/users')
// sends an object // sends an object
@ -149,7 +149,7 @@ describe.onServer('Remote Methods', function() {
// batch create must be tested with a remote request because there are // batch create must be tested with a remote request because there are
// coercion being done on strong-remoting side // coercion being done on strong-remoting side
it('creates array of models', function(done) { it('creates array of models', function(done) {
var arrayOfObjects = [ const arrayOfObjects = [
{first: 'John'}, {first: 'Jane'}, {first: 'John'}, {first: 'Jane'},
]; ];
request(app) request(app)
@ -161,8 +161,8 @@ describe.onServer('Remote Methods', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
expect(res.body.length).to.eql(2); expect(res.body.length).to.eql(2);
expect(res.body).to.have.deep.property('[0].first', 'John'); expect(res.body).to.have.nested.property('[0].first', 'John');
expect(res.body).to.have.deep.property('[1].first', 'Jane'); expect(res.body).to.have.nested.property('[1].first', 'Jane');
done(); done();
}); });
}); });
@ -170,7 +170,7 @@ describe.onServer('Remote Methods', function() {
it('creates related models', function(done) { it('creates related models', function(done) {
User.create({first: 'Bob'}, function(err, res) { User.create({first: 'Bob'}, function(err, res) {
expect(res).to.have.property('id'); expect(res).to.have.property('id');
var aPost = {title: 'A story', content: 'Once upon a time'}; const aPost = {title: 'A story', content: 'Once upon a time'};
request(app) request(app)
.post('/users/' + res.id + '/posts') .post('/users/' + res.id + '/posts')
.send(aPost) .send(aPost)
@ -189,7 +189,7 @@ describe.onServer('Remote Methods', function() {
it('creates array of hasMany models', function(done) { it('creates array of hasMany models', function(done) {
User.create({first: 'Bob'}, function(err, res) { User.create({first: 'Bob'}, function(err, res) {
expect(res).to.have.property('id'); expect(res).to.have.property('id');
var twoPosts = [ const twoPosts = [
{title: 'One story', content: 'Content #1'}, {title: 'One story', content: 'Content #1'},
{title: 'Two story', content: 'Content #2'}, {title: 'Two story', content: 'Content #2'},
]; ];
@ -201,21 +201,21 @@ describe.onServer('Remote Methods', function() {
.end(function(err, result) { .end(function(err, result) {
if (err) return done(err); if (err) return done(err);
expect(result.body.length).to.eql(2); expect(result.body.length).to.eql(2);
expect(result.body).to.have.deep.property('[0].title', 'One story'); expect(result.body).to.have.nested.property('[0].title', 'One story');
expect(result.body).to.have.deep.property('[1].title', 'Two story'); expect(result.body).to.have.nested.property('[1].title', 'Two story');
done(); done();
}); });
}); });
}); });
it('rejects array of obj input for hasOne relation', function(done) { it('rejects array of obj input for hasOne relation', function(done) {
var Friend = app.registry.createModel('friend', {name: String}); const Friend = app.registry.createModel('friend', {name: String});
app.model(Friend, {dataSource: 'db'}); app.model(Friend, {dataSource: 'db'});
User.hasOne(Friend); User.hasOne(Friend);
User.create({first: 'Bob'}, function(err, res) { User.create({first: 'Bob'}, function(err, res) {
expect(res).to.have.property('id'); expect(res).to.have.property('id');
var twoFriends = [ const twoFriends = [
{name: 'bob'}, {name: 'bob'},
{name: 'rob'}, {name: 'rob'},
]; ];
@ -226,7 +226,7 @@ describe.onServer('Remote Methods', function() {
.expect(400) .expect(400)
.end(function(err, result) { .end(function(err, result) {
if (err) return done(err); if (err) return done(err);
var resError = result.body.error; const resError = result.body.error;
expect(resError.message).to.match(/value(.*?)not(.*?)object(\.?)/i); expect(resError.message).to.match(/value(.*?)not(.*?)object(\.?)/i);
done(); done();
}); });
@ -258,14 +258,14 @@ describe.onServer('Remote Methods', function() {
describe('Model.upsertWithWhere(where, data, callback)', function() { describe('Model.upsertWithWhere(where, data, callback)', function() {
it('Updates when a Model instance is retreived from data source', function(done) { it('Updates when a Model instance is retreived from data source', function(done) {
var taskEmitter = new TaskEmitter(); const taskEmitter = new TaskEmitter();
taskEmitter taskEmitter
.task(User, 'create', {first: 'jill', second: 'pill'}) .task(User, 'create', {first: 'jill', second: 'pill'})
.task(User, 'create', {first: 'bob', second: 'sob'}) .task(User, 'create', {first: 'bob', second: 'sob'})
.on('done', function() { .on('done', function() {
User.upsertWithWhere({second: 'pill'}, {second: 'jones'}, function(err, user) { User.upsertWithWhere({second: 'pill'}, {second: 'jones'}, function(err, user) {
if (err) return done(err); if (err) return done(err);
var id = user.id; const id = user.id;
User.findById(id, function(err, user) { User.findById(id, function(err, user) {
if (err) return done(err); if (err) return done(err);
assert.equal(user.second, 'jones'); assert.equal(user.second, 'jones');
@ -276,13 +276,13 @@ describe.onServer('Remote Methods', function() {
}); });
it('Creates when no Model instance is retreived from data source', function(done) { it('Creates when no Model instance is retreived from data source', function(done) {
var taskEmitter = new TaskEmitter(); const taskEmitter = new TaskEmitter();
taskEmitter taskEmitter
.task(User, 'create', {first: 'simon', second: 'somers'}) .task(User, 'create', {first: 'simon', second: 'somers'})
.on('done', function() { .on('done', function() {
User.upsertWithWhere({first: 'somers'}, {first: 'Simon'}, function(err, user) { User.upsertWithWhere({first: 'somers'}, {first: 'Simon'}, function(err, user) {
if (err) return done(err); if (err) return done(err);
var id = user.id; const id = user.id;
User.findById(id, function(err, user) { User.findById(id, function(err, user) {
if (err) return done(err); if (err) return done(err);
assert.equal(user.first, 'Simon'); assert.equal(user.first, 'Simon');
@ -315,7 +315,7 @@ describe.onServer('Remote Methods', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert(errorResponse); assert(errorResponse);
assert.equal(errorResponse.code, 'MODEL_NOT_FOUND'); assert.equal(errorResponse.code, 'MODEL_NOT_FOUND');
@ -332,7 +332,7 @@ describe.onServer('Remote Methods', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var userId = res.body.id; const userId = res.body.id;
assert(userId); assert(userId);
request(app) request(app)
.get('/users/' + userId + '?filter[fields]=first') .get('/users/' + userId + '?filter[fields]=first')
@ -358,7 +358,7 @@ describe.onServer('Remote Methods', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var userId = res.body.id; const userId = res.body.id;
assert(userId); assert(userId);
request(app) request(app)
.post('/users/' + userId + '/posts') .post('/users/' + userId + '/posts')
@ -368,7 +368,7 @@ describe.onServer('Remote Methods', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var post = res.body; const post = res.body;
request(app) request(app)
.get('/users/' + userId + '?filter[include]=posts') .get('/users/' + userId + '?filter[include]=posts')
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
@ -389,7 +389,7 @@ describe.onServer('Remote Methods', function() {
describe('Model.beforeRemote(name, fn)', function() { describe('Model.beforeRemote(name, fn)', function() {
it('Run a function before a remote method is called by a client', function(done) { it('Run a function before a remote method is called by a client', function(done) {
var hookCalled = false; let hookCalled = false;
User.beforeRemote('create', function(ctx, user, next) { User.beforeRemote('create', function(ctx, user, next) {
hookCalled = true; hookCalled = true;
@ -413,7 +413,7 @@ describe.onServer('Remote Methods', function() {
}); });
it('Does not stop the hook chain after returning a promise', function(done) { it('Does not stop the hook chain after returning a promise', function(done) {
var hooksCalled = []; const hooksCalled = [];
User.beforeRemote('create', function() { User.beforeRemote('create', function() {
hooksCalled.push('first'); hooksCalled.push('first');
@ -441,8 +441,8 @@ describe.onServer('Remote Methods', function() {
describe('Model.afterRemote(name, fn)', function() { describe('Model.afterRemote(name, fn)', function() {
it('Run a function after a remote method is called by a client', function(done) { it('Run a function after a remote method is called by a client', function(done) {
var beforeCalled = false; let beforeCalled = false;
var afterCalled = false; let afterCalled = false;
User.beforeRemote('create', function(ctx, user, next) { User.beforeRemote('create', function(ctx, user, next) {
assert(!afterCalled); assert(!afterCalled);
@ -476,7 +476,7 @@ describe.onServer('Remote Methods', function() {
describe('Model.afterRemoteError(name, fn)', function() { describe('Model.afterRemoteError(name, fn)', function() {
it('runs the function when method fails', function(done) { it('runs the function when method fails', function(done) {
var actualError = 'hook not called'; let actualError = 'hook not called';
User.afterRemoteError('login', function(ctx, next) { User.afterRemoteError('login', function(ctx, next) {
actualError = ctx.error; actualError = ctx.error;
@ -498,7 +498,7 @@ describe.onServer('Remote Methods', function() {
describe('Remote Method invoking context', function() { describe('Remote Method invoking context', function() {
describe('ctx.req', function() { describe('ctx.req', function() {
it('The express ServerRequest object', function(done) { it('The express ServerRequest object', function(done) {
var hookCalled = false; let hookCalled = false;
User.beforeRemote('create', function(ctx, user, next) { User.beforeRemote('create', function(ctx, user, next) {
hookCalled = true; hookCalled = true;
@ -530,7 +530,7 @@ describe.onServer('Remote Methods', function() {
describe('ctx.res', function() { describe('ctx.res', function() {
it('The express ServerResponse object', function(done) { it('The express ServerResponse object', function(done) {
var hookCalled = false; let hookCalled = false;
User.beforeRemote('create', function(ctx, user, next) { User.beforeRemote('create', function(ctx, user, next) {
hookCalled = true; hookCalled = true;
@ -563,15 +563,15 @@ describe.onServer('Remote Methods', function() {
describe('Model.hasMany(Model)', function() { describe('Model.hasMany(Model)', function() {
it('Define a one to many relationship', function(done) { it('Define a one to many relationship', function(done) {
var Book = dataSource.createModel('book', {title: String, author: String}); const Book = dataSource.createModel('book', {title: String, author: String});
var Chapter = dataSource.createModel('chapter', {title: String}); const Chapter = dataSource.createModel('chapter', {title: String});
// by referencing model // by referencing model
Book.hasMany(Chapter); Book.hasMany(Chapter);
Book.create({title: 'Into the Wild', author: 'Jon Krakauer'}, function(err, book) { Book.create({title: 'Into the Wild', author: 'Jon Krakauer'}, function(err, book) {
// using 'chapters' scope for build: // using 'chapters' scope for build:
var c = book.chapters.build({title: 'Chapter 1'}); const c = book.chapters.build({title: 'Chapter 1'});
book.chapters.create({title: 'Chapter 2'}, function() { book.chapters.create({title: 'Chapter 2'}, function() {
c.save(function() { c.save(function() {
Chapter.count({bookId: book.id}, function(err, count) { Chapter.count({bookId: book.id}, function(err, count) {
@ -591,7 +591,7 @@ describe.onServer('Remote Methods', function() {
describe('Model.properties', function() { describe('Model.properties', function() {
it('Normalized properties passed in originally by loopback.createModel()', function() { it('Normalized properties passed in originally by loopback.createModel()', function() {
var props = { const props = {
s: String, s: String,
n: {type: 'Number'}, n: {type: 'Number'},
o: {type: 'String', min: 10, max: 100}, o: {type: 'String', min: 10, max: 100},
@ -599,11 +599,11 @@ describe.onServer('Remote Methods', function() {
g: loopback.GeoPoint, g: loopback.GeoPoint,
}; };
var MyModel = loopback.createModel('foo', props); const MyModel = loopback.createModel('foo', props);
Object.keys(MyModel.definition.properties).forEach(function(key) { Object.keys(MyModel.definition.properties).forEach(function(key) {
var p = MyModel.definition.properties[key]; const p = MyModel.definition.properties[key];
var o = MyModel.definition.properties[key]; const o = MyModel.definition.properties[key];
assert(p); assert(p);
assert(o); assert(o);
assert(typeof p.type === 'function'); assert(typeof p.type === 'function');
@ -622,7 +622,7 @@ describe.onServer('Remote Methods', function() {
describe('Model.extend()', function() { describe('Model.extend()', function() {
it('Create a new model by extending an existing model', function() { it('Create a new model by extending an existing model', function() {
var User = loopback.PersistedModel.extend('test-user', { const User = loopback.PersistedModel.extend('test-user', {
email: String, email: String,
}); });
@ -634,7 +634,7 @@ describe.onServer('Remote Methods', function() {
return 'foo'; return 'foo';
}; };
var MyUser = User.extend('my-user', { const MyUser = User.extend('my-user', {
a: String, a: String,
b: String, b: String,
}); });
@ -642,7 +642,7 @@ describe.onServer('Remote Methods', function() {
assert.equal(MyUser.prototype.bar, User.prototype.bar); assert.equal(MyUser.prototype.bar, User.prototype.bar);
assert.equal(MyUser.foo, User.foo); assert.equal(MyUser.foo, User.foo);
var user = new MyUser({ const user = new MyUser({
email: 'foo@bar.com', email: 'foo@bar.com',
a: 'foo', a: 'foo',
b: 'bar', b: 'bar',
@ -656,21 +656,21 @@ describe.onServer('Remote Methods', function() {
describe('Model.extend() events', function() { describe('Model.extend() events', function() {
it('create isolated emitters for subclasses', function() { it('create isolated emitters for subclasses', function() {
var User1 = loopback.createModel('User1', { const User1 = loopback.createModel('User1', {
'first': String, 'first': String,
'last': String, 'last': String,
}); });
var User2 = loopback.createModel('User2', { const User2 = loopback.createModel('User2', {
'name': String, 'name': String,
}); });
var user1Triggered = false; let user1Triggered = false;
User1.once('x', function(event) { User1.once('x', function(event) {
user1Triggered = true; user1Triggered = true;
}); });
var user2Triggered = false; let user2Triggered = false;
User2.once('x', function(event) { User2.once('x', function(event) {
user2Triggered = true; user2Triggered = true;
}); });
@ -703,7 +703,7 @@ describe.onServer('Remote Methods', function() {
function shouldReturn(methodName, expectedAccessType) { function shouldReturn(methodName, expectedAccessType) {
describe(methodName, function() { describe(methodName, function() {
it('should return ' + expectedAccessType, function() { it('should return ' + expectedAccessType, function() {
var remoteMethod = {name: methodName}; const remoteMethod = {name: methodName};
assert.equal( assert.equal(
User._getAccessTypeForMethod(remoteMethod), User._getAccessTypeForMethod(remoteMethod),
expectedAccessType expectedAccessType
@ -715,8 +715,8 @@ describe.onServer('Remote Methods', function() {
describe('Model.getChangeModel()', function() { describe('Model.getChangeModel()', function() {
it('Get the Change Model', function() { it('Get the Change Model', function() {
var UserChange = User.getChangeModel(); const UserChange = User.getChangeModel();
var change = new UserChange(); const change = new UserChange();
assert(change instanceof app.registry.getModel('Change')); assert(change instanceof app.registry.getModel('Change'));
}); });
}); });
@ -733,12 +733,12 @@ describe.onServer('Remote Methods', function() {
describe('Model.checkpoint(callback)', function() { describe('Model.checkpoint(callback)', function() {
it('Create a checkpoint', function(done) { it('Create a checkpoint', function(done) {
var Checkpoint = User.getChangeModel().getCheckpointModel(); const Checkpoint = User.getChangeModel().getCheckpointModel();
var tasks = [ const tasks = [
getCurrentCheckpoint, getCurrentCheckpoint,
checkpoint, checkpoint,
]; ];
var result, current; let result, current;
async.series(tasks, function(err) { async.series(tasks, function(err) {
if (err) return done(err); if (err) return done(err);
@ -766,11 +766,11 @@ describe.onServer('Remote Methods', function() {
describe('Model._getACLModel()', function() { describe('Model._getACLModel()', function() {
it('should return the subclass of ACL', function() { it('should return the subclass of ACL', function() {
var Model = require('../').Model; const Model = require('../').Model;
var originalValue = Model._ACL(); const originalValue = Model._ACL();
var acl = ACL.extend('acl'); const acl = ACL.extend('acl');
Model._ACL(null); // Reset the ACL class for the base model Model._ACL(null); // Reset the ACL class for the base model
var model = Model._ACL(); const model = Model._ACL();
Model._ACL(originalValue); // Reset the value back Model._ACL(originalValue); // Reset the value back
assert.equal(model, acl); assert.equal(model, acl);
}); });
@ -778,21 +778,21 @@ describe.onServer('Remote Methods', function() {
describe('PersistedModel remote methods', function() { describe('PersistedModel remote methods', function() {
it('includes all aliases', function() { it('includes all aliases', function() {
var app = loopback(); const app = loopback();
var model = PersistedModel.extend('PersistedModelForAliases'); const model = PersistedModel.extend('PersistedModelForAliases');
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
app.model(model, {dataSource: 'db'}); app.model(model, {dataSource: 'db'});
// this code is used by loopback-sdk-angular codegen // this code is used by loopback-sdk-angular codegen
var metadata = app.handler('rest') const metadata = app.handler('rest')
.adapter .adapter
.getClasses() .getClasses()
.filter(function(c) { return c.name === model.modelName; })[0]; .filter(function(c) { return c.name === model.modelName; })[0];
var methodNames = []; let methodNames = [];
metadata.methods.forEach(function(method) { metadata.methods.forEach(function(method) {
methodNames.push(method.name); methodNames.push(method.name);
var aliases = method.sharedMethod.aliases; let aliases = method.sharedMethod.aliases;
if (method.name.indexOf('prototype.') === 0) { if (method.name.indexOf('prototype.') === 0) {
aliases = aliases.map(function(alias) { aliases = aliases.map(function(alias) {
return 'prototype.' + alias; return 'prototype.' + alias;
@ -826,13 +826,13 @@ describe.onServer('Remote Methods', function() {
}); });
it('emits a `remoteMethodDisabled` event', function() { it('emits a `remoteMethodDisabled` event', function() {
var app = loopback(); const app = loopback();
var model = PersistedModel.extend('TestModelForDisablingRemoteMethod'); const model = PersistedModel.extend('TestModelForDisablingRemoteMethod');
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
app.model(model, {dataSource: 'db'}); app.model(model, {dataSource: 'db'});
var callbackSpy = require('sinon').spy(); const callbackSpy = require('sinon').spy();
var TestModel = app.models.TestModelForDisablingRemoteMethod; const TestModel = app.models.TestModelForDisablingRemoteMethod;
TestModel.on('remoteMethodDisabled', callbackSpy); TestModel.on('remoteMethodDisabled', callbackSpy);
TestModel.disableRemoteMethod('findOne', true); TestModel.disableRemoteMethod('findOne', true);
@ -840,13 +840,13 @@ describe.onServer('Remote Methods', function() {
}); });
it('emits a `remoteMethodDisabled` event from disableRemoteMethodByName', function() { it('emits a `remoteMethodDisabled` event from disableRemoteMethodByName', function() {
var app = loopback(); const app = loopback();
var model = PersistedModel.extend('TestModelForDisablingRemoteMethod'); const model = PersistedModel.extend('TestModelForDisablingRemoteMethod');
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
app.model(model, {dataSource: 'db'}); app.model(model, {dataSource: 'db'});
var callbackSpy = require('sinon').spy(); const callbackSpy = require('sinon').spy();
var TestModel = app.models.TestModelForDisablingRemoteMethod; const TestModel = app.models.TestModelForDisablingRemoteMethod;
TestModel.on('remoteMethodDisabled', callbackSpy); TestModel.on('remoteMethodDisabled', callbackSpy);
TestModel.disableRemoteMethodByName('findOne'); TestModel.disableRemoteMethodByName('findOne');
@ -854,17 +854,17 @@ describe.onServer('Remote Methods', function() {
}); });
it('emits a `remoteMethodAdded` event', function() { it('emits a `remoteMethodAdded` event', function() {
var app = loopback(); const app = loopback();
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
var User = app.registry.getModel('User'); const User = app.registry.getModel('User');
app.model(User, {dataSource: 'db'}); app.model(User, {dataSource: 'db'});
var Token = app.registry.getModel('AccessToken'); const Token = app.registry.getModel('AccessToken');
app.model(Token, {dataSource: 'db'}); app.model(Token, {dataSource: 'db'});
var callbackSpy = require('sinon').spy(); const callbackSpy = require('sinon').spy();
var TestModel = app.models.User; const TestModel = app.models.User;
TestModel.on('remoteMethodAdded', callbackSpy); TestModel.on('remoteMethodAdded', callbackSpy);
TestModel.nestRemoting('accessTokens'); TestModel.nestRemoting('accessTokens');
@ -873,13 +873,13 @@ describe.onServer('Remote Methods', function() {
}); });
it('emits a `remoteMethodAdded` event from remoteMethod', function() { it('emits a `remoteMethodAdded` event from remoteMethod', function() {
var app = loopback(); const app = loopback();
var model = PersistedModel.extend('TestModelForAddingRemoteMethod'); const model = PersistedModel.extend('TestModelForAddingRemoteMethod');
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
app.model(model, {dataSource: 'db'}); app.model(model, {dataSource: 'db'});
var callbackSpy = require('sinon').spy(); const callbackSpy = require('sinon').spy();
var TestModel = app.models.TestModelForAddingRemoteMethod; const TestModel = app.models.TestModelForAddingRemoteMethod;
TestModel.on('remoteMethodAdded', callbackSpy); TestModel.on('remoteMethodAdded', callbackSpy);
TestModel.remoteMethod('getTest', { TestModel.remoteMethod('getTest', {
accepts: {arg: 'options', type: 'object', http: 'optionsFromRequest'}, accepts: {arg: 'options', type: 'object', http: 'optionsFromRequest'},
@ -891,7 +891,7 @@ describe.onServer('Remote Methods', function() {
}); });
describe('Model.getApp(cb)', function() { describe('Model.getApp(cb)', function() {
var app, TestModel; let app, TestModel;
beforeEach(function setup() { beforeEach(function setup() {
app = loopback(); app = loopback();
TestModel = loopback.createModel('TestModelForGetApp'); // unique name TestModel = loopback.createModel('TestModelForGetApp'); // unique name
@ -924,7 +924,7 @@ describe.onServer('Remote Methods', function() {
}); });
describe('Model.createOptionsFromRemotingContext', function() { describe('Model.createOptionsFromRemotingContext', function() {
var app, TestModel, accessToken, actualOptions; let app, TestModel, accessToken, actualOptions;
before(setupAppAndRequest); before(setupAppAndRequest);
before(createUserAndAccessToken); before(createUserAndAccessToken);
@ -1055,8 +1055,8 @@ describe.onServer('Remote Methods', function() {
} }
function createUserAndAccessToken() { function createUserAndAccessToken() {
var CREDENTIALS = {email: 'context@example.com', password: 'pass'}; const CREDENTIALS = {email: 'context@example.com', password: 'pass'};
var User = app.registry.getModel('User'); const User = app.registry.getModel('User');
return User.create(CREDENTIALS) return User.create(CREDENTIALS)
.then(function(u) { .then(function(u) {
return User.login(CREDENTIALS); return User.login(CREDENTIALS);

View File

@ -4,13 +4,13 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var loopback = require('../'); const loopback = require('../');
var ctx = require('../lib/access-context'); const ctx = require('../lib/access-context');
var extend = require('util')._extend; const extend = require('util')._extend;
var AccessContext = ctx.AccessContext; const AccessContext = ctx.AccessContext;
var Principal = ctx.Principal; const Principal = ctx.Principal;
var Promise = require('bluebird'); const Promise = require('bluebird');
const waitForEvent = require('./helpers/wait-for-event'); const waitForEvent = require('./helpers/wait-for-event');
const supertest = require('supertest'); const supertest = require('supertest');
const loggers = require('./helpers/error-loggers'); const loggers = require('./helpers/error-loggers');
@ -19,8 +19,8 @@ const logServerErrorsOtherThan = loggers.logServerErrorsOtherThan;
describe('Multiple users with custom principalType', function() { describe('Multiple users with custom principalType', function() {
this.timeout(10000); this.timeout(10000);
var commonCredentials = {email: 'foo@bar.com', password: 'bar'}; const commonCredentials = {email: 'foo@bar.com', password: 'bar'};
var app, OneUser, AnotherUser, AccessToken, Role, let app, OneUser, AnotherUser, AccessToken, Role,
userFromOneModel, userFromAnotherModel, userRole, userOneBaseContext; userFromOneModel, userFromAnotherModel, userRole, userOneBaseContext;
beforeEach(function setupAppAndModels() { beforeEach(function setupAppAndModels() {
@ -30,7 +30,7 @@ describe('Multiple users with custom principalType', function() {
app.set('remoting', {rest: {handleErrors: false}}); app.set('remoting', {rest: {handleErrors: false}});
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
var userModelOptions = { const userModelOptions = {
base: 'User', base: 'User',
// forceId is set to false for the purpose of updating the same affected user within the // forceId is set to false for the purpose of updating the same affected user within the
// `Email Update` test cases. // `Email Update` test cases.
@ -118,7 +118,7 @@ describe('Multiple users with custom principalType', function() {
describe('User.logout', function() { describe('User.logout', function() {
it('logs out a user from user model 1 without logging out user from model 2', it('logs out a user from user model 1 without logging out user from model 2',
function() { function() {
var tokenOfOneUser; let tokenOfOneUser;
return Promise.all([ return Promise.all([
OneUser.login(commonCredentials), OneUser.login(commonCredentials),
AnotherUser.login(commonCredentials), AnotherUser.login(commonCredentials),
@ -131,7 +131,7 @@ describe('Multiple users with custom principalType', function() {
return AccessToken.find({}); return AccessToken.find({});
}) })
.then(function(allTokens) { .then(function(allTokens) {
var data = allTokens.map(function(token) { const data = allTokens.map(function(token) {
return {userId: token.userId, principalType: token.principalType}; return {userId: token.userId, principalType: token.principalType};
}); });
expect(data).to.eql([ expect(data).to.eql([
@ -144,7 +144,7 @@ describe('Multiple users with custom principalType', function() {
describe('Password Reset', function() { describe('Password Reset', function() {
describe('User.resetPassword(options)', function() { describe('User.resetPassword(options)', function() {
var options = { const options = {
email: 'foo@bar.com', email: 'foo@bar.com',
redirect: 'http://foobar.com/reset-password', redirect: 'http://foobar.com/reset-password',
}; };
@ -172,7 +172,7 @@ describe('Multiple users with custom principalType', function() {
}); });
describe('AccessToken (session) invalidation when changing email', function() { describe('AccessToken (session) invalidation when changing email', function() {
var anotherUserFromOneModel; let anotherUserFromOneModel;
it('impact only the related user', function() { it('impact only the related user', function() {
return OneUser.create({email: 'original@example.com', password: 'bar'}) return OneUser.create({email: 'original@example.com', password: 'bar'})
@ -192,7 +192,7 @@ describe('Multiple users with custom principalType', function() {
return AccessToken.find({'order': 'principalType ASC'}); return AccessToken.find({'order': 'principalType ASC'});
}) })
.then(function(allTokens) { .then(function(allTokens) {
var data = allTokens.map(function(token) { const data = allTokens.map(function(token) {
return {userId: token.userId, principalType: token.principalType}; return {userId: token.userId, principalType: token.principalType};
}); });
expect(data).to.eql([ expect(data).to.eql([
@ -205,7 +205,7 @@ describe('Multiple users with custom principalType', function() {
}); });
describe('AccessContext', function() { describe('AccessContext', function() {
var ThirdUser, userFromThirdModel, accessContext; let ThirdUser, userFromThirdModel, accessContext;
beforeEach(function() { beforeEach(function() {
accessContext = new AccessContext({registry: OneUser.registry}); accessContext = new AccessContext({registry: OneUser.registry});
@ -221,7 +221,7 @@ describe('Multiple users with custom principalType', function() {
{type: Principal.SCOPE}, {type: Principal.SCOPE},
{type: OneUser.modelName, id: userFromOneModel.id}, {type: OneUser.modelName, id: userFromOneModel.id},
]); ]);
var user = accessContext.getUser(); const user = accessContext.getUser();
expect(user).to.eql({ expect(user).to.eql({
id: userFromOneModel.id, id: userFromOneModel.id,
principalType: OneUser.modelName, principalType: OneUser.modelName,
@ -237,7 +237,7 @@ describe('Multiple users with custom principalType', function() {
{type: 'invalidModelName'}, {type: 'invalidModelName'},
{type: OneUser.modelName, id: userFromOneModel.id}, {type: OneUser.modelName, id: userFromOneModel.id},
]); ]);
var user = accessContext.getUser(); const user = accessContext.getUser();
expect(user).to.eql({ expect(user).to.eql({
id: userFromOneModel.id, id: userFromOneModel.id,
principalType: OneUser.modelName, principalType: OneUser.modelName,
@ -251,7 +251,7 @@ describe('Multiple users with custom principalType', function() {
return ThirdUser.create(commonCredentials) return ThirdUser.create(commonCredentials)
.then(function(userFromThirdModel) { .then(function(userFromThirdModel) {
accessContext.addPrincipal(ThirdUser.modelName, userFromThirdModel.id); accessContext.addPrincipal(ThirdUser.modelName, userFromThirdModel.id);
var user = accessContext.getUser(); const user = accessContext.getUser();
expect(user).to.eql({ expect(user).to.eql({
id: userFromThirdModel.id, id: userFromThirdModel.id,
principalType: ThirdUser.modelName, principalType: ThirdUser.modelName,
@ -272,7 +272,7 @@ describe('Multiple users with custom principalType', function() {
describe('Role model', function() { describe('Role model', function() {
this.timeout(10000); this.timeout(10000);
var RoleMapping, ACL, user; let RoleMapping, ACL, user;
beforeEach(function() { beforeEach(function() {
ACL = app.registry.getModel('ACL'); ACL = app.registry.getModel('ACL');
@ -374,7 +374,7 @@ describe('Multiple users with custom principalType', function() {
describe('$owner', function() { describe('$owner', function() {
it('supports legacy behavior with relations', function() { it('supports legacy behavior with relations', function() {
var Album = app.registry.createModel('Album', { const Album = app.registry.createModel('Album', {
name: String, name: String,
userId: Number, userId: Number,
}, { }, {
@ -390,7 +390,7 @@ describe('Multiple users with custom principalType', function() {
return Album.create({name: 'album', userId: userFromOneModel.id}) return Album.create({name: 'album', userId: userFromOneModel.id})
.then(function(album) { .then(function(album) {
var validContext = { const validContext = {
principalType: OneUser.modelName, principalType: OneUser.modelName,
principalId: userFromOneModel.id, principalId: userFromOneModel.id,
model: Album, model: Album,
@ -406,7 +406,7 @@ describe('Multiple users with custom principalType', function() {
// With multiple users config, we cannot resolve a user based just on // With multiple users config, we cannot resolve a user based just on
// his id, as many users from different models could have the same id. // his id, as many users from different models could have the same id.
it('legacy behavior resolves false without belongsTo relation', function() { it('legacy behavior resolves false without belongsTo relation', function() {
var Album = app.registry.createModel('Album', { const Album = app.registry.createModel('Album', {
name: String, name: String,
userId: Number, userId: Number,
owner: Number, owner: Number,
@ -419,7 +419,7 @@ describe('Multiple users with custom principalType', function() {
owner: userFromOneModel.id, owner: userFromOneModel.id,
}) })
.then(function(album) { .then(function(album) {
var authContext = { const authContext = {
principalType: OneUser.modelName, principalType: OneUser.modelName,
principalId: userFromOneModel.id, principalId: userFromOneModel.id,
model: Album, model: Album,
@ -433,7 +433,7 @@ describe('Multiple users with custom principalType', function() {
}); });
it('legacy behavior resolves false if owner has incorrect principalType', function() { it('legacy behavior resolves false if owner has incorrect principalType', function() {
var Album = app.registry.createModel('Album', { const Album = app.registry.createModel('Album', {
name: String, name: String,
userId: Number, userId: Number,
}, { }, {
@ -449,12 +449,12 @@ describe('Multiple users with custom principalType', function() {
return Album.create({name: 'album', userId: userFromOneModel.id}) return Album.create({name: 'album', userId: userFromOneModel.id})
.then(function(album) { .then(function(album) {
var invalidPrincipalTypes = [ const invalidPrincipalTypes = [
'invalidContextName', 'invalidContextName',
'USER', 'USER',
AnotherUser.modelName, AnotherUser.modelName,
]; ];
var invalidContexts = invalidPrincipalTypes.map(principalType => { const invalidContexts = invalidPrincipalTypes.map(principalType => {
return { return {
principalType, principalType,
principalId: userFromOneModel.id, principalId: userFromOneModel.id,
@ -485,12 +485,12 @@ describe('Multiple users with custom principalType', function() {
function() { function() {
// passing {ownerRelations: true} will enable the new $owner role resolver // passing {ownerRelations: true} will enable the new $owner role resolver
// with any belongsTo relation allowing to resolve truthy // with any belongsTo relation allowing to resolve truthy
var Message = createModelWithOptions( const Message = createModelWithOptions(
'ModelWithAllRelations', 'ModelWithAllRelations',
{ownerRelations: true} {ownerRelations: true}
); );
var messages = [ const messages = [
{content: 'firstMessage', customerId: userFromOneModel.id}, {content: 'firstMessage', customerId: userFromOneModel.id},
{ {
content: 'secondMessage', content: 'secondMessage',
@ -552,7 +552,7 @@ describe('Multiple users with custom principalType', function() {
// helpers // helpers
function isOwnerForMessage(user, msg) { function isOwnerForMessage(user, msg) {
var accessContext = { const accessContext = {
principalType: user.constructor.modelName, principalType: user.constructor.modelName,
principalId: user.id, principalId: user.id,
model: msg.constructor, model: msg.constructor,
@ -569,7 +569,7 @@ describe('Multiple users with custom principalType', function() {
} }
function createModelWithOptions(name, options) { function createModelWithOptions(name, options) {
var baseOptions = { const baseOptions = {
relations: { relations: {
sender: { sender: {
type: 'belongsTo', type: 'belongsTo',
@ -584,7 +584,7 @@ describe('Multiple users with custom principalType', function() {
}, },
}; };
options = extend(baseOptions, options); options = extend(baseOptions, options);
var Model = app.registry.createModel( const Model = app.registry.createModel(
name, name,
{content: String, senderType: String}, {content: String, senderType: String},
options options
@ -768,7 +768,7 @@ describe('Multiple users with custom principalType', function() {
// helpers // helpers
function createUserModel(app, name, options) { function createUserModel(app, name, options) {
var model = app.registry.createModel(Object.assign({name: name}, options)); const model = app.registry.createModel(Object.assign({name: name}, options));
app.model(model, {dataSource: 'db'}); app.model(model, {dataSource: 'db'});
model.setMaxListeners(0); // allow many User.afterRemote's to be called model.setMaxListeners(0); // allow many User.afterRemote's to be called
return model; return model;

View File

@ -4,16 +4,16 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var loopback = require('../'); const loopback = require('../');
describe('Registry', function() { describe('Registry', function() {
describe('createModel', function() { describe('createModel', function() {
it('should throw error upon extending non-exist base model', function() { it('should throw error upon extending non-exist base model', function() {
var app = loopback(); const app = loopback();
var props = {}; const props = {};
var opts = {base: 'nonexistent'}; const opts = {base: 'nonexistent'};
expect(function() { app.registry.createModel('aModel', props, opts); }) expect(function() { app.registry.createModel('aModel', props, opts); })
.to.throw(/model\s`aModel`(.*)unknown\smodel\s`nonexistent`/); .to.throw(/model\s`aModel`(.*)unknown\smodel\s`nonexistent`/);
}); });
@ -21,26 +21,26 @@ describe('Registry', function() {
describe('one per app', function() { describe('one per app', function() {
it('should allow two apps to reuse the same model name', function(done) { it('should allow two apps to reuse the same model name', function(done) {
var appFoo = loopback(); const appFoo = loopback();
var appBar = loopback(); const appBar = loopback();
var modelName = 'MyModel'; const modelName = 'MyModel';
var subModelName = 'Sub' + modelName; const subModelName = 'Sub' + modelName;
var settings = {base: 'PersistedModel'}; const settings = {base: 'PersistedModel'};
appFoo.set('perAppRegistries', true); appFoo.set('perAppRegistries', true);
appBar.set('perAppRegistries', true); appBar.set('perAppRegistries', true);
var dsFoo = appFoo.dataSource('dsFoo', {connector: 'memory'}); const dsFoo = appFoo.dataSource('dsFoo', {connector: 'memory'});
var dsBar = appFoo.dataSource('dsBar', {connector: 'memory'}); const dsBar = appFoo.dataSource('dsBar', {connector: 'memory'});
var FooModel = appFoo.registry.createModel(modelName, {}, settings); const FooModel = appFoo.registry.createModel(modelName, {}, settings);
appFoo.model(FooModel, {dataSource: dsFoo}); appFoo.model(FooModel, {dataSource: dsFoo});
var FooSubModel = appFoo.registry.createModel(subModelName, {}, settings); const FooSubModel = appFoo.registry.createModel(subModelName, {}, settings);
appFoo.model(FooSubModel, {dataSource: dsFoo}); appFoo.model(FooSubModel, {dataSource: dsFoo});
var BarModel = appBar.registry.createModel(modelName, {}, settings); const BarModel = appBar.registry.createModel(modelName, {}, settings);
appBar.model(BarModel, {dataSource: dsBar}); appBar.model(BarModel, {dataSource: dsBar});
var BarSubModel = appBar.registry.createModel(subModelName, {}, settings); const BarSubModel = appBar.registry.createModel(subModelName, {}, settings);
appBar.model(BarSubModel, {dataSource: dsBar}); appBar.model(BarSubModel, {dataSource: dsBar});
FooModel.hasMany(FooSubModel); FooModel.hasMany(FooSubModel);

View File

@ -4,15 +4,15 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../'); const loopback = require('../');
var lt = require('./helpers/loopback-testing-helper'); const lt = require('./helpers/loopback-testing-helper');
var path = require('path'); const path = require('path');
var SIMPLE_APP = path.join(__dirname, 'fixtures', 'simple-integration-app'); const SIMPLE_APP = path.join(__dirname, 'fixtures', 'simple-integration-app');
var app = require(path.join(SIMPLE_APP, 'server/server.js')); const app = require(path.join(SIMPLE_APP, 'server/server.js'));
var assert = require('assert'); const assert = require('assert');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var debug = require('debug')('loopback:test:relations.integration'); const debug = require('debug')('loopback:test:relations.integration');
var async = require('async'); const async = require('async');
describe('relations - integration', function() { describe('relations - integration', function() {
lt.beforeEach.withApp(app); lt.beforeEach.withApp(app);
@ -32,9 +32,9 @@ describe('relations - integration', function() {
describe('polymorphicHasMany', function() { describe('polymorphicHasMany', function() {
before(function defineProductAndCategoryModels() { before(function defineProductAndCategoryModels() {
var Team = app.registry.createModel('Team', {name: 'string'}); const Team = app.registry.createModel('Team', {name: 'string'});
var Reader = app.registry.createModel('Reader', {name: 'string'}); const Reader = app.registry.createModel('Reader', {name: 'string'});
var Picture = app.registry.createModel('Picture', const Picture = app.registry.createModel('Picture',
{name: 'string', imageableId: 'number', imageableType: 'string'}); {name: 'string', imageableId: 'number', imageableType: 'string'});
app.model(Team, {dataSource: 'db'}); app.model(Team, {dataSource: 'db'});
@ -56,7 +56,7 @@ describe('relations - integration', function() {
}); });
before(function createEvent(done) { before(function createEvent(done) {
var test = this; const test = this;
app.models.Team.create({name: 'Team 1'}, app.models.Team.create({name: 'Team 1'},
function(err, team) { function(err, team) {
if (err) return done(err); if (err) return done(err);
@ -80,7 +80,7 @@ describe('relations - integration', function() {
}); });
it('includes the related child model', function(done) { it('includes the related child model', function(done) {
var url = '/api/readers/' + this.reader.id; const url = '/api/readers/' + this.reader.id;
this.get(url) this.get(url)
.query({'filter': {'include': 'pictures'}}) .query({'filter': {'include': 'pictures'}})
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -97,7 +97,7 @@ describe('relations - integration', function() {
}); });
it('includes the related parent model', function(done) { it('includes the related parent model', function(done) {
var url = '/api/pictures'; const url = '/api/pictures';
this.get(url) this.get(url)
.query({'filter': {'include': 'imageable'}}) .query({'filter': {'include': 'imageable'}})
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -112,7 +112,7 @@ describe('relations - integration', function() {
}); });
it('includes related models scoped to the related parent model', function(done) { it('includes related models scoped to the related parent model', function(done) {
var url = '/api/pictures'; const url = '/api/pictures';
this.get(url) this.get(url)
.query({'filter': {'include': { .query({'filter': {'include': {
'relation': 'imageable', 'relation': 'imageable',
@ -227,7 +227,7 @@ describe('relations - integration', function() {
describe('PUT /api/store/:id/widgets/:fk', function() { describe('PUT /api/store/:id/widgets/:fk', function() {
beforeEach(function(done) { beforeEach(function(done) {
var self = this; const self = this;
this.store.widgets.create({ this.store.widgets.create({
name: this.widgetName, name: this.widgetName,
}, function(err, widget) { }, function(err, widget) {
@ -237,7 +237,7 @@ describe('relations - integration', function() {
}); });
}); });
it('does not add default properties to request body', function(done) { it('does not add default properties to request body', function(done) {
var self = this; const self = this;
self.request.put(self.url) self.request.put(self.url)
.send({active: true}) .send({active: true})
.end(function(err) { .end(function(err) {
@ -254,7 +254,7 @@ describe('relations - integration', function() {
describe('/stores/:id/widgets/:fk - 200', function() { describe('/stores/:id/widgets/:fk - 200', function() {
beforeEach(function(done) { beforeEach(function(done) {
var self = this; const self = this;
this.store.widgets.create({ this.store.widgets.create({
name: this.widgetName, name: this.widgetName,
}, function(err, widget) { }, function(err, widget) {
@ -328,7 +328,7 @@ describe('relations - integration', function() {
describe('/widgets/:id/store', function() { describe('/widgets/:id/store', function() {
beforeEach(function(done) { beforeEach(function(done) {
var self = this; const self = this;
this.store.widgets.create({ this.store.widgets.create({
name: this.widgetName, name: this.widgetName,
}, function(err, widget) { }, function(err, widget) {
@ -348,7 +348,7 @@ describe('relations - integration', function() {
describe('hasMany through', function() { describe('hasMany through', function() {
function setup(connecting, cb) { function setup(connecting, cb) {
var root = {}; const root = {};
async.series([ async.series([
// Clean up models // Clean up models
@ -401,7 +401,7 @@ describe('relations - integration', function() {
describe('PUT /physicians/:id/patients/rel/:fk', function() { describe('PUT /physicians/:id/patients/rel/:fk', function() {
before(function(done) { before(function(done) {
var self = this; const self = this;
setup(false, function(err, root) { setup(false, function(err, root) {
self.url = root.relUrl; self.url = root.relUrl;
self.patient = root.patient; self.patient = root.patient;
@ -419,7 +419,7 @@ describe('relations - integration', function() {
}); });
it('should create a record in appointment', function(done) { it('should create a record in appointment', function(done) {
var self = this; const self = this;
app.models.appointment.find(function(err, apps) { app.models.appointment.find(function(err, apps) {
assert.equal(apps.length, 1); assert.equal(apps.length, 1);
assert.equal(apps[0].patientId, self.patient.id); assert.equal(apps[0].patientId, self.patient.id);
@ -429,7 +429,7 @@ describe('relations - integration', function() {
}); });
it('should connect physician to patient', function(done) { it('should connect physician to patient', function(done) {
var self = this; const self = this;
self.physician.patients(function(err, patients) { self.physician.patients(function(err, patients) {
assert.equal(patients.length, 1); assert.equal(patients.length, 1);
assert.equal(patients[0].id, self.patient.id); assert.equal(patients[0].id, self.patient.id);
@ -442,7 +442,7 @@ describe('relations - integration', function() {
describe('PUT /physicians/:id/patients/rel/:fk with data', function() { describe('PUT /physicians/:id/patients/rel/:fk with data', function() {
before(function(done) { before(function(done) {
var self = this; const self = this;
setup(false, function(err, root) { setup(false, function(err, root) {
self.url = root.relUrl; self.url = root.relUrl;
self.patient = root.patient; self.patient = root.patient;
@ -452,8 +452,8 @@ describe('relations - integration', function() {
}); });
}); });
var NOW = Date.now(); const NOW = Date.now();
var data = {date: new Date(NOW)}; const data = {date: new Date(NOW)};
lt.describe.whenCalledRemotely('PUT', '/api/physicians/:id/patients/rel/:fk', data, function() { lt.describe.whenCalledRemotely('PUT', '/api/physicians/:id/patients/rel/:fk', data, function() {
it('should succeed with statusCode 200', function() { it('should succeed with statusCode 200', function() {
@ -464,7 +464,7 @@ describe('relations - integration', function() {
}); });
it('should create a record in appointment', function(done) { it('should create a record in appointment', function(done) {
var self = this; const self = this;
app.models.appointment.find(function(err, apps) { app.models.appointment.find(function(err, apps) {
assert.equal(apps.length, 1); assert.equal(apps.length, 1);
assert.equal(apps[0].patientId, self.patient.id); assert.equal(apps[0].patientId, self.patient.id);
@ -476,7 +476,7 @@ describe('relations - integration', function() {
}); });
it('should connect physician to patient', function(done) { it('should connect physician to patient', function(done) {
var self = this; const self = this;
self.physician.patients(function(err, patients) { self.physician.patients(function(err, patients) {
assert.equal(patients.length, 1); assert.equal(patients.length, 1);
assert.equal(patients[0].id, self.patient.id); assert.equal(patients[0].id, self.patient.id);
@ -489,7 +489,7 @@ describe('relations - integration', function() {
describe('HEAD /physicians/:id/patients/rel/:fk', function() { describe('HEAD /physicians/:id/patients/rel/:fk', function() {
before(function(done) { before(function(done) {
var self = this; const self = this;
setup(true, function(err, root) { setup(true, function(err, root) {
self.url = root.relUrl; self.url = root.relUrl;
self.patient = root.patient; self.patient = root.patient;
@ -508,7 +508,7 @@ describe('relations - integration', function() {
describe('HEAD /physicians/:id/patients/rel/:fk that does not exist', function() { describe('HEAD /physicians/:id/patients/rel/:fk that does not exist', function() {
before(function(done) { before(function(done) {
var self = this; const self = this;
setup(true, function(err, root) { setup(true, function(err, root) {
self.url = '/api/physicians/' + root.physician.id + self.url = '/api/physicians/' + root.physician.id +
'/patients/rel/' + '999'; '/patients/rel/' + '999';
@ -528,7 +528,7 @@ describe('relations - integration', function() {
describe('DELETE /physicians/:id/patients/rel/:fk', function() { describe('DELETE /physicians/:id/patients/rel/:fk', function() {
before(function(done) { before(function(done) {
var self = this; const self = this;
setup(true, function(err, root) { setup(true, function(err, root) {
self.url = root.relUrl; self.url = root.relUrl;
self.patient = root.patient; self.patient = root.patient;
@ -539,7 +539,7 @@ describe('relations - integration', function() {
}); });
it('should create a record in appointment', function(done) { it('should create a record in appointment', function(done) {
var self = this; const self = this;
app.models.appointment.find(function(err, apps) { app.models.appointment.find(function(err, apps) {
assert.equal(apps.length, 1); assert.equal(apps.length, 1);
assert.equal(apps[0].patientId, self.patient.id); assert.equal(apps[0].patientId, self.patient.id);
@ -549,7 +549,7 @@ describe('relations - integration', function() {
}); });
it('should connect physician to patient', function(done) { it('should connect physician to patient', function(done) {
var self = this; const self = this;
self.physician.patients(function(err, patients) { self.physician.patients(function(err, patients) {
assert.equal(patients.length, 1); assert.equal(patients.length, 1);
assert.equal(patients[0].id, self.patient.id); assert.equal(patients[0].id, self.patient.id);
@ -564,7 +564,7 @@ describe('relations - integration', function() {
}); });
it('should remove the record in appointment', function(done) { it('should remove the record in appointment', function(done) {
var self = this; const self = this;
app.models.appointment.find(function(err, apps) { app.models.appointment.find(function(err, apps) {
assert.equal(apps.length, 0); assert.equal(apps.length, 0);
@ -573,7 +573,7 @@ describe('relations - integration', function() {
}); });
it('should remove the connection between physician and patient', function(done) { it('should remove the connection between physician and patient', function(done) {
var self = this; const self = this;
// Need to refresh the cache // Need to refresh the cache
self.physician.patients(true, function(err, patients) { self.physician.patients(true, function(err, patients) {
assert.equal(patients.length, 0); assert.equal(patients.length, 0);
@ -586,7 +586,7 @@ describe('relations - integration', function() {
describe('GET /physicians/:id/patients/:fk', function() { describe('GET /physicians/:id/patients/:fk', function() {
before(function(done) { before(function(done) {
var self = this; const self = this;
setup(true, function(err, root) { setup(true, function(err, root) {
self.url = '/api/physicians/' + root.physician.id + self.url = '/api/physicians/' + root.physician.id +
'/patients/' + root.patient.id; '/patients/' + root.patient.id;
@ -607,7 +607,7 @@ describe('relations - integration', function() {
describe('DELETE /physicians/:id/patients/:fk', function() { describe('DELETE /physicians/:id/patients/:fk', function() {
before(function(done) { before(function(done) {
var self = this; const self = this;
setup(true, function(err, root) { setup(true, function(err, root) {
self.url = '/api/physicians/' + root.physician.id + self.url = '/api/physicians/' + root.physician.id +
'/patients/' + root.patient.id; '/patients/' + root.patient.id;
@ -624,7 +624,7 @@ describe('relations - integration', function() {
}); });
it('should remove the record in appointment', function(done) { it('should remove the record in appointment', function(done) {
var self = this; const self = this;
app.models.appointment.find(function(err, apps) { app.models.appointment.find(function(err, apps) {
assert.equal(apps.length, 0); assert.equal(apps.length, 0);
@ -633,7 +633,7 @@ describe('relations - integration', function() {
}); });
it('should remove the connection between physician and patient', function(done) { it('should remove the connection between physician and patient', function(done) {
var self = this; const self = this;
// Need to refresh the cache // Need to refresh the cache
self.physician.patients(true, function(err, patients) { self.physician.patients(true, function(err, patients) {
assert.equal(patients.length, 0); assert.equal(patients.length, 0);
@ -643,7 +643,7 @@ describe('relations - integration', function() {
}); });
it('should remove the record in patient', function(done) { it('should remove the record in patient', function(done) {
var self = this; const self = this;
app.models.patient.find(function(err, patients) { app.models.patient.find(function(err, patients) {
assert.equal(patients.length, 0); assert.equal(patients.length, 0);
@ -659,11 +659,11 @@ describe('relations - integration', function() {
// Disable "Warning: overriding remoting type product" // Disable "Warning: overriding remoting type product"
this.app.remotes()._typeRegistry._options.warnWhenOverridingType = false; this.app.remotes()._typeRegistry._options.warnWhenOverridingType = false;
var product = app.registry.createModel( const product = app.registry.createModel(
'product', 'product',
{id: 'string', name: 'string'} {id: 'string', name: 'string'}
); );
var category = app.registry.createModel( const category = app.registry.createModel(
'category', 'category',
{id: 'string', name: 'string'} {id: 'string', name: 'string'}
); );
@ -677,7 +677,7 @@ describe('relations - integration', function() {
lt.beforeEach.givenModel('category'); lt.beforeEach.givenModel('category');
beforeEach(function createProductsInCategory(done) { beforeEach(function createProductsInCategory(done) {
var test = this; const test = this;
this.category.products.create({ this.category.products.create({
name: 'a-product', name: 'a-product',
}, function(err, product) { }, function(err, product) {
@ -704,7 +704,7 @@ describe('relations - integration', function() {
it.skip('allows to find related objects via where filter', function(done) { it.skip('allows to find related objects via where filter', function(done) {
// TODO https://github.com/strongloop/loopback-datasource-juggler/issues/94 // TODO https://github.com/strongloop/loopback-datasource-juggler/issues/94
var expectedProduct = this.product; const expectedProduct = this.product;
this.get('/api/products?filter[where][categoryId]=' + this.category.id) this.get('/api/products?filter[where][categoryId]=' + this.category.id)
.expect(200, function(err, res) { .expect(200, function(err, res) {
if (err) return done(err); if (err) return done(err);
@ -721,7 +721,7 @@ describe('relations - integration', function() {
}); });
it('allows to find related object via URL scope', function(done) { it('allows to find related object via URL scope', function(done) {
var expectedProduct = this.product; const expectedProduct = this.product;
this.get('/api/categories/' + this.category.id + '/products') this.get('/api/categories/' + this.category.id + '/products')
.expect(200, function(err, res) { .expect(200, function(err, res) {
if (err) return done(err); if (err) return done(err);
@ -738,8 +738,8 @@ describe('relations - integration', function() {
}); });
it('includes requested related models in `find`', function(done) { it('includes requested related models in `find`', function(done) {
var expectedProduct = this.product; const expectedProduct = this.product;
var url = '/api/categories/findOne?filter[where][id]=' + const url = '/api/categories/findOne?filter[where][id]=' +
this.category.id + '&filter[include]=products'; this.category.id + '&filter[include]=products';
this.get(url) this.get(url)
@ -760,9 +760,9 @@ describe('relations - integration', function() {
it.skip('includes requested related models in `findById`', function(done) { it.skip('includes requested related models in `findById`', function(done) {
// TODO https://github.com/strongloop/loopback-datasource-juggler/issues/93 // TODO https://github.com/strongloop/loopback-datasource-juggler/issues/93
var expectedProduct = this.product; const expectedProduct = this.product;
// Note: the URL format is not final // Note: the URL format is not final
var url = '/api/categories/' + this.category.id + '?include=products'; const url = '/api/categories/' + this.category.id + '?include=products';
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -783,14 +783,14 @@ describe('relations - integration', function() {
describe('embedsOne', function() { describe('embedsOne', function() {
before(function defineGroupAndPosterModels() { before(function defineGroupAndPosterModels() {
var group = app.registry.createModel( const group = app.registry.createModel(
'group', 'group',
{name: 'string'}, {name: 'string'},
{plural: 'groups'} {plural: 'groups'}
); );
app.model(group, {dataSource: 'db'}); app.model(group, {dataSource: 'db'});
var poster = app.registry.createModel( const poster = app.registry.createModel(
'poster', 'poster',
{url: 'string'} {url: 'string'}
); );
@ -800,7 +800,7 @@ describe('relations - integration', function() {
}); });
before(function createImage(done) { before(function createImage(done) {
var test = this; const test = this;
app.models.group.create({name: 'Group 1'}, app.models.group.create({name: 'Group 1'},
function(err, group) { function(err, group) {
if (err) return done(err); if (err) return done(err);
@ -816,7 +816,7 @@ describe('relations - integration', function() {
}); });
it('creates an embedded model', function(done) { it('creates an embedded model', function(done) {
var url = '/api/groups/' + this.group.id + '/cover'; const url = '/api/groups/' + this.group.id + '/cover';
this.post(url) this.post(url)
.send({url: 'http://image.url'}) .send({url: 'http://image.url'})
@ -830,7 +830,7 @@ describe('relations - integration', function() {
}); });
it('includes the embedded models', function(done) { it('includes the embedded models', function(done) {
var url = '/api/groups/' + this.group.id; const url = '/api/groups/' + this.group.id;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -846,7 +846,7 @@ describe('relations - integration', function() {
}); });
it('returns the embedded model', function(done) { it('returns the embedded model', function(done) {
var url = '/api/groups/' + this.group.id + '/cover'; const url = '/api/groups/' + this.group.id + '/cover';
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -861,7 +861,7 @@ describe('relations - integration', function() {
}); });
it('updates an embedded model', function(done) { it('updates an embedded model', function(done) {
var url = '/api/groups/' + this.group.id + '/cover'; const url = '/api/groups/' + this.group.id + '/cover';
this.put(url) this.put(url)
.send({url: 'http://changed.url'}) .send({url: 'http://changed.url'})
@ -873,7 +873,7 @@ describe('relations - integration', function() {
}); });
it('returns the updated embedded model', function(done) { it('returns the updated embedded model', function(done) {
var url = '/api/groups/' + this.group.id + '/cover'; const url = '/api/groups/' + this.group.id + '/cover';
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -888,26 +888,26 @@ describe('relations - integration', function() {
}); });
it('deletes an embedded model', function(done) { it('deletes an embedded model', function(done) {
var url = '/api/groups/' + this.group.id + '/cover'; const url = '/api/groups/' + this.group.id + '/cover';
this.del(url).expect(204, done); this.del(url).expect(204, done);
}); });
it('deleted the embedded model', function(done) { it('deleted the embedded model', function(done) {
var url = '/api/groups/' + this.group.id + '/cover'; const url = '/api/groups/' + this.group.id + '/cover';
this.get(url).expect(404, done); this.get(url).expect(404, done);
}); });
}); });
describe('embedsMany', function() { describe('embedsMany', function() {
before(function defineProductAndCategoryModels() { before(function defineProductAndCategoryModels() {
var todoList = app.registry.createModel( const todoList = app.registry.createModel(
'todoList', 'todoList',
{name: 'string'}, {name: 'string'},
{plural: 'todo-lists'} {plural: 'todo-lists'}
); );
app.model(todoList, {dataSource: 'db'}); app.model(todoList, {dataSource: 'db'});
var todoItem = app.registry.createModel( const todoItem = app.registry.createModel(
'todoItem', 'todoItem',
{content: 'string'}, {forceId: false} {content: 'string'}, {forceId: false}
); );
@ -917,7 +917,7 @@ describe('relations - integration', function() {
}); });
before(function createTodoList(done) { before(function createTodoList(done) {
var test = this; const test = this;
app.models.todoList.create({name: 'List A'}, app.models.todoList.create({name: 'List A'},
function(err, list) { function(err, list) {
if (err) return done(err); if (err) return done(err);
@ -934,7 +934,7 @@ describe('relations - integration', function() {
}); });
it('includes the embedded models', function(done) { it('includes the embedded models', function(done) {
var url = '/api/todo-lists/' + this.todoList.id; const url = '/api/todo-lists/' + this.todoList.id;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -951,7 +951,7 @@ describe('relations - integration', function() {
}); });
it('returns the embedded models', function(done) { it('returns the embedded models', function(done) {
var url = '/api/todo-lists/' + this.todoList.id + '/items'; const url = '/api/todo-lists/' + this.todoList.id + '/items';
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -967,7 +967,7 @@ describe('relations - integration', function() {
}); });
it('filters the embedded models', function(done) { it('filters the embedded models', function(done) {
var url = '/api/todo-lists/' + this.todoList.id + '/items'; let url = '/api/todo-lists/' + this.todoList.id + '/items';
url += '?filter[where][id]=2'; url += '?filter[where][id]=2';
this.get(url) this.get(url)
@ -983,9 +983,9 @@ describe('relations - integration', function() {
}); });
it('creates embedded models', function(done) { it('creates embedded models', function(done) {
var url = '/api/todo-lists/' + this.todoList.id + '/items'; const url = '/api/todo-lists/' + this.todoList.id + '/items';
var expected = {content: 'Todo 3', id: 3}; const expected = {content: 'Todo 3', id: 3};
this.post(url) this.post(url)
.send({content: 'Todo 3'}) .send({content: 'Todo 3'})
@ -997,7 +997,7 @@ describe('relations - integration', function() {
}); });
it('includes the created embedded model', function(done) { it('includes the created embedded model', function(done) {
var url = '/api/todo-lists/' + this.todoList.id + '/items'; const url = '/api/todo-lists/' + this.todoList.id + '/items';
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1014,7 +1014,7 @@ describe('relations - integration', function() {
}); });
it('returns an embedded model by (internal) id', function(done) { it('returns an embedded model by (internal) id', function(done) {
var url = '/api/todo-lists/' + this.todoList.id + '/items/3'; const url = '/api/todo-lists/' + this.todoList.id + '/items/3';
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1029,8 +1029,8 @@ describe('relations - integration', function() {
}); });
it('removes an embedded model', function(done) { it('removes an embedded model', function(done) {
var expectedProduct = this.product; const expectedProduct = this.product;
var url = '/api/todo-lists/' + this.todoList.id + '/items/2'; const url = '/api/todo-lists/' + this.todoList.id + '/items/2';
this.del(url) this.del(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1039,7 +1039,7 @@ describe('relations - integration', function() {
}); });
it('returns the embedded models - verify', function(done) { it('returns the embedded models - verify', function(done) {
var url = '/api/todo-lists/' + this.todoList.id + '/items'; const url = '/api/todo-lists/' + this.todoList.id + '/items';
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1055,7 +1055,7 @@ describe('relations - integration', function() {
}); });
it('returns a 404 response when embedded model is not found', function(done) { it('returns a 404 response when embedded model is not found', function(done) {
var url = '/api/todo-lists/' + this.todoList.id + '/items/2'; const url = '/api/todo-lists/' + this.todoList.id + '/items/2';
this.get(url).expect(404, function(err, res) { this.get(url).expect(404, function(err, res) {
if (err) return done(err); if (err) return done(err);
@ -1068,7 +1068,7 @@ describe('relations - integration', function() {
}); });
it.skip('checks if an embedded model exists - ok', function(done) { it.skip('checks if an embedded model exists - ok', function(done) {
var url = '/api/todo-lists/' + this.todoList.id + '/items/3'; const url = '/api/todo-lists/' + this.todoList.id + '/items/3';
this.head(url) this.head(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1077,7 +1077,7 @@ describe('relations - integration', function() {
}); });
it.skip('checks if an embedded model exists - fail', function(done) { it.skip('checks if an embedded model exists - fail', function(done) {
var url = '/api/todo-lists/' + this.todoList.id + '/items/2'; const url = '/api/todo-lists/' + this.todoList.id + '/items/2';
this.head(url) this.head(url)
.expect(404, function(err, res) { .expect(404, function(err, res) {
@ -1088,19 +1088,19 @@ describe('relations - integration', function() {
describe('referencesMany', function() { describe('referencesMany', function() {
before(function defineProductAndCategoryModels() { before(function defineProductAndCategoryModels() {
var recipe = app.registry.createModel( const recipe = app.registry.createModel(
'recipe', 'recipe',
{name: 'string'} {name: 'string'}
); );
app.model(recipe, {dataSource: 'db'}); app.model(recipe, {dataSource: 'db'});
var ingredient = app.registry.createModel( const ingredient = app.registry.createModel(
'ingredient', 'ingredient',
{name: 'string'} {name: 'string'}
); );
app.model(ingredient, {dataSource: 'db'}); app.model(ingredient, {dataSource: 'db'});
var photo = app.registry.createModel( const photo = app.registry.createModel(
'photo', 'photo',
{name: 'string'} {name: 'string'}
); );
@ -1114,7 +1114,7 @@ describe('relations - integration', function() {
}); });
before(function createRecipe(done) { before(function createRecipe(done) {
var test = this; const test = this;
app.models.recipe.create({name: 'Recipe'}, app.models.recipe.create({name: 'Recipe'},
function(err, recipe) { function(err, recipe) {
if (err) return done(err); if (err) return done(err);
@ -1130,7 +1130,7 @@ describe('relations - integration', function() {
}); });
before(function createIngredient(done) { before(function createIngredient(done) {
var test = this; const test = this;
app.models.ingredient.create({name: 'Sugar'}, function(err, ing) { app.models.ingredient.create({name: 'Sugar'}, function(err, ing) {
test.ingredient2 = ing.id; test.ingredient2 = ing.id;
@ -1139,7 +1139,7 @@ describe('relations - integration', function() {
}); });
after(function(done) { after(function(done) {
var app = this.app; const app = this.app;
app.models.recipe.destroyAll(function() { app.models.recipe.destroyAll(function() {
app.models.ingredient.destroyAll(function() { app.models.ingredient.destroyAll(function() {
app.models.photo.destroyAll(done); app.models.photo.destroyAll(done);
@ -1148,8 +1148,8 @@ describe('relations - integration', function() {
}); });
it('keeps an array of ids', function(done) { it('keeps an array of ids', function(done) {
var url = '/api/recipes/' + this.recipe.id; const url = '/api/recipes/' + this.recipe.id;
var test = this; const test = this;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1163,8 +1163,8 @@ describe('relations - integration', function() {
}); });
it('creates referenced models', function(done) { it('creates referenced models', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/ingredients'; const url = '/api/recipes/' + this.recipe.id + '/ingredients';
var test = this; const test = this;
this.post(url) this.post(url)
.send({name: 'Butter'}) .send({name: 'Butter'})
@ -1177,8 +1177,8 @@ describe('relations - integration', function() {
}); });
it('has created models', function(done) { it('has created models', function(done) {
var url = '/api/ingredients'; const url = '/api/ingredients';
var test = this; const test = this;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1195,8 +1195,8 @@ describe('relations - integration', function() {
}); });
it('returns the referenced models', function(done) { it('returns the referenced models', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/ingredients'; const url = '/api/recipes/' + this.recipe.id + '/ingredients';
var test = this; const test = this;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1212,9 +1212,9 @@ describe('relations - integration', function() {
}); });
it('filters the referenced models', function(done) { it('filters the referenced models', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/ingredients'; let url = '/api/recipes/' + this.recipe.id + '/ingredients';
url += '?filter[where][name]=Butter'; url += '?filter[where][name]=Butter';
var test = this; const test = this;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1229,9 +1229,9 @@ describe('relations - integration', function() {
}); });
it('includes the referenced models', function(done) { it('includes the referenced models', function(done) {
var url = '/api/recipes/findOne?filter[where][id]=' + this.recipe.id; let url = '/api/recipes/findOne?filter[where][id]=' + this.recipe.id;
url += '&filter[include]=ingredients'; url += '&filter[include]=ingredients';
var test = this; const test = this;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1250,9 +1250,9 @@ describe('relations - integration', function() {
}); });
it('returns a referenced model by id', function(done) { it('returns a referenced model by id', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/ingredients/'; let url = '/api/recipes/' + this.recipe.id + '/ingredients/';
url += this.ingredient3; url += this.ingredient3;
var test = this; const test = this;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1267,10 +1267,10 @@ describe('relations - integration', function() {
}); });
it('keeps an array of ids - verify', function(done) { it('keeps an array of ids - verify', function(done) {
var url = '/api/recipes/' + this.recipe.id; const url = '/api/recipes/' + this.recipe.id;
var test = this; const test = this;
var expected = [test.ingredient1, test.ingredient3]; const expected = [test.ingredient1, test.ingredient3];
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1284,8 +1284,8 @@ describe('relations - integration', function() {
}); });
it('destroys a referenced model', function(done) { it('destroys a referenced model', function(done) {
var expectedProduct = this.product; const expectedProduct = this.product;
var url = '/api/recipes/' + this.recipe.id + '/ingredients/'; let url = '/api/recipes/' + this.recipe.id + '/ingredients/';
url += this.ingredient3; url += this.ingredient3;
this.del(url) this.del(url)
@ -1295,8 +1295,8 @@ describe('relations - integration', function() {
}); });
it('has destroyed a referenced model', function(done) { it('has destroyed a referenced model', function(done) {
var url = '/api/ingredients'; const url = '/api/ingredients';
var test = this; const test = this;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1312,8 +1312,8 @@ describe('relations - integration', function() {
}); });
it('returns the referenced models without the deleted one', function(done) { it('returns the referenced models without the deleted one', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/ingredients'; const url = '/api/recipes/' + this.recipe.id + '/ingredients';
var test = this; const test = this;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1328,9 +1328,9 @@ describe('relations - integration', function() {
}); });
it('creates/links a reference by id', function(done) { it('creates/links a reference by id', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/ingredients'; let url = '/api/recipes/' + this.recipe.id + '/ingredients';
url += '/rel/' + this.ingredient2; url += '/rel/' + this.ingredient2;
var test = this; const test = this;
this.put(url) this.put(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1343,8 +1343,8 @@ describe('relations - integration', function() {
}); });
it('returns the referenced models - verify', function(done) { it('returns the referenced models - verify', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/ingredients'; const url = '/api/recipes/' + this.recipe.id + '/ingredients';
var test = this; const test = this;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1360,9 +1360,9 @@ describe('relations - integration', function() {
}); });
it('removes/unlinks a reference by id', function(done) { it('removes/unlinks a reference by id', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/ingredients'; let url = '/api/recipes/' + this.recipe.id + '/ingredients';
url += '/rel/' + this.ingredient1; url += '/rel/' + this.ingredient1;
var test = this; const test = this;
this.del(url) this.del(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1371,8 +1371,8 @@ describe('relations - integration', function() {
}); });
it('returns the referenced models without the unlinked one', function(done) { it('returns the referenced models without the unlinked one', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/ingredients'; const url = '/api/recipes/' + this.recipe.id + '/ingredients';
var test = this; const test = this;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1387,8 +1387,8 @@ describe('relations - integration', function() {
}); });
it('has not destroyed an unlinked model', function(done) { it('has not destroyed an unlinked model', function(done) {
var url = '/api/ingredients'; const url = '/api/ingredients';
var test = this; const test = this;
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1404,7 +1404,7 @@ describe('relations - integration', function() {
}); });
it('uses a custom relation path', function(done) { it('uses a custom relation path', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/image'; const url = '/api/recipes/' + this.recipe.id + '/image';
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1418,7 +1418,7 @@ describe('relations - integration', function() {
}); });
it.skip('checks if a referenced model exists - ok', function(done) { it.skip('checks if a referenced model exists - ok', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/ingredients/'; let url = '/api/recipes/' + this.recipe.id + '/ingredients/';
url += this.ingredient1; url += this.ingredient1;
this.head(url) this.head(url)
@ -1428,7 +1428,7 @@ describe('relations - integration', function() {
}); });
it.skip('checks if an referenced model exists - fail', function(done) { it.skip('checks if an referenced model exists - fail', function(done) {
var url = '/api/recipes/' + this.recipe.id + '/ingredients/'; let url = '/api/recipes/' + this.recipe.id + '/ingredients/';
url += this.ingredient3; url += this.ingredient3;
this.head(url) this.head(url)
@ -1442,35 +1442,35 @@ describe('relations - integration', function() {
let accessOptions; let accessOptions;
before(function defineModels() { before(function defineModels() {
var Book = app.registry.createModel( const Book = app.registry.createModel(
'Book', 'Book',
{name: 'string'}, {name: 'string'},
{plural: 'books'} {plural: 'books'}
); );
app.model(Book, {dataSource: 'db'}); app.model(Book, {dataSource: 'db'});
var Page = app.registry.createModel( const Page = app.registry.createModel(
'Page', 'Page',
{name: 'string'}, {name: 'string'},
{plural: 'pages'} {plural: 'pages'}
); );
app.model(Page, {dataSource: 'db'}); app.model(Page, {dataSource: 'db'});
var Image = app.registry.createModel( const Image = app.registry.createModel(
'Image', 'Image',
{name: 'string'}, {name: 'string'},
{plural: 'images'} {plural: 'images'}
); );
app.model(Image, {dataSource: 'db'}); app.model(Image, {dataSource: 'db'});
var Note = app.registry.createModel( const Note = app.registry.createModel(
'Note', 'Note',
{text: 'string'}, {text: 'string'},
{plural: 'notes'} {plural: 'notes'}
); );
app.model(Note, {dataSource: 'db'}); app.model(Note, {dataSource: 'db'});
var Chapter = app.registry.createModel( const Chapter = app.registry.createModel(
'Chapter', 'Chapter',
{name: 'string'}, {name: 'string'},
{plural: 'chapters'} {plural: 'chapters'}
@ -1523,7 +1523,7 @@ describe('relations - integration', function() {
}); });
before(function createBook(done) { before(function createBook(done) {
var test = this; const test = this;
app.models.Book.create({name: 'Book 1'}, app.models.Book.create({name: 'Book 1'},
function(err, book) { function(err, book) {
if (err) return done(err); if (err) return done(err);
@ -1545,7 +1545,7 @@ describe('relations - integration', function() {
}); });
before(function createChapters(done) { before(function createChapters(done) {
var test = this; const test = this;
test.book.chapters.create({name: 'Chapter 1'}, test.book.chapters.create({name: 'Chapter 1'},
function(err, chapter) { function(err, chapter) {
if (err) return done(err); if (err) return done(err);
@ -1560,7 +1560,7 @@ describe('relations - integration', function() {
}); });
before(function createCover(done) { before(function createCover(done) {
var test = this; const test = this;
app.models.Image.create({name: 'Cover 1', book: test.book}, app.models.Image.create({name: 'Cover 1', book: test.book},
function(err, image) { function(err, image) {
if (err) return done(err); if (err) return done(err);
@ -1572,7 +1572,7 @@ describe('relations - integration', function() {
}); });
it('has regular relationship routes - pages', function(done) { it('has regular relationship routes - pages', function(done) {
var test = this; const test = this;
this.get('/api/books/' + test.book.id + '/pages') this.get('/api/books/' + test.book.id + '/pages')
.expect(200, function(err, res) { .expect(200, function(err, res) {
if (err) return done(err); if (err) return done(err);
@ -1586,7 +1586,7 @@ describe('relations - integration', function() {
}); });
it('has regular relationship routes - notes', function(done) { it('has regular relationship routes - notes', function(done) {
var test = this; const test = this;
this.get('/api/pages/' + test.page.id + '/notes/' + test.note.id) this.get('/api/pages/' + test.page.id + '/notes/' + test.note.id)
.expect(200, function(err, res) { .expect(200, function(err, res) {
if (err) return done(err); if (err) return done(err);
@ -1601,13 +1601,13 @@ describe('relations - integration', function() {
}); });
it('has a basic error handler', function(done) { it('has a basic error handler', function(done) {
var test = this; const test = this;
this.get('/api/books/unknown/pages/' + test.page.id + '/notes') this.get('/api/books/unknown/pages/' + test.page.id + '/notes')
.expect(404, function(err, res) { .expect(404, function(err, res) {
if (err) return done(err); if (err) return done(err);
expect(res.body.error).to.be.an('object'); expect(res.body.error).to.be.an('object');
var expected = 'could not find a model with id unknown'; const expected = 'could not find a model with id unknown';
expect(res.body.error.message).to.equal(expected); expect(res.body.error.message).to.equal(expected);
expect(res.body.error.code).to.be.equal('MODEL_NOT_FOUND'); expect(res.body.error.code).to.be.equal('MODEL_NOT_FOUND');
@ -1616,7 +1616,7 @@ describe('relations - integration', function() {
}); });
it('enables nested relationship routes - belongsTo find', function(done) { it('enables nested relationship routes - belongsTo find', function(done) {
var test = this; const test = this;
this.get('/api/images/' + test.image.id + '/book/pages') this.get('/api/images/' + test.image.id + '/book/pages')
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
@ -1630,7 +1630,7 @@ describe('relations - integration', function() {
}); });
it('enables nested relationship routes - belongsTo findById', function(done) { it('enables nested relationship routes - belongsTo findById', function(done) {
var test = this; const test = this;
this.get('/api/images/' + test.image.id + '/book/pages/' + test.page.id) this.get('/api/images/' + test.image.id + '/book/pages/' + test.page.id)
.expect(200) .expect(200)
.end(function(err, res) { .end(function(err, res) {
@ -1644,7 +1644,7 @@ describe('relations - integration', function() {
}); });
it('enables nested relationship routes - hasMany find', function(done) { it('enables nested relationship routes - hasMany find', function(done) {
var test = this; const test = this;
this.get('/api/books/' + test.book.id + '/pages/' + test.page.id + '/notes') this.get('/api/books/' + test.book.id + '/pages/' + test.page.id + '/notes')
.expect(200, function(err, res) { .expect(200, function(err, res) {
if (err) return done(err); if (err) return done(err);
@ -1658,7 +1658,7 @@ describe('relations - integration', function() {
}); });
it('enables nested relationship routes - hasMany findById', function(done) { it('enables nested relationship routes - hasMany findById', function(done) {
var test = this; const test = this;
this.get('/api/books/' + test.book.id + '/pages/' + test.page.id + '/notes/' + test.note.id) this.get('/api/books/' + test.book.id + '/pages/' + test.page.id + '/notes/' + test.note.id)
.expect(200, function(err, res) { .expect(200, function(err, res) {
if (err) return done(err); if (err) return done(err);
@ -1681,13 +1681,13 @@ describe('relations - integration', function() {
}); });
it('should nest remote hooks of ModelTo - hasMany findById', function(done) { it('should nest remote hooks of ModelTo - hasMany findById', function(done) {
var test = this; const test = this;
this.get('/api/books/' + test.book.id + '/chapters/' + test.chapter.id + '/notes/' + test.cnote.id) this.get('/api/books/' + test.book.id + '/chapters/' + test.chapter.id + '/notes/' + test.cnote.id)
.expect(200, function(err, res) { .expect(200, function(err, res) {
if (err) return done(err); if (err) return done(err);
expect(res.headers['x-before']).to.empty(); expect(res.headers['x-before']).to.be.undefined();
expect(res.headers['x-after']).to.empty(); expect(res.headers['x-after']).to.be.undefined();
done(); done();
}); });
@ -1696,7 +1696,7 @@ describe('relations - integration', function() {
it('should have proper http.path for remoting', function() { it('should have proper http.path for remoting', function() {
[app.models.Book, app.models.Image].forEach(function(Model) { [app.models.Book, app.models.Image].forEach(function(Model) {
Model.sharedClass.methods().forEach(function(method) { Model.sharedClass.methods().forEach(function(method) {
var http = Array.isArray(method.http) ? method.http : [method.http]; const http = Array.isArray(method.http) ? method.http : [method.http];
http.forEach(function(opt) { http.forEach(function(opt) {
// destroyAll has been shared but missing http property // destroyAll has been shared but missing http property
if (opt.path === undefined) return; if (opt.path === undefined) return;
@ -1708,7 +1708,7 @@ describe('relations - integration', function() {
}); });
it('should catch error if nested function throws', function(done) { it('should catch error if nested function throws', function(done) {
var test = this; const test = this;
this.get('/api/books/' + test.book.id + '/pages/' + this.page.id + '/throws') this.get('/api/books/' + test.book.id + '/pages/' + this.page.id + '/throws')
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
@ -1725,10 +1725,10 @@ describe('relations - integration', function() {
}); });
describe('hasOne', function() { describe('hasOne', function() {
var cust; let cust;
before(function createCustomer(done) { before(function createCustomer(done) {
var test = this; const test = this;
app.models.customer.create({name: 'John'}, function(err, c) { app.models.customer.create({name: 'John'}, function(err, c) {
if (err) return done(err); if (err) return done(err);
@ -1739,7 +1739,7 @@ describe('relations - integration', function() {
}); });
after(function(done) { after(function(done) {
var self = this; const self = this;
this.app.models.customer.destroyAll(function(err) { this.app.models.customer.destroyAll(function(err) {
if (err) return done(err); if (err) return done(err);
@ -1748,7 +1748,7 @@ describe('relations - integration', function() {
}); });
it('should create the referenced model', function(done) { it('should create the referenced model', function(done) {
var url = '/api/customers/' + cust.id + '/profile'; const url = '/api/customers/' + cust.id + '/profile';
this.post(url) this.post(url)
.send({points: 10}) .send({points: 10})
@ -1763,7 +1763,7 @@ describe('relations - integration', function() {
}); });
it('should find the referenced model', function(done) { it('should find the referenced model', function(done) {
var url = '/api/customers/' + cust.id + '/profile'; const url = '/api/customers/' + cust.id + '/profile';
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
if (err) return done(err); if (err) return done(err);
@ -1776,7 +1776,7 @@ describe('relations - integration', function() {
}); });
it('should not create the referenced model twice', function(done) { it('should not create the referenced model twice', function(done) {
var url = '/api/customers/' + cust.id + '/profile'; const url = '/api/customers/' + cust.id + '/profile';
this.post(url) this.post(url)
.send({points: 20}) .send({points: 20})
.expect(500, function(err, res) { .expect(500, function(err, res) {
@ -1785,7 +1785,7 @@ describe('relations - integration', function() {
}); });
it('should update the referenced model', function(done) { it('should update the referenced model', function(done) {
var url = '/api/customers/' + cust.id + '/profile'; const url = '/api/customers/' + cust.id + '/profile';
this.put(url) this.put(url)
.send({points: 100}) .send({points: 100})
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -1799,7 +1799,7 @@ describe('relations - integration', function() {
}); });
it('should delete the referenced model', function(done) { it('should delete the referenced model', function(done) {
var url = '/api/customers/' + cust.id + '/profile'; const url = '/api/customers/' + cust.id + '/profile';
this.del(url) this.del(url)
.expect(204, function(err, res) { .expect(204, function(err, res) {
done(err); done(err);
@ -1807,7 +1807,7 @@ describe('relations - integration', function() {
}); });
it('should not find the referenced model', function(done) { it('should not find the referenced model', function(done) {
var url = '/api/customers/' + cust.id + '/profile'; const url = '/api/customers/' + cust.id + '/profile';
this.get(url) this.get(url)
.expect(404, function(err, res) { .expect(404, function(err, res) {
done(err); done(err);

View File

@ -4,18 +4,18 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var loopback = require('../'); const loopback = require('../');
var defineModelTestsWithDataSource = require('./util/model-tests'); const defineModelTestsWithDataSource = require('./util/model-tests');
describe('RemoteConnector', function() { describe('RemoteConnector', function() {
this.timeout(10000); this.timeout(10000);
var remoteApp, remote; let remoteApp, remote;
defineModelTestsWithDataSource({ defineModelTestsWithDataSource({
beforeEach: function(done) { beforeEach: function(done) {
var test = this; const test = this;
remoteApp = loopback(); remoteApp = loopback();
remoteApp.set('remoting', { remoteApp.set('remoting', {
errorHandler: {debug: true, log: false}, errorHandler: {debug: true, log: false},
@ -40,7 +40,7 @@ describe('RemoteConnector', function() {
enableRemoteReplication: true, enableRemoteReplication: true,
onDefine: function(Model) { onDefine: function(Model) {
var ServerModel = Model.extend('Server' + Model.modelName, {}, { const ServerModel = Model.extend('Server' + Model.modelName, {}, {
plural: Model.pluralModelName, plural: Model.pluralModelName,
// This is the model running on the server & attached to a real // This is the model running on the server & attached to a real
// datasource, that's the place where to keep track of changes // datasource, that's the place where to keep track of changes
@ -54,13 +54,13 @@ describe('RemoteConnector', function() {
}); });
beforeEach(function(done) { beforeEach(function(done) {
var test = this; const test = this;
remoteApp = this.remoteApp = loopback(); remoteApp = this.remoteApp = loopback();
remoteApp.set('remoting', { remoteApp.set('remoting', {
types: {warnWhenOverridingType: false}, types: {warnWhenOverridingType: false},
}); });
remoteApp.use(loopback.rest()); remoteApp.use(loopback.rest());
var ServerModel = this.ServerModel = loopback.PersistedModel.extend('TestModel'); const ServerModel = this.ServerModel = loopback.PersistedModel.extend('TestModel');
remoteApp.model(ServerModel); remoteApp.model(ServerModel);
@ -76,11 +76,11 @@ describe('RemoteConnector', function() {
}); });
it('should support the save method', function(done) { it('should support the save method', function(done) {
var calledServerCreate = false; let calledServerCreate = false;
var RemoteModel = loopback.PersistedModel.extend('TestModel'); const RemoteModel = loopback.PersistedModel.extend('TestModel');
RemoteModel.attachTo(this.remote); RemoteModel.attachTo(this.remote);
var ServerModel = this.ServerModel; const ServerModel = this.ServerModel;
ServerModel.create = function(data, options, cb) { ServerModel.create = function(data, options, cb) {
calledServerCreate = true; calledServerCreate = true;
@ -90,7 +90,7 @@ describe('RemoteConnector', function() {
ServerModel.setupRemoting(); ServerModel.setupRemoting();
var m = new RemoteModel({foo: 'bar'}); const m = new RemoteModel({foo: 'bar'});
m.save(function(err, inst) { m.save(function(err, inst) {
if (err) return done(err); if (err) return done(err);

View File

@ -4,17 +4,17 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var loopback = require('../'); const loopback = require('../');
var request = require('supertest'); const request = require('supertest');
describe('remoting coercion', function() { describe('remoting coercion', function() {
it('should coerce arguments based on the type', function(done) { it('should coerce arguments based on the type', function(done) {
var called = false; let called = false;
var app = loopback(); const app = loopback();
app.use(loopback.rest()); app.use(loopback.rest());
var TestModel = app.registry.createModel('TestModel', const TestModel = app.registry.createModel('TestModel',
{}, {},
{base: 'Model'}); {base: 'Model'});
app.model(TestModel, {public: true}); app.model(TestModel, {public: true});

View File

@ -4,13 +4,13 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../'); const loopback = require('../');
var lt = require('./helpers/loopback-testing-helper'); const lt = require('./helpers/loopback-testing-helper');
var path = require('path'); const path = require('path');
var SIMPLE_APP = path.join(__dirname, 'fixtures', 'simple-integration-app'); const SIMPLE_APP = path.join(__dirname, 'fixtures', 'simple-integration-app');
var app = require(path.join(SIMPLE_APP, 'server/server.js')); const app = require(path.join(SIMPLE_APP, 'server/server.js'));
var assert = require('assert'); const assert = require('assert');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
describe('remoting - integration', function() { describe('remoting - integration', function() {
lt.beforeEach.withApp(app); lt.beforeEach.withApp(app);
@ -22,21 +22,21 @@ describe('remoting - integration', function() {
describe('app.remotes.options', function() { describe('app.remotes.options', function() {
it('should load remoting options', function() { it('should load remoting options', function() {
var remotes = app.remotes(); const remotes = app.remotes();
assert.deepEqual(remotes.options, {'json': {'limit': '1kb', 'strict': false}, assert.deepEqual(remotes.options, {'json': {'limit': '1kb', 'strict': false},
'urlencoded': {'limit': '8kb', 'extended': true}, 'urlencoded': {'limit': '8kb', 'extended': true},
'errorHandler': {'debug': true, log: false}}); 'errorHandler': {'debug': true, log: false}});
}); });
it('rest handler', function() { it('rest handler', function() {
var handler = app.handler('rest'); const handler = app.handler('rest');
assert(handler); assert(handler);
}); });
it('should accept request that has entity below 1kb', function(done) { it('should accept request that has entity below 1kb', function(done) {
// Build an object that is smaller than 1kb // Build an object that is smaller than 1kb
var name = ''; let name = '';
for (var i = 0; i < 256; i++) { for (let i = 0; i < 256; i++) {
name += '11'; name += '11';
} }
this.http = this.post('/api/stores'); this.http = this.post('/api/stores');
@ -55,8 +55,8 @@ describe('remoting - integration', function() {
it('should reject request that has entity beyond 1kb', function(done) { it('should reject request that has entity beyond 1kb', function(done) {
// Build an object that is larger than 1kb // Build an object that is larger than 1kb
var name = ''; let name = '';
for (var i = 0; i < 2048; i++) { for (let i = 0; i < 2048; i++) {
name += '11111111111'; name += '11111111111';
} }
this.http = this.post('/api/stores'); this.http = this.post('/api/stores');
@ -79,10 +79,10 @@ describe('remoting - integration', function() {
it('has expected remote methods with default model.settings.replaceOnPUT' + it('has expected remote methods with default model.settings.replaceOnPUT' +
'set to true (3.x)', 'set to true (3.x)',
function() { function() {
var storeClass = findClass('store'); const storeClass = findClass('store');
var methods = getFormattedMethodsExcludingRelations(storeClass.methods); const methods = getFormattedMethodsExcludingRelations(storeClass.methods);
var expectedMethods = [ const expectedMethods = [
'create(data:object:store):store POST /stores', 'create(data:object:store):store POST /stores',
'patchOrCreate(data:object:store):store PATCH /stores', 'patchOrCreate(data:object:store):store PATCH /stores',
'replaceOrCreate(data:object:store):store PUT /stores', 'replaceOrCreate(data:object:store):store PUT /stores',
@ -106,10 +106,10 @@ describe('remoting - integration', function() {
}); });
it('has expected remote methods for scopes', function() { it('has expected remote methods for scopes', function() {
var storeClass = findClass('store'); const storeClass = findClass('store');
var methods = getFormattedScopeMethods(storeClass.methods); const methods = getFormattedScopeMethods(storeClass.methods);
var expectedMethods = [ const expectedMethods = [
'__get__superStores(filter:object):store GET /stores/superStores', '__get__superStores(filter:object):store GET /stores/superStores',
'__create__superStores(data:object:store):store POST /stores/superStores', '__create__superStores(data:object:store):store POST /stores/superStores',
'__delete__superStores() DELETE /stores/superStores', '__delete__superStores() DELETE /stores/superStores',
@ -121,10 +121,10 @@ describe('remoting - integration', function() {
it('should have correct signatures for belongsTo methods', it('should have correct signatures for belongsTo methods',
function() { function() {
var widgetClass = findClass('widget'); const widgetClass = findClass('widget');
var methods = getFormattedPrototypeMethods(widgetClass.methods); const methods = getFormattedPrototypeMethods(widgetClass.methods);
var expectedMethods = [ const expectedMethods = [
'prototype.__get__store(refresh:boolean):store ' + 'prototype.__get__store(refresh:boolean):store ' +
'GET /widgets/:id/store', 'GET /widgets/:id/store',
]; ];
@ -133,10 +133,10 @@ describe('remoting - integration', function() {
it('should have correct signatures for hasMany methods', it('should have correct signatures for hasMany methods',
function() { function() {
var storeClass = findClass('store'); const storeClass = findClass('store');
var methods = getFormattedPrototypeMethods(storeClass.methods); const methods = getFormattedPrototypeMethods(storeClass.methods);
var expectedMethods = [ const expectedMethods = [
'prototype.__findById__widgets(fk:any):widget ' + 'prototype.__findById__widgets(fk:any):widget ' +
'GET /stores/:id/widgets/:fk', 'GET /stores/:id/widgets/:fk',
'prototype.__destroyById__widgets(fk:any) ' + 'prototype.__destroyById__widgets(fk:any) ' +
@ -157,10 +157,10 @@ describe('remoting - integration', function() {
it('should have correct signatures for hasMany-through methods', it('should have correct signatures for hasMany-through methods',
function() { // jscs:disable validateIndentation function() { // jscs:disable validateIndentation
var physicianClass = findClass('physician'); const physicianClass = findClass('physician');
var methods = getFormattedPrototypeMethods(physicianClass.methods); const methods = getFormattedPrototypeMethods(physicianClass.methods);
var expectedMethods = [ const expectedMethods = [
'prototype.__findById__patients(fk:any):patient ' + 'prototype.__findById__patients(fk:any):patient ' +
'GET /physicians/:id/patients/:fk', 'GET /physicians/:id/patients/:fk',
'prototype.__destroyById__patients(fk:any) ' + 'prototype.__destroyById__patients(fk:any) ' +
@ -187,9 +187,9 @@ describe('remoting - integration', function() {
}); });
it('has upsertWithWhere remote method', function() { it('has upsertWithWhere remote method', function() {
var storeClass = findClass('store'); const storeClass = findClass('store');
var methods = getFormattedMethodsExcludingRelations(storeClass.methods); const methods = getFormattedMethodsExcludingRelations(storeClass.methods);
var expectedMethods = [ const expectedMethods = [
'upsertWithWhere(where:object,data:object:store):store POST /stores/upsertWithWhere', 'upsertWithWhere(where:object,data:object:store):store POST /stores/upsertWithWhere',
]; ];
expect(methods).to.include.members(expectedMethods); expect(methods).to.include.members(expectedMethods);
@ -198,21 +198,21 @@ describe('remoting - integration', function() {
describe('createOnlyInstance', function() { describe('createOnlyInstance', function() {
it('sets createOnlyInstance to true if id is generated and forceId is not set to false', it('sets createOnlyInstance to true if id is generated and forceId is not set to false',
function() { function() {
var storeClass = findClass('store'); const storeClass = findClass('store');
var createMethod = getCreateMethod(storeClass.methods); const createMethod = getCreateMethod(storeClass.methods);
assert(createMethod.accepts[0].createOnlyInstance === true); assert(createMethod.accepts[0].createOnlyInstance === true);
}); });
it('sets createOnlyInstance to false if forceId is set to false in the model', function() { it('sets createOnlyInstance to false if forceId is set to false in the model', function() {
var customerClass = findClass('customerforceidfalse'); const customerClass = findClass('customerforceidfalse');
var createMethod = getCreateMethod(customerClass.methods); const createMethod = getCreateMethod(customerClass.methods);
assert(createMethod.accepts[0].createOnlyInstance === false); assert(createMethod.accepts[0].createOnlyInstance === false);
}); });
it('sets createOnlyInstance based on target model for scoped or related methods', it('sets createOnlyInstance based on target model for scoped or related methods',
function() { function() {
var userClass = findClass('user'); const userClass = findClass('user');
var createMethod = userClass.methods.find(function(m) { const createMethod = userClass.methods.find(function(m) {
return (m.name === 'prototype.__create__accessTokens'); return (m.name === 'prototype.__create__accessTokens');
}); });
assert(createMethod.accepts[0].createOnlyInstance === false); assert(createMethod.accepts[0].createOnlyInstance === false);
@ -229,10 +229,10 @@ describe('With model.settings.replaceOnPUT false', function() {
it('should have expected remote methods', it('should have expected remote methods',
function() { function() {
var storeClass = findClass('storeWithReplaceOnPUTfalse'); const storeClass = findClass('storeWithReplaceOnPUTfalse');
var methods = getFormattedMethodsExcludingRelations(storeClass.methods); const methods = getFormattedMethodsExcludingRelations(storeClass.methods);
var expectedMethods = [ const expectedMethods = [
'create(data:object:storeWithReplaceOnPUTfalse):storeWithReplaceOnPUTfalse POST /stores-updating', 'create(data:object:storeWithReplaceOnPUTfalse):storeWithReplaceOnPUTfalse POST /stores-updating',
'patchOrCreate(data:object:storeWithReplaceOnPUTfalse):storeWithReplaceOnPUTfalse PUT /stores-updating', 'patchOrCreate(data:object:storeWithReplaceOnPUTfalse):storeWithReplaceOnPUTfalse PUT /stores-updating',
'patchOrCreate(data:object:storeWithReplaceOnPUTfalse):storeWithReplaceOnPUTfalse PATCH /stores-updating', 'patchOrCreate(data:object:storeWithReplaceOnPUTfalse):storeWithReplaceOnPUTfalse PATCH /stores-updating',
@ -266,10 +266,10 @@ describe('With model.settings.replaceOnPUT true', function() {
it('should have expected remote methods', it('should have expected remote methods',
function() { function() {
var storeClass = findClass('storeWithReplaceOnPUTtrue'); const storeClass = findClass('storeWithReplaceOnPUTtrue');
var methods = getFormattedMethodsExcludingRelations(storeClass.methods); const methods = getFormattedMethodsExcludingRelations(storeClass.methods);
var expectedMethods = [ const expectedMethods = [
'patchOrCreate(data:object:storeWithReplaceOnPUTtrue):storeWithReplaceOnPUTtrue PATCH /stores-replacing', 'patchOrCreate(data:object:storeWithReplaceOnPUTtrue):storeWithReplaceOnPUTtrue PATCH /stores-replacing',
'replaceOrCreate(data:object:storeWithReplaceOnPUTtrue):storeWithReplaceOnPUTtrue POST /stores-replacing/replaceOrCreate', 'replaceOrCreate(data:object:storeWithReplaceOnPUTtrue):storeWithReplaceOnPUTtrue POST /stores-replacing/replaceOrCreate',
'replaceOrCreate(data:object:storeWithReplaceOnPUTtrue):storeWithReplaceOnPUTtrue PUT /stores-replacing', 'replaceOrCreate(data:object:storeWithReplaceOnPUTtrue):storeWithReplaceOnPUTtrue PUT /stores-replacing',
@ -283,11 +283,11 @@ describe('With model.settings.replaceOnPUT true', function() {
}); });
function formatReturns(m) { function formatReturns(m) {
var returns = m.returns; const returns = m.returns;
if (!returns || returns.length === 0) { if (!returns || returns.length === 0) {
return ''; return '';
} }
var type = returns[0].type; let type = returns[0].type;
// handle anonymous type definitions, e.g // handle anonymous type definitions, e.g
// { arg: 'info', type: { count: 'number' } } // { arg: 'info', type: { count: 'number' } }
@ -298,9 +298,9 @@ function formatReturns(m) {
} }
function formatMethod(m) { function formatMethod(m) {
var arr = []; const arr = [];
var endpoints = m.getEndpoints(); const endpoints = m.getEndpoints();
for (var i = 0; i < endpoints.length; i++) { for (let i = 0; i < endpoints.length; i++) {
arr.push([ arr.push([
m.name, m.name,
'(', '(',

View File

@ -4,25 +4,25 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var async = require('async'); const async = require('async');
var debug = require('debug')('test'); const debug = require('debug')('test');
var extend = require('util')._extend; const extend = require('util')._extend;
var loopback = require('../'); const loopback = require('../');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var supertest = require('supertest'); const supertest = require('supertest');
describe('Replication over REST', function() { describe('Replication over REST', function() {
this.timeout(10000); this.timeout(10000);
var ALICE = {id: 'a', username: 'alice', email: 'a@t.io', password: 'p'}; const ALICE = {id: 'a', username: 'alice', email: 'a@t.io', password: 'p'};
var PETER = {id: 'p', username: 'peter', email: 'p@t.io', password: 'p'}; const PETER = {id: 'p', username: 'peter', email: 'p@t.io', password: 'p'};
var EMERY = {id: 'e', username: 'emery', email: 'e@t.io', password: 'p'}; const EMERY = {id: 'e', username: 'emery', email: 'e@t.io', password: 'p'};
/* eslint-disable one-var */ /* eslint-disable one-var */
var serverApp, serverUrl, ServerUser, ServerCar, serverCars; let serverApp, serverUrl, ServerUser, ServerCar, serverCars;
var aliceId, peterId, aliceToken, peterToken, emeryToken, request; let aliceId, peterId, aliceToken, peterToken, emeryToken, request;
var clientApp, LocalUser, LocalCar, RemoteUser, RemoteCar, clientCars; let clientApp, LocalUser, LocalCar, RemoteUser, RemoteCar, clientCars;
var conflictedCarId; let conflictedCarId;
/* eslint-enable one-var */ /* eslint-enable one-var */
before(setupServer); before(setupServer);
@ -177,7 +177,7 @@ describe('Replication over REST', function() {
}); });
describe('conflict resolution with model-level permissions', function() { describe('conflict resolution with model-level permissions', function() {
var LocalConflict, RemoteConflict; let LocalConflict, RemoteConflict;
before(function setupConflictModels() { before(function setupConflictModels() {
LocalConflict = LocalCar.getChangeModel().Conflict; LocalConflict = LocalCar.getChangeModel().Conflict;
@ -189,7 +189,7 @@ describe('Replication over REST', function() {
describe('as anonymous user', function() { describe('as anonymous user', function() {
it('rejects resolve() on the client', function(done) { it('rejects resolve() on the client', function(done) {
// simulate replication Client->Server // simulate replication Client->Server
var conflict = new LocalConflict( const conflict = new LocalConflict(
conflictedCarId, conflictedCarId,
LocalCar, LocalCar,
RemoteCar RemoteCar
@ -199,7 +199,7 @@ describe('Replication over REST', function() {
it('rejects resolve() on the server', function(done) { it('rejects resolve() on the server', function(done) {
// simulate replication Server->Client // simulate replication Server->Client
var conflict = new RemoteConflict( const conflict = new RemoteConflict(
conflictedCarId, conflictedCarId,
RemoteCar, RemoteCar,
LocalCar LocalCar
@ -215,7 +215,7 @@ describe('Replication over REST', function() {
it('allows resolve() on the client', function(done) { it('allows resolve() on the client', function(done) {
// simulate replication Client->Server // simulate replication Client->Server
var conflict = new LocalConflict( const conflict = new LocalConflict(
conflictedCarId, conflictedCarId,
LocalCar, LocalCar,
RemoteCar RemoteCar
@ -225,7 +225,7 @@ describe('Replication over REST', function() {
it('rejects resolve() on the server', function(done) { it('rejects resolve() on the server', function(done) {
// simulate replication Server->Client // simulate replication Server->Client
var conflict = new RemoteConflict( const conflict = new RemoteConflict(
conflictedCarId, conflictedCarId,
RemoteCar, RemoteCar,
LocalCar LocalCar
@ -332,7 +332,7 @@ describe('Replication over REST', function() {
if (conflicts.length) return done(conflictError(conflicts)); if (conflicts.length) return done(conflictError(conflicts));
LocalUser.find(function(err, users) { LocalUser.find(function(err, users) {
var userNames = users.map(function(u) { return u.username; }); const userNames = users.map(function(u) { return u.username; });
expect(userNames).to.eql([ALICE.username]); expect(userNames).to.eql([ALICE.username]);
done(); done();
@ -413,11 +413,11 @@ describe('Replication over REST', function() {
} }
}); });
var USER_PROPS = { const USER_PROPS = {
id: {type: 'string', id: true}, id: {type: 'string', id: true},
}; };
var USER_OPTS = { const USER_OPTS = {
base: 'User', base: 'User',
plural: 'Users', // use the same REST path in all models plural: 'Users', // use the same REST path in all models
trackChanges: true, trackChanges: true,
@ -427,13 +427,13 @@ describe('Replication over REST', function() {
saltWorkFactor: 4, saltWorkFactor: 4,
}; };
var CAR_PROPS = { const CAR_PROPS = {
id: {type: 'string', id: true, defaultFn: 'guid'}, id: {type: 'string', id: true, defaultFn: 'guid'},
model: {type: 'string', required: true}, model: {type: 'string', required: true},
maker: {type: 'string'}, maker: {type: 'string'},
}; };
var CAR_OPTS = { const CAR_OPTS = {
base: 'PersistedModel', base: 'PersistedModel',
plural: 'Cars', // use the same REST path in all models plural: 'Cars', // use the same REST path in all models
trackChanges: true, trackChanges: true,
@ -477,7 +477,7 @@ describe('Replication over REST', function() {
// Setup a custom access-token model that is not shared // Setup a custom access-token model that is not shared
// with the client app // with the client app
var ServerToken = serverApp.registry.createModel('ServerToken', {}, { const ServerToken = serverApp.registry.createModel('ServerToken', {}, {
base: 'AccessToken', base: 'AccessToken',
relations: { relations: {
user: { user: {
@ -531,7 +531,7 @@ describe('Replication over REST', function() {
// model. This causes the in-process replication to work differently // model. This causes the in-process replication to work differently
// than client-server replication. // than client-server replication.
// As a workaround, we manually setup unique Checkpoint for ClientModel. // As a workaround, we manually setup unique Checkpoint for ClientModel.
var ClientCheckpoint = clientApp.registry.createModel({ const ClientCheckpoint = clientApp.registry.createModel({
name: 'ClientCheckpoint', name: 'ClientCheckpoint',
base: 'Checkpoint', base: 'Checkpoint',
}); });
@ -545,7 +545,7 @@ describe('Replication over REST', function() {
LocalCar.Change.Checkpoint = ClientCheckpoint; LocalCar.Change.Checkpoint = ClientCheckpoint;
clientApp.model(LocalCar, {dataSource: 'db'}); clientApp.model(LocalCar, {dataSource: 'db'});
var remoteOpts = createRemoteModelOpts(USER_OPTS); let remoteOpts = createRemoteModelOpts(USER_OPTS);
RemoteUser = clientApp.registry.createModel('RemoteUser', USER_PROPS, remoteOpts); RemoteUser = clientApp.registry.createModel('RemoteUser', USER_PROPS, remoteOpts);
clientApp.model(RemoteUser, {dataSource: 'remote'}); clientApp.model(RemoteUser, {dataSource: 'remote'});
@ -690,7 +690,7 @@ describe('Replication over REST', function() {
} }
function conflictError(conflicts) { function conflictError(conflicts) {
var err = new Error('Unexpected conflicts\n' + const err = new Error('Unexpected conflicts\n' +
conflicts.map(JSON.stringify).join('\n')); conflicts.map(JSON.stringify).join('\n'));
err.name = 'ConflictError'; err.name = 'ConflictError';
} }

View File

@ -4,26 +4,26 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var async = require('async'); const async = require('async');
var loopback = require('../'); const loopback = require('../');
var Change = loopback.Change; const Change = loopback.Change;
var defineModelTestsWithDataSource = require('./util/model-tests'); const defineModelTestsWithDataSource = require('./util/model-tests');
var PersistedModel = loopback.PersistedModel; const PersistedModel = loopback.PersistedModel;
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var debug = require('debug')('test'); const debug = require('debug')('test');
var runtime = require('./../lib/runtime'); const runtime = require('./../lib/runtime');
describe('Replication / Change APIs', function() { describe('Replication / Change APIs', function() {
this.timeout(10000); this.timeout(10000);
var dataSource, SourceModel, TargetModel, useSinceFilter; let dataSource, SourceModel, TargetModel, useSinceFilter;
var tid = 0; // per-test unique id used e.g. to build unique model names let tid = 0; // per-test unique id used e.g. to build unique model names
beforeEach(function() { beforeEach(function() {
tid++; tid++;
useSinceFilter = false; useSinceFilter = false;
var test = this; const test = this;
dataSource = this.dataSource = loopback.createDataSource({ dataSource = this.dataSource = loopback.createDataSource({
connector: loopback.Memory, connector: loopback.Memory,
}); });
@ -45,7 +45,7 @@ describe('Replication / Change APIs', function() {
// model. This causes the in-process replication to work differently // model. This causes the in-process replication to work differently
// than client-server replication. // than client-server replication.
// As a workaround, we manually setup unique Checkpoint for TargetModel. // As a workaround, we manually setup unique Checkpoint for TargetModel.
var TargetChange = TargetModel.Change; const TargetChange = TargetModel.Change;
TargetChange.Checkpoint = loopback.Checkpoint.extend('TargetCheckpoint'); TargetChange.Checkpoint = loopback.Checkpoint.extend('TargetCheckpoint');
TargetChange.Checkpoint.attachTo(dataSource); TargetChange.Checkpoint.attachTo(dataSource);
@ -66,7 +66,7 @@ describe('Replication / Change APIs', function() {
describe('cleanup check for enableChangeTracking', function() { describe('cleanup check for enableChangeTracking', function() {
describe('when no changeCleanupInterval set', function() { describe('when no changeCleanupInterval set', function() {
it('should call rectifyAllChanges if running on server', function(done) { it('should call rectifyAllChanges if running on server', function(done) {
var calls = mockRectifyAllChanges(SourceModel); const calls = mockRectifyAllChanges(SourceModel);
SourceModel.enableChangeTracking(); SourceModel.enableChangeTracking();
if (runtime.isServer) { if (runtime.isServer) {
@ -80,7 +80,7 @@ describe('Replication / Change APIs', function() {
}); });
describe('when changeCleanupInterval set to -1', function() { describe('when changeCleanupInterval set to -1', function() {
var Model; let Model;
beforeEach(function() { beforeEach(function() {
Model = this.Model = PersistedModel.extend( Model = this.Model = PersistedModel.extend(
'Model-' + tid, 'Model-' + tid,
@ -92,7 +92,7 @@ describe('Replication / Change APIs', function() {
}); });
it('should not call rectifyAllChanges', function(done) { it('should not call rectifyAllChanges', function(done) {
var calls = mockRectifyAllChanges(Model); const calls = mockRectifyAllChanges(Model);
Model.enableChangeTracking(); Model.enableChangeTracking();
expect(calls).to.eql([]); expect(calls).to.eql([]);
done(); done();
@ -100,7 +100,7 @@ describe('Replication / Change APIs', function() {
}); });
describe('when changeCleanupInterval set to 10000', function() { describe('when changeCleanupInterval set to 10000', function() {
var Model; let Model;
beforeEach(function() { beforeEach(function() {
Model = this.Model = PersistedModel.extend( Model = this.Model = PersistedModel.extend(
'Model-' + tid, 'Model-' + tid,
@ -112,7 +112,7 @@ describe('Replication / Change APIs', function() {
}); });
it('should call rectifyAllChanges if running on server', function(done) { it('should call rectifyAllChanges if running on server', function(done) {
var calls = mockRectifyAllChanges(Model); const calls = mockRectifyAllChanges(Model);
Model.enableChangeTracking(); Model.enableChangeTracking();
if (runtime.isServer) { if (runtime.isServer) {
expect(calls).to.eql(['rectifyAllChanges']); expect(calls).to.eql(['rectifyAllChanges']);
@ -125,7 +125,7 @@ describe('Replication / Change APIs', function() {
}); });
function mockRectifyAllChanges(Model) { function mockRectifyAllChanges(Model) {
var calls = []; const calls = [];
Model.rectifyAllChanges = function(cb) { Model.rectifyAllChanges = function(cb) {
calls.push('rectifyAllChanges'); calls.push('rectifyAllChanges');
@ -138,7 +138,7 @@ describe('Replication / Change APIs', function() {
describe('optimization check rectifyChange Vs rectifyAllChanges', function() { describe('optimization check rectifyChange Vs rectifyAllChanges', function() {
beforeEach(function initialData(done) { beforeEach(function initialData(done) {
var data = [{name: 'John', surname: 'Doe'}, {name: 'Jane', surname: 'Roe'}]; const data = [{name: 'John', surname: 'Doe'}, {name: 'Jane', surname: 'Roe'}];
async.waterfall([ async.waterfall([
function(callback) { function(callback) {
SourceModel.create(data, callback); SourceModel.create(data, callback);
@ -151,7 +151,7 @@ describe('Replication / Change APIs', function() {
}); });
it('should call rectifyAllChanges if no id is passed for rectifyOnDelete', function(done) { it('should call rectifyAllChanges if no id is passed for rectifyOnDelete', function(done) {
var calls = mockSourceModelRectify(); const calls = mockSourceModelRectify();
SourceModel.destroyAll({name: 'John'}, function(err, data) { SourceModel.destroyAll({name: 'John'}, function(err, data) {
if (err) return done(err); if (err) return done(err);
@ -162,8 +162,8 @@ describe('Replication / Change APIs', function() {
}); });
it('should call rectifyAllChanges if no id is passed for rectifyOnSave', function(done) { it('should call rectifyAllChanges if no id is passed for rectifyOnSave', function(done) {
var calls = mockSourceModelRectify(); const calls = mockSourceModelRectify();
var newData = {'name': 'Janie'}; const newData = {'name': 'Janie'};
SourceModel.update({name: 'Jane'}, newData, function(err, data) { SourceModel.update({name: 'Jane'}, newData, function(err, data) {
if (err) return done(err); if (err) return done(err);
@ -175,7 +175,7 @@ describe('Replication / Change APIs', function() {
it('rectifyOnDelete for Delete should call rectifyChange instead of rectifyAllChanges', it('rectifyOnDelete for Delete should call rectifyChange instead of rectifyAllChanges',
function(done) { function(done) {
var calls = mockTargetModelRectify(); const calls = mockTargetModelRectify();
async.waterfall([ async.waterfall([
function(callback) { function(callback) {
SourceModel.destroyAll({name: 'John'}, callback); SourceModel.destroyAll({name: 'John'}, callback);
@ -195,8 +195,8 @@ describe('Replication / Change APIs', function() {
it('rectifyOnSave for Update should call rectifyChange instead of rectifyAllChanges', it('rectifyOnSave for Update should call rectifyChange instead of rectifyAllChanges',
function(done) { function(done) {
var calls = mockTargetModelRectify(); const calls = mockTargetModelRectify();
var newData = {'name': 'Janie'}; const newData = {'name': 'Janie'};
async.waterfall([ async.waterfall([
function(callback) { function(callback) {
SourceModel.update({name: 'Jane'}, newData, callback); SourceModel.update({name: 'Jane'}, newData, callback);
@ -216,8 +216,8 @@ describe('Replication / Change APIs', function() {
it('rectifyOnSave for Create should call rectifyChange instead of rectifyAllChanges', it('rectifyOnSave for Create should call rectifyChange instead of rectifyAllChanges',
function(done) { function(done) {
var calls = mockTargetModelRectify(); const calls = mockTargetModelRectify();
var newData = [{name: 'Janie', surname: 'Doe'}]; const newData = [{name: 'Janie', surname: 'Doe'}];
async.waterfall([ async.waterfall([
function(callback) { function(callback) {
SourceModel.create(newData, callback); SourceModel.create(newData, callback);
@ -236,7 +236,7 @@ describe('Replication / Change APIs', function() {
}); });
function mockSourceModelRectify() { function mockSourceModelRectify() {
var calls = []; const calls = [];
SourceModel.rectifyChange = function(id, cb) { SourceModel.rectifyChange = function(id, cb) {
calls.push('rectifyChange'); calls.push('rectifyChange');
@ -252,7 +252,7 @@ describe('Replication / Change APIs', function() {
} }
function mockTargetModelRectify() { function mockTargetModelRectify() {
var calls = []; const calls = [];
TargetModel.rectifyChange = function(id, cb) { TargetModel.rectifyChange = function(id, cb) {
calls.push('rectifyChange'); calls.push('rectifyChange');
@ -270,7 +270,7 @@ describe('Replication / Change APIs', function() {
describe('Model.changes(since, filter, callback)', function() { describe('Model.changes(since, filter, callback)', function() {
it('Get changes since the given checkpoint', function(done) { it('Get changes since the given checkpoint', function(done) {
var test = this; const test = this;
this.SourceModel.create({name: 'foo'}, function(err) { this.SourceModel.create({name: 'foo'}, function(err) {
if (err) return done(err); if (err) return done(err);
@ -285,7 +285,7 @@ describe('Replication / Change APIs', function() {
}); });
it('excludes changes from older checkpoints', function(done) { it('excludes changes from older checkpoints', function(done) {
var FUTURE_CHECKPOINT = 999; const FUTURE_CHECKPOINT = 999;
SourceModel.create({name: 'foo'}, function(err) { SourceModel.create({name: 'foo'}, function(err) {
if (err) return done(err); if (err) return done(err);
@ -302,8 +302,8 @@ describe('Replication / Change APIs', function() {
describe('Model.replicate(since, targetModel, options, callback)', function() { describe('Model.replicate(since, targetModel, options, callback)', function() {
it('Replicate data using the target model', function(done) { it('Replicate data using the target model', function(done) {
var test = this; const test = this;
var options = {}; const options = {};
this.SourceModel.create({name: 'foo'}, function(err) { this.SourceModel.create({name: 'foo'}, function(err) {
if (err) return done(err); if (err) return done(err);
@ -319,8 +319,8 @@ describe('Replication / Change APIs', function() {
}); });
it('Replicate data using the target model - promise variant', function(done) { it('Replicate data using the target model - promise variant', function(done) {
var test = this; const test = this;
var options = {}; const options = {};
this.SourceModel.create({name: 'foo'}, function(err) { this.SourceModel.create({name: 'foo'}, function(err) {
if (err) return done(err); if (err) return done(err);
@ -403,7 +403,7 @@ describe('Replication / Change APIs', function() {
// Because the "since" filter is just an optimization, // Because the "since" filter is just an optimization,
// there isn't really any observable behaviour we could // there isn't really any observable behaviour we could
// check to assert correct implementation. // check to assert correct implementation.
var diffSince = []; const diffSince = [];
spyAndStoreSinceArg(TargetModel, 'diff', diffSince); spyAndStoreSinceArg(TargetModel, 'diff', diffSince);
SourceModel.replicate(10, TargetModel, function(err) { SourceModel.replicate(10, TargetModel, function(err) {
@ -419,7 +419,7 @@ describe('Replication / Change APIs', function() {
// Because the "since" filter is just an optimization, // Because the "since" filter is just an optimization,
// there isn't really any observable behaviour we could // there isn't really any observable behaviour we could
// check to assert correct implementation. // check to assert correct implementation.
var diffSince = []; const diffSince = [];
spyAndStoreSinceArg(TargetModel, 'diff', diffSince); spyAndStoreSinceArg(TargetModel, 'diff', diffSince);
SourceModel.replicate(10, TargetModel, {}) SourceModel.replicate(10, TargetModel, {})
@ -434,13 +434,13 @@ describe('Replication / Change APIs', function() {
}); });
it('uses different "since" value for source and target', function(done) { it('uses different "since" value for source and target', function(done) {
var sourceSince = []; const sourceSince = [];
var targetSince = []; const targetSince = [];
spyAndStoreSinceArg(SourceModel, 'changes', sourceSince); spyAndStoreSinceArg(SourceModel, 'changes', sourceSince);
spyAndStoreSinceArg(TargetModel, 'diff', targetSince); spyAndStoreSinceArg(TargetModel, 'diff', targetSince);
var since = {source: 1, target: 2}; const since = {source: 1, target: 2};
SourceModel.replicate(since, TargetModel, function(err) { SourceModel.replicate(since, TargetModel, function(err) {
if (err) return done(err); if (err) return done(err);
@ -452,13 +452,13 @@ describe('Replication / Change APIs', function() {
}); });
it('uses different "since" value for source and target - promise variant', function(done) { it('uses different "since" value for source and target - promise variant', function(done) {
var sourceSince = []; const sourceSince = [];
var targetSince = []; const targetSince = [];
spyAndStoreSinceArg(SourceModel, 'changes', sourceSince); spyAndStoreSinceArg(SourceModel, 'changes', sourceSince);
spyAndStoreSinceArg(TargetModel, 'diff', targetSince); spyAndStoreSinceArg(TargetModel, 'diff', targetSince);
var since = {source: 1, target: 2}; const since = {source: 1, target: 2};
SourceModel.replicate(since, TargetModel, {}) SourceModel.replicate(since, TargetModel, {})
.then(function() { .then(function() {
expect(sourceSince).to.eql([1]); expect(sourceSince).to.eql([1]);
@ -478,7 +478,7 @@ describe('Replication / Change APIs', function() {
SourceModel.create({id: 'racer'}, cb); SourceModel.create({id: 'racer'}, cb);
}); });
var lastCp; let lastCp;
async.series([ async.series([
function buildSomeDataToReplicate(next) { function buildSomeDataToReplicate(next) {
SourceModel.create({id: 'init'}, next); SourceModel.create({id: 'init'}, next);
@ -522,7 +522,7 @@ describe('Replication / Change APIs', function() {
}); });
it('returns new current checkpoints to callback', function(done) { it('returns new current checkpoints to callback', function(done) {
var sourceCp, targetCp; let sourceCp, targetCp;
async.series([ async.series([
bumpSourceCheckpoint, bumpSourceCheckpoint,
bumpTargetCheckpoint, bumpTargetCheckpoint,
@ -603,7 +603,7 @@ describe('Replication / Change APIs', function() {
}, },
function replicateWith3rdPartyModifyingData(next) { function replicateWith3rdPartyModifyingData(next) {
setupRaceConditionInReplication(function(cb) { setupRaceConditionInReplication(function(cb) {
var connector = TargetModel.dataSource.connector; const connector = TargetModel.dataSource.connector;
if (connector.updateAttributes.length <= 4) { if (connector.updateAttributes.length <= 4) {
connector.updateAttributes( connector.updateAttributes(
TargetModel.modelName, TargetModel.modelName,
@ -628,7 +628,7 @@ describe('Replication / Change APIs', function() {
function(err, conflicts, cps, updates) { function(err, conflicts, cps, updates) {
if (err) return next(err); if (err) return next(err);
var conflictedIds = getPropValue(conflicts || [], 'modelId'); const conflictedIds = getPropValue(conflicts || [], 'modelId');
expect(conflictedIds).to.eql(['1']); expect(conflictedIds).to.eql(['1']);
// resolve the conflict using ours // resolve the conflict using ours
@ -648,7 +648,7 @@ describe('Replication / Change APIs', function() {
// of UPDATE is fixed to correctly remove properties // of UPDATE is fixed to correctly remove properties
createModel(SourceModel, {id: '1', name: 'source'}), createModel(SourceModel, {id: '1', name: 'source'}),
function replicateWith3rdPartyModifyingData(next) { function replicateWith3rdPartyModifyingData(next) {
var connector = TargetModel.dataSource.connector; const connector = TargetModel.dataSource.connector;
setupRaceConditionInReplication(function(cb) { setupRaceConditionInReplication(function(cb) {
if (connector.create.length <= 3) { if (connector.create.length <= 3) {
connector.create( connector.create(
@ -672,7 +672,7 @@ describe('Replication / Change APIs', function() {
function(err, conflicts, cps, updates) { function(err, conflicts, cps, updates) {
if (err) return next(err); if (err) return next(err);
var conflictedIds = getPropValue(conflicts || [], 'modelId'); const conflictedIds = getPropValue(conflicts || [], 'modelId');
expect(conflictedIds).to.eql(['1']); expect(conflictedIds).to.eql(['1']);
// resolve the conflict using ours // resolve the conflict using ours
@ -695,7 +695,7 @@ describe('Replication / Change APIs', function() {
}, },
function replicateWith3rdPartyModifyingData(next) { function replicateWith3rdPartyModifyingData(next) {
setupRaceConditionInReplication(function(cb) { setupRaceConditionInReplication(function(cb) {
var connector = TargetModel.dataSource.connector; const connector = TargetModel.dataSource.connector;
if (connector.updateAttributes.length <= 4) { if (connector.updateAttributes.length <= 4) {
connector.updateAttributes( connector.updateAttributes(
TargetModel.modelName, TargetModel.modelName,
@ -720,7 +720,7 @@ describe('Replication / Change APIs', function() {
function(err, conflicts, cps, updates) { function(err, conflicts, cps, updates) {
if (err) return next(err); if (err) return next(err);
var conflictedIds = getPropValue(conflicts || [], 'modelId'); const conflictedIds = getPropValue(conflicts || [], 'modelId');
expect(conflictedIds).to.eql(['1']); expect(conflictedIds).to.eql(['1']);
// resolve the conflict using ours // resolve the conflict using ours
@ -742,7 +742,7 @@ describe('Replication / Change APIs', function() {
SourceModel.deleteById('1', next); SourceModel.deleteById('1', next);
}, },
function setup3rdPartyModifyingData(next) { function setup3rdPartyModifyingData(next) {
var connector = TargetModel.dataSource.connector; const connector = TargetModel.dataSource.connector;
setupRaceConditionInReplication(function(cb) { setupRaceConditionInReplication(function(cb) {
if (connector.destroy.length <= 3) { if (connector.destroy.length <= 3) {
connector.destroy( connector.destroy(
@ -772,9 +772,9 @@ describe('Replication / Change APIs', function() {
describe('conflict detection - both updated', function() { describe('conflict detection - both updated', function() {
beforeEach(function(done) { beforeEach(function(done) {
var SourceModel = this.SourceModel; const SourceModel = this.SourceModel;
var TargetModel = this.TargetModel; const TargetModel = this.TargetModel;
var test = this; const test = this;
test.createInitalData(createConflict); test.createInitalData(createConflict);
@ -820,7 +820,7 @@ describe('Replication / Change APIs', function() {
}); });
}); });
it('conflict.changes()', function(done) { it('conflict.changes()', function(done) {
var test = this; const test = this;
this.conflict.changes(function(err, sourceChange, targetChange) { this.conflict.changes(function(err, sourceChange, targetChange) {
assert.equal(typeof sourceChange.id, 'string'); assert.equal(typeof sourceChange.id, 'string');
assert.equal(typeof targetChange.id, 'string'); assert.equal(typeof targetChange.id, 'string');
@ -832,7 +832,7 @@ describe('Replication / Change APIs', function() {
}); });
}); });
it('conflict.models()', function(done) { it('conflict.models()', function(done) {
var test = this; const test = this;
this.conflict.models(function(err, source, target) { this.conflict.models(function(err, source, target) {
assert.deepEqual(source.toJSON(), { assert.deepEqual(source.toJSON(), {
id: test.model.id, id: test.model.id,
@ -850,9 +850,9 @@ describe('Replication / Change APIs', function() {
describe('conflict detection - source deleted', function() { describe('conflict detection - source deleted', function() {
beforeEach(function(done) { beforeEach(function(done) {
var SourceModel = this.SourceModel; const SourceModel = this.SourceModel;
var TargetModel = this.TargetModel; const TargetModel = this.TargetModel;
var test = this; const test = this;
test.createInitalData(createConflict); test.createInitalData(createConflict);
@ -900,7 +900,7 @@ describe('Replication / Change APIs', function() {
}); });
}); });
it('conflict.changes()', function(done) { it('conflict.changes()', function(done) {
var test = this; const test = this;
this.conflict.changes(function(err, sourceChange, targetChange) { this.conflict.changes(function(err, sourceChange, targetChange) {
assert.equal(typeof sourceChange.id, 'string'); assert.equal(typeof sourceChange.id, 'string');
assert.equal(typeof targetChange.id, 'string'); assert.equal(typeof targetChange.id, 'string');
@ -912,7 +912,7 @@ describe('Replication / Change APIs', function() {
}); });
}); });
it('conflict.models()', function(done) { it('conflict.models()', function(done) {
var test = this; const test = this;
this.conflict.models(function(err, source, target) { this.conflict.models(function(err, source, target) {
assert.equal(source, null); assert.equal(source, null);
assert.deepEqual(target.toJSON(), { assert.deepEqual(target.toJSON(), {
@ -927,9 +927,9 @@ describe('Replication / Change APIs', function() {
describe('conflict detection - target deleted', function() { describe('conflict detection - target deleted', function() {
beforeEach(function(done) { beforeEach(function(done) {
var SourceModel = this.SourceModel; const SourceModel = this.SourceModel;
var TargetModel = this.TargetModel; const TargetModel = this.TargetModel;
var test = this; const test = this;
test.createInitalData(createConflict); test.createInitalData(createConflict);
@ -976,7 +976,7 @@ describe('Replication / Change APIs', function() {
}); });
}); });
it('conflict.changes()', function(done) { it('conflict.changes()', function(done) {
var test = this; const test = this;
this.conflict.changes(function(err, sourceChange, targetChange) { this.conflict.changes(function(err, sourceChange, targetChange) {
assert.equal(typeof sourceChange.id, 'string'); assert.equal(typeof sourceChange.id, 'string');
assert.equal(typeof targetChange.id, 'string'); assert.equal(typeof targetChange.id, 'string');
@ -988,7 +988,7 @@ describe('Replication / Change APIs', function() {
}); });
}); });
it('conflict.models()', function(done) { it('conflict.models()', function(done) {
var test = this; const test = this;
this.conflict.models(function(err, source, target) { this.conflict.models(function(err, source, target) {
assert.equal(target, null); assert.equal(target, null);
assert.deepEqual(source.toJSON(), { assert.deepEqual(source.toJSON(), {
@ -1003,9 +1003,9 @@ describe('Replication / Change APIs', function() {
describe('conflict detection - both deleted', function() { describe('conflict detection - both deleted', function() {
beforeEach(function(done) { beforeEach(function(done) {
var SourceModel = this.SourceModel; const SourceModel = this.SourceModel;
var TargetModel = this.TargetModel; const TargetModel = this.TargetModel;
var test = this; const test = this;
test.createInitalData(createConflict); test.createInitalData(createConflict);
@ -1059,7 +1059,7 @@ describe('Replication / Change APIs', function() {
givenReplicatedInstance(function(err, created) { givenReplicatedInstance(function(err, created) {
if (err) return done(err); if (err) return done(err);
var data = created.toObject(); const data = created.toObject();
created.name = 'updated'; created.name = 'updated';
SourceModel.updateOrCreate(created, function(err, inst) { SourceModel.updateOrCreate(created, function(err, inst) {
if (err) return done(err); if (err) return done(err);
@ -1214,7 +1214,7 @@ describe('Replication / Change APIs', function() {
if (err) return cb(err); if (err) return cb(err);
expect(pendingChanges, 'list of changes').to.have.length(1); expect(pendingChanges, 'list of changes').to.have.length(1);
var change = pendingChanges[0].toObject(); const change = pendingChanges[0].toObject();
expect(change).to.have.property('checkpoint', cp); // sanity check expect(change).to.have.property('checkpoint', cp); // sanity check
expect(change).to.have.property('modelName', SourceModel.modelName); expect(change).to.have.property('modelName', SourceModel.modelName);
// NOTE(bajtos) Change.modelId is always String // NOTE(bajtos) Change.modelId is always String
@ -1228,7 +1228,7 @@ describe('Replication / Change APIs', function() {
}); });
describe('complex setup', function() { describe('complex setup', function() {
var sourceInstance, sourceInstanceId, AnotherModel; let sourceInstance, sourceInstanceId, AnotherModel;
beforeEach(function createReplicatedInstance(done) { beforeEach(function createReplicatedInstance(done) {
async.series([ async.series([
@ -1256,7 +1256,7 @@ describe('Replication / Change APIs', function() {
// model. This causes the in-process replication to work differently // model. This causes the in-process replication to work differently
// than client-server replication. // than client-server replication.
// As a workaround, we manually setup unique Checkpoint for AnotherModel. // As a workaround, we manually setup unique Checkpoint for AnotherModel.
var AnotherChange = AnotherModel.Change; const AnotherChange = AnotherModel.Change;
AnotherChange.Checkpoint = loopback.Checkpoint.extend('AnotherCheckpoint'); AnotherChange.Checkpoint = loopback.Checkpoint.extend('AnotherCheckpoint');
AnotherChange.Checkpoint.attachTo(dataSource); AnotherChange.Checkpoint.attachTo(dataSource);
@ -1298,7 +1298,7 @@ describe('Replication / Change APIs', function() {
}); });
describe('clientA-server-clientB', function() { describe('clientA-server-clientB', function() {
var ClientA, Server, ClientB; let ClientA, Server, ClientB;
beforeEach(function() { beforeEach(function() {
ClientA = SourceModel; ClientA = SourceModel;
@ -1606,8 +1606,8 @@ describe('Replication / Change APIs', function() {
}); });
describe('ensure options object is set on context during bulkUpdate', function() { describe('ensure options object is set on context during bulkUpdate', function() {
var syncPropertyExists = false; let syncPropertyExists = false;
var OptionsSourceModel; let OptionsSourceModel;
beforeEach(function() { beforeEach(function() {
OptionsSourceModel = PersistedModel.extend( OptionsSourceModel = PersistedModel.extend(
@ -1629,8 +1629,8 @@ describe('Replication / Change APIs', function() {
}); });
it('bulkUpdate should call Model updates with the provided options object', function(done) { it('bulkUpdate should call Model updates with the provided options object', function(done) {
var testData = {name: 'Janie', surname: 'Doe'}; const testData = {name: 'Janie', surname: 'Doe'};
var updates = [ const updates = [
{ {
data: null, data: null,
change: null, change: null,
@ -1638,7 +1638,7 @@ describe('Replication / Change APIs', function() {
}, },
]; ];
var options = { const options = {
sync: true, sync: true,
}; };
@ -1666,8 +1666,8 @@ describe('Replication / Change APIs', function() {
describe('ensure bulkUpdate works with just 2 args', function() { describe('ensure bulkUpdate works with just 2 args', function() {
it('bulkUpdate should successfully finish without options', function(done) { it('bulkUpdate should successfully finish without options', function(done) {
var testData = {name: 'Janie', surname: 'Doe'}; const testData = {name: 'Janie', surname: 'Doe'};
var updates = [{ const updates = [{
data: null, data: null,
change: null, change: null,
type: 'create', type: 'create',
@ -1694,7 +1694,7 @@ describe('Replication / Change APIs', function() {
describe('Replication with chunking', function() { describe('Replication with chunking', function() {
beforeEach(function() { beforeEach(function() {
var test = this; const test = this;
SourceModel = this.SourceModel = PersistedModel.extend( SourceModel = this.SourceModel = PersistedModel.extend(
'SourceModel-' + tid, 'SourceModel-' + tid,
{id: {id: true, type: String, defaultFn: 'guid'}}, {id: {id: true, type: String, defaultFn: 'guid'}},
@ -1709,7 +1709,7 @@ describe('Replication / Change APIs', function() {
{trackChanges: true, replicationChunkSize: 1} {trackChanges: true, replicationChunkSize: 1}
); );
var TargetChange = TargetModel.Change; const TargetChange = TargetModel.Change;
TargetChange.Checkpoint = loopback.Checkpoint.extend('TargetCheckpoint'); TargetChange.Checkpoint = loopback.Checkpoint.extend('TargetCheckpoint');
TargetChange.Checkpoint.attachTo(dataSource); TargetChange.Checkpoint.attachTo(dataSource);
@ -1720,9 +1720,9 @@ describe('Replication / Change APIs', function() {
describe('Model.replicate(since, targetModel, options, callback)', function() { describe('Model.replicate(since, targetModel, options, callback)', function() {
it('calls bulkUpdate multiple times', function(done) { it('calls bulkUpdate multiple times', function(done) {
var test = this; const test = this;
var options = {}; const options = {};
var calls = mockBulkUpdate(TargetModel); const calls = mockBulkUpdate(TargetModel);
SourceModel.create([{name: 'foo'}, {name: 'bar'}], function(err) { SourceModel.create([{name: 'foo'}, {name: 'bar'}], function(err) {
if (err) return done(err); if (err) return done(err);
@ -1742,7 +1742,7 @@ describe('Replication / Change APIs', function() {
describe('Replication without chunking', function() { describe('Replication without chunking', function() {
beforeEach(function() { beforeEach(function() {
var test = this; const test = this;
SourceModel = this.SourceModel = PersistedModel.extend( SourceModel = this.SourceModel = PersistedModel.extend(
'SourceModel-' + tid, 'SourceModel-' + tid,
{id: {id: true, type: String, defaultFn: 'guid'}}, {id: {id: true, type: String, defaultFn: 'guid'}},
@ -1757,7 +1757,7 @@ describe('Replication / Change APIs', function() {
{trackChanges: true} {trackChanges: true}
); );
var TargetChange = TargetModel.Change; const TargetChange = TargetModel.Change;
TargetChange.Checkpoint = loopback.Checkpoint.extend('TargetCheckpoint'); TargetChange.Checkpoint = loopback.Checkpoint.extend('TargetCheckpoint');
TargetChange.Checkpoint.attachTo(dataSource); TargetChange.Checkpoint.attachTo(dataSource);
@ -1768,9 +1768,9 @@ describe('Replication / Change APIs', function() {
describe('Model.replicate(since, targetModel, options, callback)', function() { describe('Model.replicate(since, targetModel, options, callback)', function() {
it('calls bulkUpdate only once', function(done) { it('calls bulkUpdate only once', function(done) {
var test = this; const test = this;
var options = {}; const options = {};
var calls = mockBulkUpdate(TargetModel); const calls = mockBulkUpdate(TargetModel);
SourceModel.create([{name: 'foo'}, {name: 'bar'}], function(err) { SourceModel.create([{name: 'foo'}, {name: 'bar'}], function(err) {
if (err) return done(err); if (err) return done(err);
@ -1789,9 +1789,9 @@ describe('Replication / Change APIs', function() {
}); });
function mockBulkUpdate(modelToMock) { function mockBulkUpdate(modelToMock) {
var calls = []; const calls = [];
var originalBulkUpdateFunction = modelToMock.bulkUpdate; const originalBulkUpdateFunction = modelToMock.bulkUpdate;
modelToMock.bulkUpdate = function(since, filter, callback) { modelToMock.bulkUpdate = function(since, filter, callback) {
calls.push('bulkUpdate'); calls.push('bulkUpdate');
@ -1801,14 +1801,14 @@ describe('Replication / Change APIs', function() {
return calls; return calls;
} }
var _since = {}; const _since = {};
function replicate(source, target, since, next) { function replicate(source, target, since, next) {
if (typeof since === 'function') { if (typeof since === 'function') {
next = since; next = since;
since = undefined; since = undefined;
} }
var sinceIx = source.modelName + ':to:' + target.modelName; const sinceIx = source.modelName + ':to:' + target.modelName;
if (since === undefined) { if (since === undefined) {
since = useSinceFilter ? since = useSinceFilter ?
_since[sinceIx] || -1 : _since[sinceIx] || -1 :
@ -1854,11 +1854,11 @@ describe('Replication / Change APIs', function() {
} }
function setupRaceConditionInReplication(fn) { function setupRaceConditionInReplication(fn) {
var bulkUpdate = TargetModel.bulkUpdate; const bulkUpdate = TargetModel.bulkUpdate;
TargetModel.bulkUpdate = function(data, options, cb) { TargetModel.bulkUpdate = function(data, options, cb) {
// simulate the situation when a 3rd party modifies the database // simulate the situation when a 3rd party modifies the database
// while a replication run is in progress // while a replication run is in progress
var self = this; const self = this;
fn(function(err) { fn(function(err) {
if (err) return cb(err); if (err) return cb(err);
@ -1889,7 +1889,7 @@ describe('Replication / Change APIs', function() {
} }
function spyAndStoreSinceArg(Model, methodName, store) { function spyAndStoreSinceArg(Model, methodName, store) {
var orig = Model[methodName]; const orig = Model[methodName];
Model[methodName] = function(since) { Model[methodName] = function(since) {
store.push(since); store.push(since);
orig.apply(this, arguments); orig.apply(this, arguments);
@ -1908,7 +1908,7 @@ describe('Replication / Change APIs', function() {
function assertTargetModelEqualsSourceModel(conflicts, sourceModel, function assertTargetModelEqualsSourceModel(conflicts, sourceModel,
targetModel, done) { targetModel, done) {
var sourceData, targetData; let sourceData, targetData;
assert(conflicts.length === 0); assert(conflicts.length === 0);
async.parallel([ async.parallel([
@ -1940,13 +1940,13 @@ describe('Replication / Change APIs', function() {
describe('Replication / Change APIs with custom change properties', function() { describe('Replication / Change APIs with custom change properties', function() {
this.timeout(10000); this.timeout(10000);
var dataSource, useSinceFilter, SourceModel, TargetModel, startingCheckpoint; let dataSource, useSinceFilter, SourceModel, TargetModel, startingCheckpoint;
var tid = 0; // per-test unique id used e.g. to build unique model names let tid = 0; // per-test unique id used e.g. to build unique model names
beforeEach(function() { beforeEach(function() {
tid++; tid++;
useSinceFilter = false; useSinceFilter = false;
var test = this; const test = this;
dataSource = this.dataSource = loopback.createDataSource({ dataSource = this.dataSource = loopback.createDataSource({
connector: loopback.Memory, connector: loopback.Memory,
@ -1994,7 +1994,7 @@ describe('Replication / Change APIs with custom change properties', function() {
} }
); );
var ChangeModelForTarget = TargetModel.Change; const ChangeModelForTarget = TargetModel.Change;
ChangeModelForTarget.Checkpoint = loopback.Checkpoint.extend('TargetCheckpoint'); ChangeModelForTarget.Checkpoint = loopback.Checkpoint.extend('TargetCheckpoint');
ChangeModelForTarget.Checkpoint.attachTo(dataSource); ChangeModelForTarget.Checkpoint.attachTo(dataSource);
@ -2005,8 +2005,8 @@ describe('Replication / Change APIs with custom change properties', function() {
describe('Model._defineChangeModel()', function() { describe('Model._defineChangeModel()', function() {
it('defines change model with custom properties', function() { it('defines change model with custom properties', function() {
var changeModel = SourceModel.getChangeModel(); const changeModel = SourceModel.getChangeModel();
var changeModelProperties = changeModel.definition.properties; const changeModelProperties = changeModel.definition.properties;
expect(changeModelProperties).to.have.property('customProperty'); expect(changeModelProperties).to.have.property('customProperty');
}); });
@ -2016,7 +2016,7 @@ describe('Replication / Change APIs with custom change properties', function() {
beforeEach(givenSomeSourceModelInstances); beforeEach(givenSomeSourceModelInstances);
it('queries changes using customized filter', function(done) { it('queries changes using customized filter', function(done) {
var filterUsed = mockChangeFind(this.SourceModel); const filterUsed = mockChangeFind(this.SourceModel);
SourceModel.changes( SourceModel.changes(
startingCheckpoint, startingCheckpoint,
@ -2057,7 +2057,7 @@ describe('Replication / Change APIs with custom change properties', function() {
}); });
function mockChangeFind(Model) { function mockChangeFind(Model) {
var filterUsed = []; const filterUsed = [];
Model.getChangeModel().find = function(filter, cb) { Model.getChangeModel().find = function(filter, cb) {
filterUsed.push(filter); filterUsed.push(filter);

View File

@ -4,22 +4,22 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var loopback = require('../'); const loopback = require('../');
var path = require('path'); const path = require('path');
var request = require('supertest'); const request = require('supertest');
describe('loopback.rest', function() { describe('loopback.rest', function() {
this.timeout(10000); this.timeout(10000);
var app, MyModel; let app, MyModel;
beforeEach(function() { beforeEach(function() {
// override the global app object provided by test/support.js // override the global app object provided by test/support.js
// and create a local one that does not share state with other tests // and create a local one that does not share state with other tests
app = loopback({localRegistry: true, loadBuiltinModels: true}); app = loopback({localRegistry: true, loadBuiltinModels: true});
app.set('remoting', {errorHandler: {debug: true, log: false}}); app.set('remoting', {errorHandler: {debug: true, log: false}});
var db = app.dataSource('db', {connector: 'memory'}); const db = app.dataSource('db', {connector: 'memory'});
MyModel = app.registry.createModel('MyModel'); MyModel = app.registry.createModel('MyModel');
MyModel.attachTo(db); MyModel.attachTo(db);
}); });
@ -54,7 +54,7 @@ describe('loopback.rest', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert(errorResponse); assert(errorResponse);
assert.equal(errorResponse.code, 'MODEL_NOT_FOUND'); assert.equal(errorResponse.code, 'MODEL_NOT_FOUND');
@ -121,10 +121,10 @@ describe('loopback.rest', function() {
}); });
it('should honour `remoting.rest.supportedTypes`', function(done) { it('should honour `remoting.rest.supportedTypes`', function(done) {
var app = loopback({localRegistry: true}); const app = loopback({localRegistry: true});
// NOTE it is crucial to set `remoting` before creating any models // NOTE it is crucial to set `remoting` before creating any models
var supportedTypes = ['json', 'application/javascript', 'text/javascript']; const supportedTypes = ['json', 'application/javascript', 'text/javascript'];
app.set('remoting', {rest: {supportedTypes: supportedTypes}}); app.set('remoting', {rest: {supportedTypes: supportedTypes}});
app.model(MyModel); app.model(MyModel);
@ -137,7 +137,7 @@ describe('loopback.rest', function() {
}); });
it('allows models to provide a custom HTTP path', function(done) { it('allows models to provide a custom HTTP path', function(done) {
var CustomModel = app.registry.createModel('CustomModel', const CustomModel = app.registry.createModel('CustomModel',
{name: String}, {name: String},
{http: {'path': 'domain1/CustomModelPath'}}); {http: {'path': 'domain1/CustomModelPath'}});
@ -148,7 +148,7 @@ describe('loopback.rest', function() {
}); });
it('should report 200 for url-encoded HTTP path', function(done) { it('should report 200 for url-encoded HTTP path', function(done) {
var CustomModel = app.registry.createModel('CustomModel', const CustomModel = app.registry.createModel('CustomModel',
{name: String}, {name: String},
{http: {path: 'domain%20one/CustomModelPath'}}); {http: {path: 'domain%20one/CustomModelPath'}});
@ -174,7 +174,7 @@ describe('loopback.rest', function() {
}); });
it('does not include loopback.token when auth not enabled', function(done) { it('does not include loopback.token when auth not enabled', function(done) {
var User = givenUserModelWithAuth(); const User = givenUserModelWithAuth();
User.getToken = function(req, cb) { User.getToken = function(req, cb) {
cb(null, req.accessToken ? req.accessToken.id : null); cb(null, req.accessToken ? req.accessToken.id : null);
}; };
@ -261,9 +261,9 @@ describe('loopback.rest', function() {
}); });
function givenUserModelWithAuth() { function givenUserModelWithAuth() {
var AccessToken = app.registry.getModel('AccessToken'); const AccessToken = app.registry.getModel('AccessToken');
app.model(AccessToken, {dataSource: 'db'}); app.model(AccessToken, {dataSource: 'db'});
var User = app.registry.getModel('User'); const User = app.registry.getModel('User');
// Speed up the password hashing algorithm for tests // Speed up the password hashing algorithm for tests
User.settings.saltWorkFactor = 4; User.settings.saltWorkFactor = 4;
app.model(User, {dataSource: 'db'}); app.model(User, {dataSource: 'db'});
@ -281,8 +281,8 @@ describe('loopback.rest', function() {
} }
function givenLoggedInUser(cb, done) { function givenLoggedInUser(cb, done) {
var credentials = {email: 'user@example.com', password: 'pwd'}; const credentials = {email: 'user@example.com', password: 'pwd'};
var User = app.models.User; const User = app.models.User;
User.create(credentials, User.create(credentials,
function(err, user) { function(err, user) {
if (err) return done(err); if (err) return done(err);
@ -300,14 +300,14 @@ describe('loopback.rest', function() {
describe('with specific definitions in model-config.json', function() { describe('with specific definitions in model-config.json', function() {
it('should not be exposed when the definition value is false', it('should not be exposed when the definition value is false',
function(done) { function(done) {
var app = require(getFixturePath('model-config-defined-false')); const app = require(getFixturePath('model-config-defined-false'));
request(app) request(app)
.get('/todos') .get('/todos')
.expect(404, done); .expect(404, done);
}); });
it('should be exposed when the definition value is true', function(done) { it('should be exposed when the definition value is true', function(done) {
var app = require(getFixturePath('model-config-defined-true')); const app = require(getFixturePath('model-config-defined-true'));
request(app) request(app)
.get('/todos') .get('/todos')
.expect(200, done); .expect(200, done);
@ -317,14 +317,14 @@ describe('loopback.rest', function() {
describe('with default definitions in model-config.json', function() { describe('with default definitions in model-config.json', function() {
it('should not be exposed when the definition value is false', it('should not be exposed when the definition value is false',
function(done) { function(done) {
var app = require(getFixturePath('model-config-default-false')); const app = require(getFixturePath('model-config-default-false'));
request(app) request(app)
.get('/todos') .get('/todos')
.expect(404, done); .expect(404, done);
}); });
it('should be exposed when the definition value is true', function(done) { it('should be exposed when the definition value is true', function(done) {
var app = require(getFixturePath('model-config-default-true')); const app = require(getFixturePath('model-config-default-true'));
app.models.Todo.create([ app.models.Todo.create([
{content: 'a'}, {content: 'a'},
{content: 'b'}, {content: 'b'},
@ -347,7 +347,7 @@ describe('loopback.rest', function() {
describe('with specific definitions in config.json', function() { describe('with specific definitions in config.json', function() {
it('should not be exposed when the definition value is false', it('should not be exposed when the definition value is false',
function(done) { function(done) {
var app = require(getFixturePath('config-defined-false')); const app = require(getFixturePath('config-defined-false'));
request(app) request(app)
.get('/todos') .get('/todos')
.expect(404, done); .expect(404, done);
@ -355,7 +355,7 @@ describe('loopback.rest', function() {
it('should be exposed when the definition value is true', it('should be exposed when the definition value is true',
function(done) { function(done) {
var app = require(getFixturePath('config-defined-true')); const app = require(getFixturePath('config-defined-true'));
request(app) request(app)
.get('/todos') .get('/todos')
.expect(200, done); .expect(200, done);
@ -365,14 +365,14 @@ describe('loopback.rest', function() {
describe('with default definitions in config.json', function() { describe('with default definitions in config.json', function() {
it('should not be exposed when the definition value is false', it('should not be exposed when the definition value is false',
function(done) { function(done) {
var app = require(getFixturePath('config-default-false')); const app = require(getFixturePath('config-default-false'));
request(app) request(app)
.get('/todos') .get('/todos')
.expect(404, done); .expect(404, done);
}); });
it('should be exposed when the definition value is true', function(done) { it('should be exposed when the definition value is true', function(done) {
var app = require(getFixturePath('config-default-true')); const app = require(getFixturePath('config-default-true'));
app.models.Todo.create([ app.models.Todo.create([
{content: 'a'}, {content: 'a'},
{content: 'b'}, {content: 'b'},
@ -399,7 +399,7 @@ describe('loopback.rest', function() {
describe.skip('with definitions in both config.json and model-config.json', describe.skip('with definitions in both config.json and model-config.json',
function() { function() {
it('should prioritize the settings in model-config.json', function(done) { it('should prioritize the settings in model-config.json', function(done) {
var app = require(getFixturePath('both-configs-set')); const app = require(getFixturePath('both-configs-set'));
request(app) request(app)
.del('/todos') .del('/todos')
.expect(404, done); .expect(404, done);
@ -407,7 +407,7 @@ describe('loopback.rest', function() {
it('should fall back to config.json settings if setting is not found in' + it('should fall back to config.json settings if setting is not found in' +
'model-config.json', function(done) { 'model-config.json', function(done) {
var app = require(getFixturePath('both-configs-set')); const app = require(getFixturePath('both-configs-set'));
request(app) request(app)
.get('/todos') .get('/todos')
.expect(404, done); .expect(404, done);

View File

@ -4,15 +4,15 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var loopback = require('../'); const loopback = require('../');
var Promise = require('bluebird'); const Promise = require('bluebird');
describe('role-mapping model', function() { describe('role-mapping model', function() {
this.timeout(10000); this.timeout(10000);
var app, oneUser, anApp, aRole; let app, oneUser, anApp, aRole;
var models = {}; const models = {};
beforeEach(function() { beforeEach(function() {
app = loopback({localRegistry: true, loadBuiltinModels: true}); app = loopback({localRegistry: true, loadBuiltinModels: true});
@ -39,7 +39,7 @@ describe('role-mapping model', function() {
// helper // helper
function setupModel(modelName) { function setupModel(modelName) {
var model = app.registry.getModel(modelName); const model = app.registry.getModel(modelName);
app.model(model, {dataSource: 'db'}); app.model(model, {dataSource: 'db'});
models[modelName] = model; models[modelName] = model;
} }

View File

@ -4,13 +4,13 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var sinon = require('sinon'); const sinon = require('sinon');
var loopback = require('../index'); const loopback = require('../index');
var async = require('async'); const async = require('async');
var extend = require('util')._extend; const extend = require('util')._extend;
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var Promise = require('bluebird'); const Promise = require('bluebird');
function checkResult(err, result) { function checkResult(err, result) {
assert(!err); assert(!err);
@ -19,7 +19,7 @@ function checkResult(err, result) {
describe('role model', function() { describe('role model', function() {
this.timeout(10000); this.timeout(10000);
var app, Role, RoleMapping, User, Application, ACL; let app, Role, RoleMapping, User, Application, ACL;
beforeEach(function() { beforeEach(function() {
// Use local app registry to ensure models are isolated to avoid // Use local app registry to ensure models are isolated to avoid
@ -153,7 +153,7 @@ describe('role model', function() {
Role.create({name: 'userRole'}, function(err, role) { Role.create({name: 'userRole'}, function(err, role) {
expect(err).to.exist(); expect(err).to.exist();
expect(err).to.have.property('name', 'ValidationError'); expect(err).to.have.property('name', 'ValidationError');
expect(err).to.have.deep.property('details.codes.name'); expect(err).to.have.nested.property('details.codes.name');
expect(err.details.codes.name).to.contain('uniqueness'); expect(err.details.codes.name).to.contain('uniqueness');
expect(err).to.have.property('statusCode', 422); expect(err).to.have.property('statusCode', 422);
@ -324,12 +324,12 @@ describe('role model', function() {
}); });
it('supports isInRole() returning a Promise', function(done) { it('supports isInRole() returning a Promise', function(done) {
var userData = {name: 'Raymond', email: 'x@y.com', password: 'foobar'}; const userData = {name: 'Raymond', email: 'x@y.com', password: 'foobar'};
User.create(userData, function(err, user) { User.create(userData, function(err, user) {
if (err) return done(err); if (err) return done(err);
Role.create({name: 'userRole'}, function(err, role) { Role.create({name: 'userRole'}, function(err, role) {
if (err) return done(err); if (err) return done(err);
var principalData = { const principalData = {
principalType: RoleMapping.USER, principalType: RoleMapping.USER,
principalId: user.id, principalId: user.id,
}; };
@ -347,12 +347,12 @@ describe('role model', function() {
}); });
it('supports getRole() returning a Promise', function(done) { it('supports getRole() returning a Promise', function(done) {
var userData = {name: 'Raymond', email: 'x@y.com', password: 'foobar'}; const userData = {name: 'Raymond', email: 'x@y.com', password: 'foobar'};
User.create(userData, function(err, user) { User.create(userData, function(err, user) {
if (err) return done(err); if (err) return done(err);
Role.create({name: 'userRole'}, function(err, role) { Role.create({name: 'userRole'}, function(err, role) {
if (err) return done(err); if (err) return done(err);
var principalData = { const principalData = {
principalType: RoleMapping.USER, principalType: RoleMapping.USER,
principalId: user.id, principalId: user.id,
}; };
@ -374,8 +374,8 @@ describe('role model', function() {
}); });
it('should be properly authenticated with 0 userId', function(done) { it('should be properly authenticated with 0 userId', function(done) {
var userData = {name: 'Raymond', email: 'x@y.com', password: 'foobar', id: 0}; const userData = {name: 'Raymond', email: 'x@y.com', password: 'foobar', id: 0};
var TestUser = app.registry.createModel({ const TestUser = app.registry.createModel({
name: 'TestUser', name: 'TestUser',
base: 'User', base: 'User',
// forceId is set to false so we can create a user with a known ID, // forceId is set to false so we can create a user with a known ID,
@ -444,7 +444,7 @@ describe('role model', function() {
}); });
}); });
var Album = app.registry.createModel('Album', { const Album = app.registry.createModel('Album', {
name: String, name: String,
userId: Number, userId: Number,
}, { }, {
@ -541,7 +541,7 @@ describe('role model', function() {
function(next) { function(next) {
Album.create({name: 'Album 1', userId: user.id}, function(err, album1) { Album.create({name: 'Album 1', userId: user.id}, function(err, album1) {
if (err) return done(err); if (err) return done(err);
var role = { let role = {
principalType: ACL.USER, principalId: user.id, principalType: ACL.USER, principalId: user.id,
model: Album, id: album1.id, model: Album, id: album1.id,
}; };
@ -569,16 +569,16 @@ describe('role model', function() {
}); });
describe('$owner role resolver', function() { describe('$owner role resolver', function() {
var sender, receiver; let sender, receiver;
var users = [ const users = [
{username: 'sender', email: 'sender@example.com', password: 'pass'}, {username: 'sender', email: 'sender@example.com', password: 'pass'},
{username: 'receiver', email: 'receiver@example.com', password: 'pass'}, {username: 'receiver', email: 'receiver@example.com', password: 'pass'},
]; ];
describe('ownerRelations not set (legacy behaviour)', () => { describe('ownerRelations not set (legacy behaviour)', () => {
it('resolves the owner via property "userId"', function() { it('resolves the owner via property "userId"', function() {
var user; let user;
var Album = app.registry.createModel('Album', { const Album = app.registry.createModel('Album', {
name: String, name: String,
userId: Number, userId: Number,
}); });
@ -601,8 +601,8 @@ describe('role model', function() {
}); });
it('resolves the owner via property "owner"', function() { it('resolves the owner via property "owner"', function() {
var user; let user;
var Album = app.registry.createModel('Album', { const Album = app.registry.createModel('Album', {
name: String, name: String,
owner: Number, owner: Number,
}); });
@ -627,11 +627,11 @@ describe('role model', function() {
it('resolves the owner via a belongsTo relation', function() { it('resolves the owner via a belongsTo relation', function() {
// passing no options will result calling // passing no options will result calling
// the legacy $owner role resolver behavior // the legacy $owner role resolver behavior
var Message = givenModelWithSenderReceiverRelations('ModelWithNoOptions'); const Message = givenModelWithSenderReceiverRelations('ModelWithNoOptions');
return givenUsers() return givenUsers()
.then(() => { .then(() => {
var messages = [ const messages = [
{content: 'firstMessage', senderId: sender.id}, {content: 'firstMessage', senderId: sender.id},
{content: 'secondMessage', receiverId: receiver.id}, {content: 'secondMessage', receiverId: receiver.id},
{content: 'thirdMessage'}, {content: 'thirdMessage'},
@ -658,8 +658,8 @@ describe('role model', function() {
}); });
it('resolves as false without belongsTo relation', function() { it('resolves as false without belongsTo relation', function() {
var user; let user;
var Album = app.registry.createModel( const Album = app.registry.createModel(
'Album', 'Album',
{ {
name: String, name: String,
@ -691,14 +691,14 @@ describe('role model', function() {
it('resolves the owner using the corrent belongsTo relation', function() { it('resolves the owner using the corrent belongsTo relation', function() {
// passing {ownerRelations: true} will enable the new $owner role resolver // passing {ownerRelations: true} will enable the new $owner role resolver
// with any belongsTo relation allowing to resolve truthy // with any belongsTo relation allowing to resolve truthy
var Message = givenModelWithSenderReceiverRelations( const Message = givenModelWithSenderReceiverRelations(
'ModelWithAllRelations', 'ModelWithAllRelations',
{ownerRelations: true} {ownerRelations: true}
); );
return givenUsers() return givenUsers()
.then(() => { .then(() => {
var messages = [ const messages = [
{content: 'firstMessage', senderId: sender.id}, {content: 'firstMessage', senderId: sender.id},
{content: 'secondMessage', receiverId: receiver.id}, {content: 'secondMessage', receiverId: receiver.id},
{content: 'thirdMessage'}, {content: 'thirdMessage'},
@ -727,14 +727,14 @@ describe('role model', function() {
function() { function() {
// passing {ownerRelations: true} will enable the new $owner role resolver // passing {ownerRelations: true} will enable the new $owner role resolver
// with a specified list of belongsTo relations allowing to resolve truthy // with a specified list of belongsTo relations allowing to resolve truthy
var Message = givenModelWithSenderReceiverRelations( const Message = givenModelWithSenderReceiverRelations(
'ModelWithCoercedRelations', 'ModelWithCoercedRelations',
{ownerRelations: ['receiver']} {ownerRelations: ['receiver']}
); );
return givenUsers() return givenUsers()
.then(() => { .then(() => {
var messages = [ const messages = [
{content: 'firstMessage', senderId: sender.id}, {content: 'firstMessage', senderId: sender.id},
{content: 'secondMessage', receiverId: receiver.id}, {content: 'secondMessage', receiverId: receiver.id},
{content: 'thirdMessage'}, {content: 'thirdMessage'},
@ -771,7 +771,7 @@ describe('role model', function() {
} }
function isOwnerForMessage(user, msg) { function isOwnerForMessage(user, msg) {
var accessContext = { const accessContext = {
principalType: ACL.USER, principalType: ACL.USER,
principalId: user.id, principalId: user.id,
model: msg.constructor, model: msg.constructor,
@ -788,7 +788,7 @@ describe('role model', function() {
} }
function givenModelWithSenderReceiverRelations(name, options) { function givenModelWithSenderReceiverRelations(name, options) {
var baseOptions = { const baseOptions = {
relations: { relations: {
sender: { sender: {
type: 'belongsTo', type: 'belongsTo',
@ -803,7 +803,7 @@ describe('role model', function() {
}, },
}; };
options = extend(baseOptions, options); options = extend(baseOptions, options);
var Model = app.registry.createModel( const Model = app.registry.createModel(
name, name,
{content: String}, {content: String},
options options
@ -843,7 +843,7 @@ describe('role model', function() {
}); });
describe('isMappedToRole', function() { describe('isMappedToRole', function() {
var user, app, role; let user, app, role;
beforeEach(function(done) { beforeEach(function(done) {
User.create({ User.create({
@ -873,7 +873,7 @@ describe('role model', function() {
if (err) return done(err); if (err) return done(err);
role = r; role = r;
var principals = [ const principals = [
{ {
principalType: ACL.USER, principalType: ACL.USER,
principalId: user.id, principalId: user.id,
@ -999,7 +999,7 @@ describe('role model', function() {
}); });
describe('listByPrincipalType', function() { describe('listByPrincipalType', function() {
var sandbox; let sandbox;
beforeEach(function() { beforeEach(function() {
sandbox = sinon.sandbox.create(); sandbox = sinon.sandbox.create();
@ -1010,27 +1010,26 @@ describe('role model', function() {
}); });
it('should fetch all models assigned to the role', function(done) { it('should fetch all models assigned to the role', function(done) {
var principalTypesToModels = {}; const principalTypesToModels = {};
var runs = 0; let runs = 0;
var mappings;
principalTypesToModels[RoleMapping.USER] = User; principalTypesToModels[RoleMapping.USER] = User;
principalTypesToModels[RoleMapping.APPLICATION] = Application; principalTypesToModels[RoleMapping.APPLICATION] = Application;
principalTypesToModels[RoleMapping.ROLE] = Role; principalTypesToModels[RoleMapping.ROLE] = Role;
mappings = Object.keys(principalTypesToModels); const mappings = Object.keys(principalTypesToModels);
mappings.forEach(function(principalType) { mappings.forEach(function(principalType) {
var Model = principalTypesToModels[principalType]; const Model = principalTypesToModels[principalType];
Model.create({name: 'test', email: 'x@y.com', password: 'foobar'}, function(err, model) { Model.create({name: 'test', email: 'x@y.com', password: 'foobar'}, function(err, model) {
if (err) return done(err); if (err) return done(err);
var uniqueRoleName = 'testRoleFor' + principalType; const uniqueRoleName = 'testRoleFor' + principalType;
Role.create({name: uniqueRoleName}, function(err, role) { Role.create({name: uniqueRoleName}, function(err, role) {
if (err) return done(err); if (err) return done(err);
role.principals.create({principalType: principalType, principalId: model.id}, role.principals.create({principalType: principalType, principalId: model.id},
function(err, p) { function(err, p) {
if (err) return done(err); if (err) return done(err);
var pluralName = Model.pluralModelName.toLowerCase(); const pluralName = Model.pluralModelName.toLowerCase();
role[pluralName](function(err, models) { role[pluralName](function(err, models) {
if (err) return done(err); if (err) return done(err);
assert.equal(models.length, 1); assert.equal(models.length, 1);
@ -1046,16 +1045,16 @@ describe('role model', function() {
}); });
it('should fetch all models only assigned to the role', function(done) { it('should fetch all models only assigned to the role', function(done) {
var principalTypesToModels = {}; const principalTypesToModels = {};
var mappings;
principalTypesToModels[RoleMapping.USER] = User; principalTypesToModels[RoleMapping.USER] = User;
principalTypesToModels[RoleMapping.APPLICATION] = Application; principalTypesToModels[RoleMapping.APPLICATION] = Application;
principalTypesToModels[RoleMapping.ROLE] = Role; principalTypesToModels[RoleMapping.ROLE] = Role;
mappings = Object.keys(principalTypesToModels);
const mappings = Object.keys(principalTypesToModels);
async.each(mappings, function(principalType, eachCallback) { async.each(mappings, function(principalType, eachCallback) {
var Model = principalTypesToModels[principalType]; const Model = principalTypesToModels[principalType];
async.waterfall([ async.waterfall([
// Create models // Create models
@ -1072,8 +1071,8 @@ describe('role model', function() {
// Create Roles // Create Roles
function(models, next) { function(models, next) {
var uniqueRoleName = 'testRoleFor' + principalType; const uniqueRoleName = 'testRoleFor' + principalType;
var otherUniqueRoleName = 'otherTestRoleFor' + principalType; const otherUniqueRoleName = 'otherTestRoleFor' + principalType;
Role.create([ Role.create([
{name: uniqueRoleName}, {name: uniqueRoleName},
{name: otherUniqueRoleName}], {name: otherUniqueRoleName}],
@ -1111,8 +1110,8 @@ describe('role model', function() {
// Run tests against unique Role // Run tests against unique Role
function(models, roles, principles, next) { function(models, roles, principles, next) {
var pluralName = Model.pluralModelName.toLowerCase(); const pluralName = Model.pluralModelName.toLowerCase();
var uniqueRole = roles[0]; const uniqueRole = roles[0];
uniqueRole[pluralName](function(err, models) { uniqueRole[pluralName](function(err, models) {
if (err) return done(err); if (err) return done(err);
assert.equal(models.length, 1); assert.equal(models.length, 1);
@ -1133,7 +1132,7 @@ describe('role model', function() {
role.principals.create({principalType: RoleMapping.USER, principalId: user.id}, role.principals.create({principalType: RoleMapping.USER, principalId: user.id},
function(err, p) { function(err, p) {
if (err) return done(err); if (err) return done(err);
var query = {fields: ['id', 'name']}; const query = {fields: ['id', 'name']};
sandbox.spy(User, 'find'); sandbox.spy(User, 'find');
role.users(query, function(err, users) { role.users(query, function(err, users) {
if (err) return done(err); if (err) return done(err);
@ -1149,12 +1148,12 @@ describe('role model', function() {
}); });
it('supports Promise API', function(done) { it('supports Promise API', function(done) {
var userData = {name: 'Raymond', email: 'x@y.com', password: 'foobar'}; const userData = {name: 'Raymond', email: 'x@y.com', password: 'foobar'};
User.create(userData, function(err, user) { User.create(userData, function(err, user) {
if (err) return done(err); if (err) return done(err);
Role.create({name: 'userRole'}, function(err, role) { Role.create({name: 'userRole'}, function(err, role) {
if (err) return done(err); if (err) return done(err);
var principalData = { const principalData = {
principalType: RoleMapping.USER, principalType: RoleMapping.USER,
principalId: user.id, principalId: user.id,
}; };
@ -1162,7 +1161,7 @@ describe('role model', function() {
if (err) return done(err); if (err) return done(err);
role.users() role.users()
.then(function(users) { .then(function(users) {
var userIds = users.map(function(u) { return u.id; }); const userIds = users.map(function(u) { return u.id; });
expect(userIds).to.eql([user.id]); expect(userIds).to.eql([user.id]);
done(); done();
}) })
@ -1175,19 +1174,19 @@ describe('role model', function() {
describe('isOwner', function() { describe('isOwner', function() {
it('supports app-local model registry', function(done) { it('supports app-local model registry', function(done) {
var app = loopback({localRegistry: true, loadBuiltinModels: true}); const app = loopback({localRegistry: true, loadBuiltinModels: true});
app.dataSource('db', {connector: 'memory'}); app.dataSource('db', {connector: 'memory'});
// attach all auth-related models to 'db' datasource // attach all auth-related models to 'db' datasource
app.enableAuth({dataSource: 'db'}); app.enableAuth({dataSource: 'db'});
var Role = app.models.Role; const Role = app.models.Role;
var User = app.models.User; const User = app.models.User;
// Speed up the password hashing algorithm for tests // Speed up the password hashing algorithm for tests
User.settings.saltWorkFactor = 4; User.settings.saltWorkFactor = 4;
var u = app.registry.findModel('User'); const u = app.registry.findModel('User');
var credentials = {email: 'test@example.com', password: 'pass'}; const credentials = {email: 'test@example.com', password: 'pass'};
User.create(credentials, function(err, user) { User.create(credentials, function(err, user) {
if (err) return done(err); if (err) return done(err);
@ -1202,7 +1201,7 @@ describe('role model', function() {
}); });
it('supports Promise API', function(done) { it('supports Promise API', function(done) {
var credentials = {email: 'test@example.com', password: 'pass'}; const credentials = {email: 'test@example.com', password: 'pass'};
User.create(credentials, function(err, user) { User.create(credentials, function(err, user) {
if (err) return done(err); if (err) return done(err);

View File

@ -4,12 +4,12 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../'); const loopback = require('../');
var lt = require('./helpers/loopback-testing-helper'); const lt = require('./helpers/loopback-testing-helper');
var path = require('path'); const path = require('path');
var SIMPLE_APP = path.join(__dirname, 'fixtures', 'user-integration-app'); const SIMPLE_APP = path.join(__dirname, 'fixtures', 'user-integration-app');
var app = require(path.join(SIMPLE_APP, 'server/server.js')); const app = require(path.join(SIMPLE_APP, 'server/server.js'));
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
const Promise = require('bluebird'); const Promise = require('bluebird');
const waitForEvent = require('./helpers/wait-for-event'); const waitForEvent = require('./helpers/wait-for-event');
@ -33,7 +33,7 @@ describe('users - integration', function() {
}); });
describe('base-user', function() { describe('base-user', function() {
var userId, accessToken; let userId, accessToken;
it('should create a new user', function(done) { it('should create a new user', function(done) {
this.post('/api/users') this.post('/api/users')
@ -49,7 +49,7 @@ describe('users - integration', function() {
}); });
it('should log into the user', function(done) { it('should log into the user', function(done) {
var url = '/api/users/login'; const url = '/api/users/login';
this.post(url) this.post(url)
.send({username: 'x', email: 'x@y.com', password: 'x'}) .send({username: 'x', email: 'x@y.com', password: 'x'})
@ -97,7 +97,7 @@ describe('users - integration', function() {
}); });
it('should create post for a given user', function(done) { it('should create post for a given user', function(done) {
var url = '/api/users/' + userId + '/posts?access_token=' + accessToken; const url = '/api/users/' + userId + '/posts?access_token=' + accessToken;
this.post(url) this.post(url)
.send({title: 'T1', content: 'C1'}) .send({title: 'T1', content: 'C1'})
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -114,13 +114,13 @@ describe('users - integration', function() {
// FIXME: [rfeng] The test is passing if run alone. But it fails with // FIXME: [rfeng] The test is passing if run alone. But it fails with
// `npm test` as the loopback models are polluted by other tests // `npm test` as the loopback models are polluted by other tests
it('should prevent access tokens from being included', function(done) { it('should prevent access tokens from being included', function(done) {
var url = '/api/posts?filter={"include":{"user":"accessTokens"}}'; const url = '/api/posts?filter={"include":{"user":"accessTokens"}}';
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
if (err) return done(err); if (err) return done(err);
expect(res.body).to.have.property('length', 1); expect(res.body).to.have.property('length', 1);
var post = res.body[0]; const post = res.body[0];
expect(post.user).to.have.property('username', 'x'); expect(post.user).to.have.property('username', 'x');
expect(post.user).to.not.have.property('accessTokens'); expect(post.user).to.not.have.property('accessTokens');
@ -129,8 +129,8 @@ describe('users - integration', function() {
}); });
it('should preserve current session when invalidating tokens', function(done) { it('should preserve current session when invalidating tokens', function(done) {
var url = '/api/users/' + userId; const url = '/api/users/' + userId;
var self = this; const self = this;
this.patch(url) this.patch(url)
.send({email: 'new@example.com'}) .send({email: 'new@example.com'})
.set('Authorization', accessToken) .set('Authorization', accessToken)
@ -274,10 +274,10 @@ describe('users - integration', function() {
}); });
describe('sub-user', function() { describe('sub-user', function() {
var userId, accessToken; let userId, accessToken;
it('should create a new user', function(done) { it('should create a new user', function(done) {
var url = '/api/myUsers'; const url = '/api/myUsers';
this.post(url) this.post(url)
.send({username: 'x', email: 'x@y.com', password: 'x'}) .send({username: 'x', email: 'x@y.com', password: 'x'})
@ -292,7 +292,7 @@ describe('users - integration', function() {
}); });
it('should log into the user', function(done) { it('should log into the user', function(done) {
var url = '/api/myUsers/login'; const url = '/api/myUsers/login';
this.post(url) this.post(url)
.send({username: 'x', email: 'x@y.com', password: 'x'}) .send({username: 'x', email: 'x@y.com', password: 'x'})
@ -307,7 +307,7 @@ describe('users - integration', function() {
}); });
it('should create blog for a given user', function(done) { it('should create blog for a given user', function(done) {
var url = '/api/myUsers/' + userId + '/blogs?access_token=' + accessToken; const url = '/api/myUsers/' + userId + '/blogs?access_token=' + accessToken;
this.post(url) this.post(url)
.send({title: 'T1', content: 'C1'}) .send({title: 'T1', content: 'C1'})
.expect(200, function(err, res) { .expect(200, function(err, res) {
@ -325,13 +325,13 @@ describe('users - integration', function() {
}); });
it('should prevent access tokens from being included', function(done) { it('should prevent access tokens from being included', function(done) {
var url = '/api/blogs?filter={"include":{"user":"accessTokens"}}'; const url = '/api/blogs?filter={"include":{"user":"accessTokens"}}';
this.get(url) this.get(url)
.expect(200, function(err, res) { .expect(200, function(err, res) {
if (err) return done(err); if (err) return done(err);
expect(res.body).to.have.property('length', 1); expect(res.body).to.have.property('length', 1);
var blog = res.body[0]; const blog = res.body[0];
expect(blog.user).to.have.property('username', 'x'); expect(blog.user).to.have.property('username', 'x');
expect(blog.user).to.not.have.property('accessTokens'); expect(blog.user).to.not.have.property('accessTokens');

View File

@ -4,41 +4,41 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var expect = require('./helpers/expect'); const expect = require('./helpers/expect');
var request = require('supertest'); const request = require('supertest');
var loopback = require('../'); const loopback = require('../');
var async = require('async'); const async = require('async');
var url = require('url'); const url = require('url');
var extend = require('util')._extend; const extend = require('util')._extend;
const Promise = require('bluebird'); const Promise = require('bluebird');
const waitForEvent = require('./helpers/wait-for-event'); const waitForEvent = require('./helpers/wait-for-event');
var User, AccessToken; let User, AccessToken;
describe('User', function() { describe('User', function() {
this.timeout(10000); this.timeout(10000);
var validCredentialsEmail = 'foo@bar.com'; const validCredentialsEmail = 'foo@bar.com';
var validCredentials = {email: validCredentialsEmail, password: 'bar'}; const validCredentials = {email: validCredentialsEmail, password: 'bar'};
var validCredentialsEmailVerified = { const validCredentialsEmailVerified = {
email: 'foo1@bar.com', password: 'bar1', emailVerified: true}; email: 'foo1@bar.com', password: 'bar1', emailVerified: true};
var validCredentialsEmailVerifiedOverREST = { const validCredentialsEmailVerifiedOverREST = {
email: 'foo2@bar.com', password: 'bar2', emailVerified: true}; email: 'foo2@bar.com', password: 'bar2', emailVerified: true};
var validCredentialsWithRealm = { const validCredentialsWithRealm = {
email: 'foo3@bar.com', password: 'bar', realm: 'foobar'}; email: 'foo3@bar.com', password: 'bar', realm: 'foobar'};
var validCredentialsWithTTL = {email: 'foo@bar.com', password: 'bar', ttl: 3600}; const validCredentialsWithTTL = {email: 'foo@bar.com', password: 'bar', ttl: 3600};
var validCredentialsWithTTLAndScope = { const validCredentialsWithTTLAndScope = {
email: 'foo@bar.com', password: 'bar', ttl: 3600, scope: 'all'}; email: 'foo@bar.com', password: 'bar', ttl: 3600, scope: 'all'};
var validMixedCaseEmailCredentials = {email: 'Foo@bar.com', password: 'bar'}; const validMixedCaseEmailCredentials = {email: 'Foo@bar.com', password: 'bar'};
var invalidCredentials = {email: 'foo1@bar.com', password: 'invalid'}; const invalidCredentials = {email: 'foo1@bar.com', password: 'invalid'};
var incompleteCredentials = {password: 'bar1'}; const incompleteCredentials = {password: 'bar1'};
var validCredentialsUser, validCredentialsEmailVerifiedUser, user; let validCredentialsUser, validCredentialsEmailVerifiedUser, user;
// Create a local app variable to prevent clashes with the global // Create a local app variable to prevent clashes with the global
// variable shared by all tests. While this should not be necessary if // variable shared by all tests. While this should not be necessary if
// the tests were written correctly, it turns out that's not the case :( // the tests were written correctly, it turns out that's not the case :(
var app = null; let app = null;
beforeEach(function setupAppAndModels() { beforeEach(function setupAppAndModels() {
// override the global app object provided by test/support.js // override the global app object provided by test/support.js
@ -52,7 +52,7 @@ describe('User', function() {
connector: loopback.Mail, connector: loopback.Mail,
transports: [{type: 'STUB'}], transports: [{type: 'STUB'}],
}); });
var Email = app.registry.getModel('Email'); const Email = app.registry.getModel('Email');
app.model(Email, {dataSource: 'email'}); app.model(Email, {dataSource: 'email'});
// attach User and related models // attach User and related models
@ -167,7 +167,7 @@ describe('User', function() {
// will change in future versions where password will be optional by default // will change in future versions where password will be optional by default
it('Password is required', function(done) { it('Password is required', function(done) {
var u = new User({email: '123@456.com'}); const u = new User({email: '123@456.com'});
User.create({email: 'c@d.com'}, function(err) { User.create({email: 'c@d.com'}, function(err) {
assert(err); assert(err);
@ -252,19 +252,19 @@ describe('User', function() {
}); });
it('Hashes the given password', function() { it('Hashes the given password', function() {
var u = new User({username: 'foo', password: 'bar'}); const u = new User({username: 'foo', password: 'bar'});
assert(u.password !== 'bar'); assert(u.password !== 'bar');
}); });
it('does not hash the password if it\'s already hashed', function() { it('does not hash the password if it\'s already hashed', function() {
var u1 = new User({username: 'foo', password: 'bar'}); const u1 = new User({username: 'foo', password: 'bar'});
assert(u1.password !== 'bar'); assert(u1.password !== 'bar');
var u2 = new User({username: 'foo', password: u1.password}); const u2 = new User({username: 'foo', password: u1.password});
assert(u2.password === u1.password); assert(u2.password === u1.password);
}); });
it('invalidates the user\'s accessToken when the user is deleted By id', function(done) { it('invalidates the user\'s accessToken when the user is deleted By id', function(done) {
var usersId; let usersId;
async.series([ async.series([
function(next) { function(next) {
User.create({email: 'b@c.com', password: 'bar'}, function(err, user) { User.create({email: 'b@c.com', password: 'bar'}, function(err, user) {
@ -319,8 +319,8 @@ describe('User', function() {
}); });
it('invalidates the user\'s accessToken when the user is deleted all', function(done) { it('invalidates the user\'s accessToken when the user is deleted all', function(done) {
var userIds = []; let userIds = [];
var users; let users;
async.series([ async.series([
function(next) { function(next) {
User.create([ User.create([
@ -371,7 +371,7 @@ describe('User', function() {
}); });
describe('custom password hash', function() { describe('custom password hash', function() {
var defaultHashPassword, defaultValidatePassword; let defaultHashPassword, defaultValidatePassword;
beforeEach(function() { beforeEach(function() {
defaultHashPassword = User.hashPassword; defaultHashPassword = User.hashPassword;
@ -396,7 +396,7 @@ describe('User', function() {
it('Reports invalid password', function() { it('Reports invalid password', function() {
try { try {
var u = new User({username: 'foo', password: 'aa'}); const u = new User({username: 'foo', password: 'aa'});
assert(false, 'Error should have been thrown'); assert(false, 'Error should have been thrown');
} catch (e) { } catch (e) {
// Ignore // Ignore
@ -404,7 +404,7 @@ describe('User', function() {
}); });
it('Hashes the given password', function() { it('Hashes the given password', function() {
var u = new User({username: 'foo', password: 'bar'}); const u = new User({username: 'foo', password: 'bar'});
assert(u.password === 'BAR'); assert(u.password === 'BAR');
}); });
}); });
@ -426,9 +426,9 @@ describe('User', function() {
}); });
describe('Password length validation', function() { describe('Password length validation', function() {
var pass72Char = new Array(70).join('a') + '012'; const pass72Char = new Array(70).join('a') + '012';
var pass73Char = pass72Char + '3'; const pass73Char = pass72Char + '3';
var passTooLong = pass72Char + 'WXYZ1234'; const passTooLong = pass72Char + 'WXYZ1234';
it('rejects empty passwords creation', function(done) { it('rejects empty passwords creation', function(done) {
User.create({email: 'b@c.com', password: ''}, function(err) { User.create({email: 'b@c.com', password: ''}, function(err) {
@ -492,7 +492,7 @@ describe('User', function() {
it('rejects a new user with password longer than 72 characters', function(done) { it('rejects a new user with password longer than 72 characters', function(done) {
try { try {
var u = new User({username: 'foo', password: pass73Char}); const u = new User({username: 'foo', password: pass73Char});
assert(false, 'Error should have been thrown'); assert(false, 'Error should have been thrown');
} catch (e) { } catch (e) {
expect(e).to.match(/password entered was too long/); expect(e).to.match(/password entered was too long/);
@ -597,7 +597,7 @@ describe('User', function() {
it('Should be able to use query filters (email case-sensitivity off)', function(done) { it('Should be able to use query filters (email case-sensitivity off)', function(done) {
User.settings.caseSensitiveEmail = false; User.settings.caseSensitiveEmail = false;
var insensitiveUser = {email: 'insensitive@example.com', password: 'abc'}; const insensitiveUser = {email: 'insensitive@example.com', password: 'abc'};
User.create(insensitiveUser, function(err, user) { User.create(insensitiveUser, function(err, user) {
User.find({where: {email: User.find({where: {email:
{inq: [insensitiveUser.email]}, {inq: [insensitiveUser.email]},
@ -612,7 +612,7 @@ describe('User', function() {
it('Should be able to use query filters (email case-sensitivity on)', function(done) { it('Should be able to use query filters (email case-sensitivity on)', function(done) {
User.settings.caseSensitiveEmail = true; User.settings.caseSensitiveEmail = true;
var sensitiveUser = {email: 'senSiTive@example.com', password: 'abc'}; const sensitiveUser = {email: 'senSiTive@example.com', password: 'abc'};
User.create(sensitiveUser, function(err, user) { User.create(sensitiveUser, function(err, user) {
User.find({where: {email: User.find({where: {email:
{inq: [sensitiveUser.email]}, {inq: [sensitiveUser.email]},
@ -729,7 +729,7 @@ describe('User', function() {
}); });
it('Login a user using a custom createAccessToken', function(done) { it('Login a user using a custom createAccessToken', function(done) {
var createToken = User.prototype.createAccessToken; // Save the original method const createToken = User.prototype.createAccessToken; // Save the original method
// Override createAccessToken // Override createAccessToken
User.prototype.createAccessToken = function(ttl, cb) { User.prototype.createAccessToken = function(ttl, cb) {
// Reduce the ttl by half for testing purpose // Reduce the ttl by half for testing purpose
@ -754,7 +754,7 @@ describe('User', function() {
it('Login a user using a custom createAccessToken with options', it('Login a user using a custom createAccessToken with options',
function(done) { function(done) {
var createToken = User.prototype.createAccessToken; // Save the original method const createToken = User.prototype.createAccessToken; // Save the original method
// Override createAccessToken // Override createAccessToken
User.prototype.createAccessToken = function(ttl, options, cb) { User.prototype.createAccessToken = function(ttl, options, cb) {
// Reduce the ttl by half for testing purpose // Reduce the ttl by half for testing purpose
@ -837,7 +837,7 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var accessToken = res.body; const accessToken = res.body;
assertGoodToken(accessToken, validCredentialsUser); assertGoodToken(accessToken, validCredentialsUser);
assert(accessToken.user === undefined); assert(accessToken.user === undefined);
@ -855,7 +855,7 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert.equal(errorResponse.code, 'LOGIN_FAILED'); assert.equal(errorResponse.code, 'LOGIN_FAILED');
done(); done();
@ -871,7 +871,7 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert.equal(errorResponse.code, 'USERNAME_EMAIL_REQUIRED'); assert.equal(errorResponse.code, 'USERNAME_EMAIL_REQUIRED');
done(); done();
@ -888,7 +888,7 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert.equal(errorResponse.code, 'USERNAME_EMAIL_REQUIRED'); assert.equal(errorResponse.code, 'USERNAME_EMAIL_REQUIRED');
done(); done();
@ -904,7 +904,7 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var token = res.body; const token = res.body;
expect(token.user, 'body.user').to.not.equal(undefined); expect(token.user, 'body.user').to.not.equal(undefined);
expect(token.user, 'body.user') expect(token.user, 'body.user')
.to.have.property('email', validCredentials.email); .to.have.property('email', validCredentials.email);
@ -922,7 +922,7 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var token = res.body; const token = res.body;
expect(token.user, 'body.user').to.not.equal(undefined); expect(token.user, 'body.user').to.not.equal(undefined);
expect(token.user, 'body.user') expect(token.user, 'body.user')
.to.have.property('email', validCredentials.email); .to.have.property('email', validCredentials.email);
@ -933,9 +933,9 @@ describe('User', function() {
it('allows login with password too long but created in old LB version', it('allows login with password too long but created in old LB version',
function(done) { function(done) {
var bcrypt = require('bcryptjs'); const bcrypt = require('bcryptjs');
var longPassword = new Array(80).join('a'); const longPassword = new Array(80).join('a');
var oldHash = bcrypt.hashSync(longPassword, bcrypt.genSaltSync(1)); const oldHash = bcrypt.hashSync(longPassword, bcrypt.genSaltSync(1));
User.create({email: 'b@c.com', password: oldHash}, function(err) { User.create({email: 'b@c.com', password: oldHash}, function(err) {
if (err) return done(err); if (err) return done(err);
@ -1047,7 +1047,7 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var accessToken = res.body; const accessToken = res.body;
assertGoodToken(accessToken, validCredentialsEmailVerifiedUser); assertGoodToken(accessToken, validCredentialsEmailVerifiedUser);
assert(accessToken.user === undefined); assert(accessToken.user === undefined);
@ -1070,7 +1070,7 @@ describe('User', function() {
// strongloop/loopback#931 // strongloop/loopback#931
// error message should be "login failed" // error message should be "login failed"
// and not "login failed as the email has not been verified" // and not "login failed as the email has not been verified"
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert(errorResponse && !/verified/.test(errorResponse.message), assert(errorResponse && !/verified/.test(errorResponse.message),
'expecting "login failed" error message, received: "' + errorResponse.message + '"'); 'expecting "login failed" error message, received: "' + errorResponse.message + '"');
assert.equal(errorResponse.code, 'LOGIN_FAILED'); assert.equal(errorResponse.code, 'LOGIN_FAILED');
@ -1091,10 +1091,10 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var errorResponse = res.body.error; const errorResponse = res.body.error;
// extracting code and details error response // extracting code and details error response
let errorExcerpts = { const errorExcerpts = {
code: errorResponse.code, code: errorResponse.code,
details: errorResponse.details, details: errorResponse.details,
}; };
@ -1112,7 +1112,7 @@ describe('User', function() {
}); });
describe('User.login requiring realm', function() { describe('User.login requiring realm', function() {
var User, AccessToken; let User, AccessToken;
beforeEach(function() { beforeEach(function() {
User = app.registry.createModel('RealmUser', {}, { User = app.registry.createModel('RealmUser', {}, {
@ -1136,57 +1136,57 @@ describe('User', function() {
User.setMaxListeners(0); User.setMaxListeners(0);
}); });
var realm1User = { const realm1User = {
realm: 'realm1', realm: 'realm1',
username: 'foo100', username: 'foo100',
email: 'foo100@bar.com', email: 'foo100@bar.com',
password: 'pass100', password: 'pass100',
}; };
var realm2User = { const realm2User = {
realm: 'realm2', realm: 'realm2',
username: 'foo100', username: 'foo100',
email: 'foo100@bar.com', email: 'foo100@bar.com',
password: 'pass200', password: 'pass200',
}; };
var credentialWithoutRealm = { const credentialWithoutRealm = {
username: 'foo100', username: 'foo100',
email: 'foo100@bar.com', email: 'foo100@bar.com',
password: 'pass100', password: 'pass100',
}; };
var credentialWithBadPass = { const credentialWithBadPass = {
realm: 'realm1', realm: 'realm1',
username: 'foo100', username: 'foo100',
email: 'foo100@bar.com', email: 'foo100@bar.com',
password: 'pass001', password: 'pass001',
}; };
var credentialWithBadRealm = { const credentialWithBadRealm = {
realm: 'realm3', realm: 'realm3',
username: 'foo100', username: 'foo100',
email: 'foo100@bar.com', email: 'foo100@bar.com',
password: 'pass100', password: 'pass100',
}; };
var credentialWithRealm = { const credentialWithRealm = {
realm: 'realm1', realm: 'realm1',
username: 'foo100', username: 'foo100',
password: 'pass100', password: 'pass100',
}; };
var credentialRealmInUsername = { const credentialRealmInUsername = {
username: 'realm1:foo100', username: 'realm1:foo100',
password: 'pass100', password: 'pass100',
}; };
var credentialRealmInEmail = { const credentialRealmInEmail = {
email: 'realm1:foo100@bar.com', email: 'realm1:foo100@bar.com',
password: 'pass100', password: 'pass100',
}; };
var user1 = null; let user1 = null;
beforeEach(function(done) { beforeEach(function(done) {
User.create(realm1User, function(err, u) { User.create(realm1User, function(err, u) {
if (err) return done(err); if (err) return done(err);
@ -1326,7 +1326,7 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var accessToken = res.body; const accessToken = res.body;
assertGoodToken(accessToken, validCredentialsUser); assertGoodToken(accessToken, validCredentialsUser);
fn(null, accessToken.id); fn(null, accessToken.id);
@ -1375,7 +1375,7 @@ describe('User', function() {
describe('user.hasPassword(plain, fn)', function() { describe('user.hasPassword(plain, fn)', function() {
it('Determine if the password matches the stored password', function(done) { it('Determine if the password matches the stored password', function(done) {
var u = new User({username: 'foo', password: 'bar'}); const u = new User({username: 'foo', password: 'bar'});
u.hasPassword('bar', function(err, isMatch) { u.hasPassword('bar', function(err, isMatch) {
assert(isMatch, 'password doesnt match'); assert(isMatch, 'password doesnt match');
@ -1384,7 +1384,7 @@ describe('User', function() {
}); });
it('Determine if the password matches the stored password - promise variant', function(done) { it('Determine if the password matches the stored password - promise variant', function(done) {
var u = new User({username: 'foo', password: 'bar'}); const u = new User({username: 'foo', password: 'bar'});
u.hasPassword('bar') u.hasPassword('bar')
.then(function(isMatch) { .then(function(isMatch) {
assert(isMatch, 'password doesnt match'); assert(isMatch, 'password doesnt match');
@ -1397,7 +1397,7 @@ describe('User', function() {
}); });
it('should match a password when saved', function(done) { it('should match a password when saved', function(done) {
var u = new User({username: 'a', password: 'b', email: 'z@z.net'}); const u = new User({username: 'a', password: 'b', email: 'z@z.net'});
u.save(function(err, user) { u.save(function(err, user) {
User.findById(user.pk, function(err, uu) { User.findById(user.pk, function(err, uu) {
@ -1679,7 +1679,7 @@ describe('User', function() {
type: 'email', type: 'email',
from: 'test@example.com', from: 'test@example.com',
}; };
var verifyOptions = Object.assign({}, defaultOptions); const verifyOptions = Object.assign({}, defaultOptions);
const user = new User({ const user = new User({
email: 'example@example.com', email: 'example@example.com',
password: 'pass', password: 'pass',
@ -1696,7 +1696,7 @@ describe('User', function() {
from: 'test@example.com', from: 'test@example.com',
}; };
User.settings.verifyOptions = Object.assign({}, defaultOptions); User.settings.verifyOptions = Object.assign({}, defaultOptions);
var verifyOptions = User.getVerifyOptions(); const verifyOptions = User.getVerifyOptions();
verifyOptions.from = 'newTest@example.com'; verifyOptions.from = 'newTest@example.com';
verifyOptions.test = 'test'; verifyOptions.test = 'test';
expect(User.getVerifyOptions()).to.eql(defaultOptions); expect(User.getVerifyOptions()).to.eql(defaultOptions);
@ -1727,7 +1727,7 @@ describe('User', function() {
assert(result.email); assert(result.email);
assert(result.email.response); assert(result.email.response);
assert(result.token); assert(result.token);
var msg = result.email.response.toString('utf-8'); const msg = result.email.response.toString('utf-8');
assert(~msg.indexOf('/api/test-users/confirm')); assert(~msg.indexOf('/api/test-users/confirm'));
assert(~msg.indexOf('To: bar@bat.com')); assert(~msg.indexOf('To: bar@bat.com'));
@ -1754,7 +1754,7 @@ describe('User', function() {
assert(result.email); assert(result.email);
assert(result.email.response); assert(result.email.response);
assert(result.token); assert(result.token);
var msg = result.email.response.toString('utf-8'); const msg = result.email.response.toString('utf-8');
assert(~msg.indexOf('/api/test-users/confirm')); assert(~msg.indexOf('/api/test-users/confirm'));
assert(~msg.indexOf('To: bar@bat.com')); assert(~msg.indexOf('To: bar@bat.com'));
@ -1811,7 +1811,7 @@ describe('User', function() {
assert(result.email); assert(result.email);
assert(result.email.response); assert(result.email.response);
assert(result.token); assert(result.token);
var msg = result.email.response.toString('utf-8'); const msg = result.email.response.toString('utf-8');
assert(~msg.indexOf('/api/test-users/confirm')); assert(~msg.indexOf('/api/test-users/confirm'));
assert(~msg.indexOf('custom template')); assert(~msg.indexOf('custom template'));
assert(~msg.indexOf('To: bar@bat.com')); assert(~msg.indexOf('To: bar@bat.com'));
@ -1889,7 +1889,7 @@ describe('User', function() {
assert(result.email.response); assert(result.email.response);
assert(result.token); assert(result.token);
assert.equal(result.token, 'token-123456'); assert.equal(result.token, 'token-123456');
var msg = result.email.response.toString('utf-8'); const msg = result.email.response.toString('utf-8');
assert(~msg.indexOf('token-123456')); assert(~msg.indexOf('token-123456'));
done(); done();
@ -1947,7 +1947,7 @@ describe('User', function() {
}); });
user.verify(verifyOptions, function(err, result) { user.verify(verifyOptions, function(err, result) {
var msg = result.email.response.toString('utf-8'); const msg = result.email.response.toString('utf-8');
assert(~msg.indexOf('http://myapp.org:3000/')); assert(~msg.indexOf('http://myapp.org:3000/'));
done(); done();
@ -1974,7 +1974,7 @@ describe('User', function() {
}); });
user.verify(verifyOptions, function(err, result) { user.verify(verifyOptions, function(err, result) {
var msg = result.email.response.toString('utf-8'); const msg = result.email.response.toString('utf-8');
assert(~msg.indexOf('http://myapp.org/')); assert(~msg.indexOf('http://myapp.org/'));
done(); done();
@ -2002,7 +2002,7 @@ describe('User', function() {
}); });
user.verify(verifyOptions, function(err, result) { user.verify(verifyOptions, function(err, result) {
var msg = result.email.response.toString('utf-8'); const msg = result.email.response.toString('utf-8');
assert(~msg.indexOf('https://myapp.org:3000/')); assert(~msg.indexOf('https://myapp.org:3000/'));
done(); done();
@ -2030,7 +2030,7 @@ describe('User', function() {
}); });
user.verify(verifyOptions, function(err, result) { user.verify(verifyOptions, function(err, result) {
var msg = result.email.response.toString('utf-8'); const msg = result.email.response.toString('utf-8');
assert(~msg.indexOf('https://myapp.org/')); assert(~msg.indexOf('https://myapp.org/'));
done(); done();
@ -2049,19 +2049,19 @@ describe('User', function() {
}); });
it('hides verification tokens from user JSON', function(done) { it('hides verification tokens from user JSON', function(done) {
var user = new User({ const user = new User({
email: 'bar@bat.com', email: 'bar@bat.com',
password: 'bar', password: 'bar',
verificationToken: 'a-token', verificationToken: 'a-token',
}); });
var data = user.toJSON(); const data = user.toJSON();
assert(!('verificationToken' in data)); assert(!('verificationToken' in data));
done(); done();
}); });
it('squashes "//" when restApiRoot is "/"', function(done) { it('squashes "//" when restApiRoot is "/"', function(done) {
var emailBody; let emailBody;
User.afterRemote('create', function(ctx, user, next) { User.afterRemote('create', function(ctx, user, next) {
assert(user, 'afterRemote should include result'); assert(user, 'afterRemote should include result');
@ -2092,7 +2092,7 @@ describe('User', function() {
}); });
it('removes "verifyOptions.template" from Email payload', function() { it('removes "verifyOptions.template" from Email payload', function() {
var MailerMock = { const MailerMock = {
send: function(verifyOptions, cb) { cb(null, verifyOptions); }, send: function(verifyOptions, cb) { cb(null, verifyOptions); },
}; };
verifyOptions.mailer = MailerMock; verifyOptions.mailer = MailerMock;
@ -2117,7 +2117,7 @@ describe('User', function() {
return user.verify(verifyOptions) return user.verify(verifyOptions)
.then(() => actualVerifyHref) .then(() => actualVerifyHref)
.then(verifyHref => { .then(verifyHref => {
var parsed = url.parse(verifyHref, true); const parsed = url.parse(verifyHref, true);
expect(parsed.query.redirect, 'redirect query') expect(parsed.query.redirect, 'redirect query')
.to.equal('#/some-path?a=1&b=2'); .to.equal('#/some-path?a=1&b=2');
}); });
@ -2258,7 +2258,7 @@ describe('User', function() {
}); });
describe('User.confirm(options, fn)', function() { describe('User.confirm(options, fn)', function() {
var verifyOptions; let verifyOptions;
function testConfirm(testFunc, done) { function testConfirm(testFunc, done) {
User.afterRemote('create', function(ctx, user, next) { User.afterRemote('create', function(ctx, user, next) {
@ -2352,7 +2352,7 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert(errorResponse); assert(errorResponse);
assert.equal(errorResponse.code, 'USER_NOT_FOUND'); assert.equal(errorResponse.code, 'USER_NOT_FOUND');
@ -2371,7 +2371,7 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert(errorResponse); assert(errorResponse);
assert.equal(errorResponse.code, 'INVALID_TOKEN'); assert.equal(errorResponse.code, 'INVALID_TOKEN');
@ -2384,7 +2384,7 @@ describe('User', function() {
describe('Password Reset', function() { describe('Password Reset', function() {
describe('User.resetPassword(options, cb)', function() { describe('User.resetPassword(options, cb)', function() {
var options = { const options = {
email: 'foo@bar.com', email: 'foo@bar.com',
redirect: 'http://foobar.com/reset-password', redirect: 'http://foobar.com/reset-password',
}; };
@ -2422,7 +2422,7 @@ describe('User', function() {
}); });
it('Checks that options exist', function(done) { it('Checks that options exist', function(done) {
var calledBack = false; let calledBack = false;
User.resetPassword(options, function() { User.resetPassword(options, function() {
calledBack = true; calledBack = true;
@ -2438,7 +2438,7 @@ describe('User', function() {
}); });
it('Creates a temp accessToken to allow a user to change password', function(done) { it('Creates a temp accessToken to allow a user to change password', function(done) {
var calledBack = false; let calledBack = false;
User.resetPassword({ User.resetPassword({
email: options.email, email: options.email,
@ -2484,7 +2484,7 @@ describe('User', function() {
.end(function(err, res) { .end(function(err, res) {
if (err) return done(err); if (err) return done(err);
var errorResponse = res.body.error; const errorResponse = res.body.error;
assert(errorResponse); assert(errorResponse);
assert.equal(errorResponse.code, 'EMAIL_REQUIRED'); assert.equal(errorResponse.code, 'EMAIL_REQUIRED');
@ -2546,7 +2546,7 @@ describe('User', function() {
}); });
describe('User.resetPassword(options, cb) requiring realm', function() { describe('User.resetPassword(options, cb) requiring realm', function() {
var realmUser; let realmUser;
beforeEach(function(done) { beforeEach(function(done) {
User.create(validCredentialsWithRealm, function(err, u) { User.create(validCredentialsWithRealm, function(err, u) {
@ -2571,7 +2571,7 @@ describe('User', function() {
}); });
it('Creates a temp accessToken to allow user in realm to change password', function(done) { it('Creates a temp accessToken to allow user in realm to change password', function(done) {
var calledBack = false; let calledBack = false;
User.resetPassword({ User.resetPassword({
email: realmUser.email, email: realmUser.email,
@ -2600,10 +2600,10 @@ describe('User', function() {
}); });
describe('AccessToken (session) invalidation', function() { describe('AccessToken (session) invalidation', function() {
var user, originalUserToken1, originalUserToken2, newUserCreated; let user, originalUserToken1, originalUserToken2, newUserCreated;
var currentEmailCredentials = {email: 'original@example.com', password: 'bar'}; const currentEmailCredentials = {email: 'original@example.com', password: 'bar'};
var updatedEmailCredentials = {email: 'updated@example.com', password: 'bar'}; const updatedEmailCredentials = {email: 'updated@example.com', password: 'bar'};
var newUserCred = {email: 'newuser@example.com', password: 'newpass'}; const newUserCred = {email: 'newuser@example.com', password: 'newpass'};
beforeEach('create user then login', function createAndLogin(done) { beforeEach('create user then login', function createAndLogin(done) {
async.series([ async.series([
@ -2748,7 +2748,7 @@ describe('User', function() {
}); });
it('keeps sessions AS IS if non-email property is changed using updateAll', function(done) { it('keeps sessions AS IS if non-email property is changed using updateAll', function(done) {
var userPartial; let userPartial;
async.series([ async.series([
function createPartialUser(next) { function createPartialUser(next) {
User.create( User.create(
@ -2798,7 +2798,7 @@ describe('User', function() {
}); });
it('preserves other users\' sessions if their email is untouched', function(done) { it('preserves other users\' sessions if their email is untouched', function(done) {
var user1, user2, user3; let user1, user2, user3;
async.series([ async.series([
function(next) { function(next) {
User.create({email: 'user1@example.com', password: 'u1pass'}, function(err, u1) { User.create({email: 'user1@example.com', password: 'u1pass'}, function(err, u1) {
@ -2861,7 +2861,7 @@ describe('User', function() {
}); });
it('invalidates correct sessions after changing email using updateAll', function(done) { it('invalidates correct sessions after changing email using updateAll', function(done) {
var userSpecial, userNormal; let userSpecial, userNormal;
async.series([ async.series([
function createSpecialUser(next) { function createSpecialUser(next) {
User.create( User.create(
@ -2907,12 +2907,12 @@ describe('User', function() {
}); });
it('preserves current session', function(done) { it('preserves current session', function(done) {
var options = {accessToken: originalUserToken1}; const options = {accessToken: originalUserToken1};
user.updateAttribute('email', 'new@example.com', options, function(err) { user.updateAttribute('email', 'new@example.com', options, function(err) {
if (err) return done(err); if (err) return done(err);
AccessToken.find({where: {userId: user.pk}}, function(err, tokens) { AccessToken.find({where: {userId: user.pk}}, function(err, tokens) {
if (err) return done(err); if (err) return done(err);
var tokenIds = tokens.map(function(t) { return t.id; }); const tokenIds = tokens.map(function(t) { return t.id; });
expect(tokenIds).to.eql([originalUserToken1.id]); expect(tokenIds).to.eql([originalUserToken1.id]);
done(); done();
}); });
@ -2920,8 +2920,8 @@ describe('User', function() {
}); });
it('forwards the "options" argument', function(done) { it('forwards the "options" argument', function(done) {
var options = {testFlag: true}; const options = {testFlag: true};
var observedOptions = []; const observedOptions = [];
saveObservedOptionsForHook('access', User); saveObservedOptionsForHook('access', User);
saveObservedOptionsForHook('before delete', AccessToken); saveObservedOptionsForHook('before delete', AccessToken);
@ -2951,7 +2951,7 @@ describe('User', function() {
}); });
it('preserves other user sessions if their password is untouched', function(done) { it('preserves other user sessions if their password is untouched', function(done) {
var user1, user2, user1Token; let user1, user2, user1Token;
async.series([ async.series([
function(next) { function(next) {
User.create({email: 'user1@example.com', password: 'u1pass'}, function(err, u1) { User.create({email: 'user1@example.com', password: 'u1pass'}, function(err, u1) {
@ -3024,9 +3024,9 @@ describe('User', function() {
function assertPreservedTokens(done) { function assertPreservedTokens(done) {
AccessToken.find({where: {userId: user.pk}}, function(err, tokens) { AccessToken.find({where: {userId: user.pk}}, function(err, tokens) {
if (err) return done(err); if (err) return done(err);
var actualIds = tokens.map(function(t) { return t.id; }); const actualIds = tokens.map(function(t) { return t.id; });
actualIds.sort(); actualIds.sort();
var expectedIds = [originalUserToken1.id, originalUserToken2.id]; const expectedIds = [originalUserToken1.id, originalUserToken2.id];
expectedIds.sort(); expectedIds.sort();
expect(actualIds).to.eql(expectedIds); expect(actualIds).to.eql(expectedIds);
done(); done();
@ -3043,8 +3043,8 @@ describe('User', function() {
}); });
describe('Verification after updating email', function() { describe('Verification after updating email', function() {
var NEW_EMAIL = 'updated@example.com'; const NEW_EMAIL = 'updated@example.com';
var userInstance; let userInstance;
beforeEach(createOriginalUser); beforeEach(createOriginalUser);
@ -3115,7 +3115,7 @@ describe('User', function() {
}); });
function createOriginalUser(done) { function createOriginalUser(done) {
var userData = { const userData = {
email: 'original@example.com', email: 'original@example.com',
password: 'bar', password: 'bar',
emailVerified: true, emailVerified: true,
@ -3132,7 +3132,7 @@ describe('User', function() {
it('allows resetPassword by email if email verification is required and done', it('allows resetPassword by email if email verification is required and done',
function(done) { function(done) {
User.settings.emailVerificationRequired = true; User.settings.emailVerificationRequired = true;
var email = validCredentialsEmailVerified.email; const email = validCredentialsEmailVerified.email;
User.resetPassword({email: email}, function(err, info) { User.resetPassword({email: email}, function(err, info) {
if (err) return done(err); if (err) return done(err);
@ -3143,7 +3143,7 @@ describe('User', function() {
it('disallows resetPassword by email if email verification is required and not done', it('disallows resetPassword by email if email verification is required and not done',
function(done) { function(done) {
User.settings.emailVerificationRequired = true; User.settings.emailVerificationRequired = true;
var email = validCredentialsEmail; const email = validCredentialsEmail;
User.resetPassword({email: email}, function(err) { User.resetPassword({email: email}, function(err) {
assert(err); assert(err);
@ -3156,7 +3156,7 @@ describe('User', function() {
it('allows resetPassword by email if email verification is not required', it('allows resetPassword by email if email verification is not required',
function(done) { function(done) {
User.settings.emailVerificationRequired = false; User.settings.emailVerificationRequired = false;
var email = validCredentialsEmail; const email = validCredentialsEmail;
User.resetPassword({email: email}, function(err) { User.resetPassword({email: email}, function(err) {
if (err) return done(err); if (err) return done(err);
@ -3178,7 +3178,7 @@ describe('User', function() {
}); });
describe('ttl', function() { describe('ttl', function() {
var User2; let User2;
beforeEach(function() { beforeEach(function() {
User2 = loopback.User.extend('User2', {}, {ttl: 10}); User2 = loopback.User.extend('User2', {}, {ttl: 10});
}); });

View File

@ -4,7 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../'); const loopback = require('../../');
module.exports = describe; module.exports = describe;

View File

@ -4,7 +4,7 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var loopback = require('../../'); const loopback = require('../../');
module.exports = it; module.exports = it;

View File

@ -4,35 +4,35 @@
// License text available at https://opensource.org/licenses/MIT // License text available at https://opensource.org/licenses/MIT
'use strict'; 'use strict';
var assert = require('assert'); const assert = require('assert');
var async = require('async'); const async = require('async');
var describe = require('./describe'); const describe = require('./describe');
var loopback = require('../../'); const loopback = require('../../');
var ACL = loopback.ACL; const ACL = loopback.ACL;
var Change = loopback.Change; const Change = loopback.Change;
var PersistedModel = loopback.PersistedModel; const PersistedModel = loopback.PersistedModel;
var RemoteObjects = require('strong-remoting'); const RemoteObjects = require('strong-remoting');
var TaskEmitter = require('strong-task-emitter'); const TaskEmitter = require('strong-task-emitter');
module.exports = function defineModelTestsWithDataSource(options) { module.exports = function defineModelTestsWithDataSource(options) {
describe('Model Tests', function() { describe('Model Tests', function() {
var User, dataSource; let User, dataSource;
if (options.beforeEach) { if (options.beforeEach) {
beforeEach(options.beforeEach); beforeEach(options.beforeEach);
} }
beforeEach(function() { beforeEach(function() {
var test = this; const test = this;
// setup a model / datasource // setup a model / datasource
dataSource = this.dataSource || loopback.createDataSource(options.dataSource); dataSource = this.dataSource || loopback.createDataSource(options.dataSource);
var extend = PersistedModel.extend; const extend = PersistedModel.extend;
// create model hook // create model hook
PersistedModel.extend = function() { PersistedModel.extend = function() {
var extendedModel = extend.apply(PersistedModel, arguments); const extendedModel = extend.apply(PersistedModel, arguments);
if (options.onDefine) { if (options.onDefine) {
options.onDefine.call(test, extendedModel); options.onDefine.call(test, extendedModel);
@ -65,7 +65,7 @@ module.exports = function defineModelTestsWithDataSource(options) {
describe('Model.validatesPresenceOf(properties...)', function() { describe('Model.validatesPresenceOf(properties...)', function() {
it('Require a model to include a property to be considered valid', function() { it('Require a model to include a property to be considered valid', function() {
User.validatesPresenceOf('first', 'last', 'age'); User.validatesPresenceOf('first', 'last', 'age');
var joe = new User({first: 'joe'}); const joe = new User({first: 'joe'});
assert(joe.isValid() === false, 'model should not validate'); assert(joe.isValid() === false, 'model should not validate');
assert(joe.errors.last, 'should have a missing last error'); assert(joe.errors.last, 'should have a missing last error');
assert(joe.errors.age, 'should have a missing age error'); assert(joe.errors.age, 'should have a missing age error');
@ -75,7 +75,7 @@ module.exports = function defineModelTestsWithDataSource(options) {
describe('Model.validatesLengthOf(property, options)', function() { describe('Model.validatesLengthOf(property, options)', function() {
it('Require a property length to be within a specified range', function() { it('Require a property length to be within a specified range', function() {
User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}}); User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}});
var joe = new User({password: '1234'}); const joe = new User({password: '1234'});
assert(joe.isValid() === false, 'model should not be valid'); assert(joe.isValid() === false, 'model should not be valid');
assert(joe.errors.password, 'should have password error'); assert(joe.errors.password, 'should have password error');
}); });
@ -84,7 +84,7 @@ module.exports = function defineModelTestsWithDataSource(options) {
describe('Model.validatesInclusionOf(property, options)', function() { describe('Model.validatesInclusionOf(property, options)', function() {
it('Require a value for `property` to be in the specified array', function() { it('Require a value for `property` to be in the specified array', function() {
User.validatesInclusionOf('gender', {in: ['male', 'female']}); User.validatesInclusionOf('gender', {in: ['male', 'female']});
var foo = new User({gender: 'bar'}); const foo = new User({gender: 'bar'});
assert(foo.isValid() === false, 'model should not be valid'); assert(foo.isValid() === false, 'model should not be valid');
assert(foo.errors.gender, 'should have gender error'); assert(foo.errors.gender, 'should have gender error');
}); });
@ -93,9 +93,9 @@ module.exports = function defineModelTestsWithDataSource(options) {
describe('Model.validatesExclusionOf(property, options)', function() { describe('Model.validatesExclusionOf(property, options)', function() {
it('Require a value for `property` to not exist in the specified array', function() { it('Require a value for `property` to not exist in the specified array', function() {
User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']}); User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']});
var foo = new User({domain: 'www'}); const foo = new User({domain: 'www'});
var bar = new User({domain: 'billing'}); const bar = new User({domain: 'billing'});
var bat = new User({domain: 'admin'}); const bat = new User({domain: 'admin'});
assert(foo.isValid() === false); assert(foo.isValid() === false);
assert(bar.isValid() === false); assert(bar.isValid() === false);
assert(bat.isValid() === false); assert(bat.isValid() === false);
@ -108,9 +108,9 @@ module.exports = function defineModelTestsWithDataSource(options) {
describe('Model.validatesNumericalityOf(property, options)', function() { describe('Model.validatesNumericalityOf(property, options)', function() {
it('Require a value for `property` to be a specific type of `Number`', function() { it('Require a value for `property` to be a specific type of `Number`', function() {
User.validatesNumericalityOf('age', {int: true}); User.validatesNumericalityOf('age', {int: true});
var joe = new User({age: 10.2}); const joe = new User({age: 10.2});
assert(joe.isValid() === false); assert(joe.isValid() === false);
var bob = new User({age: 0}); const bob = new User({age: 0});
assert(bob.isValid() === true); assert(bob.isValid() === true);
assert(joe.errors.age, 'model should have an age error'); assert(joe.errors.age, 'model should have an age error');
}); });
@ -119,15 +119,15 @@ module.exports = function defineModelTestsWithDataSource(options) {
describe('myModel.isValid()', function() { describe('myModel.isValid()', function() {
it('Validate the model instance', function() { it('Validate the model instance', function() {
User.validatesNumericalityOf('age', {int: true}); User.validatesNumericalityOf('age', {int: true});
var user = new User({first: 'joe', age: 'flarg'}); const user = new User({first: 'joe', age: 'flarg'});
var valid = user.isValid(); const valid = user.isValid();
assert(valid === false); assert(valid === false);
assert(user.errors.age, 'model should have age error'); assert(user.errors.age, 'model should have age error');
}); });
it('Asynchronously validate the model', function(done) { it('Asynchronously validate the model', function(done) {
User.validatesNumericalityOf('age', {int: true}); User.validatesNumericalityOf('age', {int: true});
var user = new User({first: 'joe', age: 'flarg'}); const user = new User({first: 'joe', age: 'flarg'});
user.isValid(function(valid) { user.isValid(function(valid) {
assert(valid === false); assert(valid === false);
assert(user.errors.age, 'model should have age error'); assert(user.errors.age, 'model should have age error');
@ -150,7 +150,7 @@ module.exports = function defineModelTestsWithDataSource(options) {
describe('model.save([options], [callback])', function() { describe('model.save([options], [callback])', function() {
it('Save an instance of a Model to the attached data source', function(done) { it('Save an instance of a Model to the attached data source', function(done) {
var joe = new User({first: 'Joe', last: 'Bob'}); const joe = new User({first: 'Joe', last: 'Bob'});
joe.save(function(err, user) { joe.save(function(err, user) {
assert(user.id); assert(user.id);
assert(!err); assert(!err);

View File

@ -5,14 +5,14 @@
'use strict'; 'use strict';
var utils = require('../lib/utils'); const utils = require('../lib/utils');
var assert = require('assert'); const assert = require('assert');
describe('Utils', function() { describe('Utils', function() {
describe('uploadInChunks', function() { describe('uploadInChunks', function() {
it('calls process function for each chunk', function(done) { it('calls process function for each chunk', function(done) {
var largeArray = ['item1', 'item2', 'item3']; const largeArray = ['item1', 'item2', 'item3'];
var calls = []; const calls = [];
utils.uploadInChunks(largeArray, 1, function processFunction(array, cb) { utils.uploadInChunks(largeArray, 1, function processFunction(array, cb) {
calls.push(array); calls.push(array);
@ -25,8 +25,8 @@ describe('Utils', function() {
}); });
it('calls process function only once when array is smaller than chunk size', function(done) { it('calls process function only once when array is smaller than chunk size', function(done) {
var largeArray = ['item1', 'item2']; const largeArray = ['item1', 'item2'];
var calls = []; const calls = [];
utils.uploadInChunks(largeArray, 3, function processFunction(array, cb) { utils.uploadInChunks(largeArray, 3, function processFunction(array, cb) {
calls.push(array); calls.push(array);
@ -39,7 +39,7 @@ describe('Utils', function() {
}); });
it('concats results from each call to the process function', function(done) { it('concats results from each call to the process function', function(done) {
var largeArray = ['item1', 'item2', 'item3', 'item4']; const largeArray = ['item1', 'item2', 'item3', 'item4'];
utils.uploadInChunks(largeArray, 2, function processFunction(array, cb) { utils.uploadInChunks(largeArray, 2, function processFunction(array, cb) {
cb(null, array); cb(null, array);
@ -52,7 +52,7 @@ describe('Utils', function() {
}); });
describe('downloadInChunks', function() { describe('downloadInChunks', function() {
var largeArray, calls, chunkSize, skip; let largeArray, calls, chunkSize, skip;
beforeEach(function() { beforeEach(function() {
largeArray = ['item1', 'item2', 'item3']; largeArray = ['item1', 'item2', 'item3'];
@ -63,9 +63,9 @@ describe('Utils', function() {
function processFunction(filter, cb) { function processFunction(filter, cb) {
calls.push(Object.assign({}, filter)); calls.push(Object.assign({}, filter));
var results = []; const results = [];
for (var i = 0; i < chunkSize; i++) { for (let i = 0; i < chunkSize; i++) {
if (largeArray[skip + i]) { if (largeArray[skip + i]) {
results.push(largeArray[skip + i]); results.push(largeArray[skip + i]);
} }
@ -76,7 +76,7 @@ describe('Utils', function() {
} }
it('calls process function with the correct filter', function(done) { it('calls process function with the correct filter', function(done) {
var expectedFilters = [{skip: 0, limit: chunkSize}, {skip: chunkSize, limit: chunkSize}]; const expectedFilters = [{skip: 0, limit: chunkSize}, {skip: chunkSize, limit: chunkSize}];
utils.downloadInChunks({}, chunkSize, processFunction, function finished(err) { utils.downloadInChunks({}, chunkSize, processFunction, function finished(err) {
if (err) return done(err); if (err) return done(err);
assert.deepEqual(calls, expectedFilters); assert.deepEqual(calls, expectedFilters);
@ -95,22 +95,22 @@ describe('Utils', function() {
describe('concatResults', function() { describe('concatResults', function() {
it('concats regular arrays', function() { it('concats regular arrays', function() {
var array1 = ['item1', 'item2']; const array1 = ['item1', 'item2'];
var array2 = ['item3', 'item4']; const array2 = ['item3', 'item4'];
var concatResults = utils.concatResults(array1, array2); const concatResults = utils.concatResults(array1, array2);
assert.deepEqual(concatResults, ['item1', 'item2', 'item3', 'item4']); assert.deepEqual(concatResults, ['item1', 'item2', 'item3', 'item4']);
}); });
it('concats objects containing arrays', function() { it('concats objects containing arrays', function() {
var object1 = {deltas: [{change: 'change 1'}], conflict: []}; const object1 = {deltas: [{change: 'change 1'}], conflict: []};
var object2 = {deltas: [{change: 'change 2'}], conflict: [{conflict: 'conflict 1'}]}; const object2 = {deltas: [{change: 'change 2'}], conflict: [{conflict: 'conflict 1'}]};
var expectedResults = { const expectedResults = {
deltas: [{change: 'change 1'}, {change: 'change 2'}], deltas: [{change: 'change 1'}, {change: 'change 2'}],
conflict: [{conflict: 'conflict 1'}], conflict: [{conflict: 'conflict 1'}],
}; };
var concatResults = utils.concatResults(object1, object2); const concatResults = utils.concatResults(object1, object2);
assert.deepEqual(concatResults, expectedResults); assert.deepEqual(concatResults, expectedResults);
}); });
}); });