Update eslint to loopback config v5
Notable side-effects: - loopback no longer exports "caller" and "arguments" properties - kv-memory connector is now properly added to the connector registry - the file "test/support.js" was finally removed
This commit is contained in:
parent
ef0478cc97
commit
06cb481c3f
|
@ -5,6 +5,7 @@
|
||||||
"ignoreComments": true,
|
"ignoreComments": true,
|
||||||
"ignoreUrls": true,
|
"ignoreUrls": true,
|
||||||
"ignorePattern": "^\\s*var\\s.+=\\s*(require\\s*\\()|(/)"
|
"ignorePattern": "^\\s*var\\s.+=\\s*(require\\s*\\()|(/)"
|
||||||
}]
|
}],
|
||||||
|
"no-unused-expressions": "off",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
// License text available at https://opensource.org/licenses/MIT
|
// License text available at https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
/*global module:false*/
|
/*global module:false*/
|
||||||
|
'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';
|
||||||
|
@ -201,7 +202,7 @@ module.exports = function(grunt) {
|
||||||
},
|
},
|
||||||
|
|
||||||
// Add browserify to preprocessors
|
// Add browserify to preprocessors
|
||||||
preprocessors: { 'test/e2e/*': ['browserify'] },
|
preprocessors: {'test/e2e/*': ['browserify']},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Module Dependencies.
|
* Module Dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
var loopback = require('../../lib/loopback');
|
var loopback = require('../../lib/loopback');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
@ -47,7 +48,7 @@ module.exports = function(AccessToken) {
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AccessToken.ANONYMOUS = new AccessToken({ id: '$anonymous' });
|
AccessToken.ANONYMOUS = new AccessToken({id: '$anonymous'});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a cryptographically random access token id.
|
* Create a cryptographically random access token id.
|
||||||
|
|
|
@ -3,13 +3,11 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
/*!
|
/*!
|
||||||
Schema ACL options
|
Schema ACL options
|
||||||
|
|
||||||
Object level permissions, for example, an album owned by a user
|
Object level permissions, for example, an album owned by a user
|
||||||
|
|
||||||
Factors to be authorized against:
|
Factors to be authorized against:
|
||||||
|
|
||||||
* model name: Album
|
* model name: Album
|
||||||
* model instance properties: userId of the album, friends, shared
|
* model instance properties: userId of the album, friends, shared
|
||||||
* methods
|
* methods
|
||||||
|
@ -21,19 +19,15 @@
|
||||||
** none
|
** none
|
||||||
** everyone
|
** everyone
|
||||||
** relations: owner/friend/granted
|
** relations: owner/friend/granted
|
||||||
|
|
||||||
Class level permissions, for example, Album
|
Class level permissions, for example, Album
|
||||||
* model name: Album
|
* model name: Album
|
||||||
* methods
|
* methods
|
||||||
|
|
||||||
URL/Route level permissions
|
URL/Route level permissions
|
||||||
* url pattern
|
* url pattern
|
||||||
* application id
|
* application id
|
||||||
* ip addresses
|
* ip addresses
|
||||||
* http headers
|
* http headers
|
||||||
|
|
||||||
Map to oAuth 2.0 scopes
|
Map to oAuth 2.0 scopes
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
|
@ -331,10 +325,10 @@ 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] };
|
var propertyQuery = (property === ACL.ALL) ? undefined : {inq: [property, ACL.ALL]};
|
||||||
accessType = accessType || ACL.ALL;
|
accessType = accessType || ACL.ALL;
|
||||||
var accessTypeQuery = (accessType === ACL.ALL) ? undefined :
|
var accessTypeQuery = (accessType === ACL.ALL) ? undefined :
|
||||||
{ inq: [accessType, ACL.ALL, ACL.EXECUTE] };
|
{inq: [accessType, ACL.ALL, ACL.EXECUTE]};
|
||||||
|
|
||||||
var req = new AccessRequest(model, property, accessType);
|
var req = new AccessRequest(model, property, accessType);
|
||||||
|
|
||||||
|
@ -352,8 +346,8 @@ module.exports = function(ACL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var self = this;
|
var 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) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (callback) callback(err);
|
if (callback) callback(err);
|
||||||
|
@ -408,21 +402,21 @@ module.exports = function(ACL) {
|
||||||
var modelName = context.modelName;
|
var modelName = context.modelName;
|
||||||
|
|
||||||
var methodNames = context.methodNames;
|
var methodNames = context.methodNames;
|
||||||
var propertyQuery = (property === ACL.ALL) ? undefined : { inq: methodNames.concat([ACL.ALL]) };
|
var propertyQuery = (property === ACL.ALL) ? undefined : {inq: methodNames.concat([ACL.ALL])};
|
||||||
|
|
||||||
var accessTypeQuery = (accessType === ACL.ALL) ?
|
var 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(modelName, property, accessType, ACL.DEFAULT, methodNames);
|
var req = new AccessRequest(modelName, property, accessType, ACL.DEFAULT, methodNames);
|
||||||
|
|
||||||
var effectiveACLs = [];
|
var effectiveACLs = [];
|
||||||
var staticACLs = self.getStaticACLs(model.modelName, property);
|
var staticACLs = self.getStaticACLs(model.modelName, property);
|
||||||
|
|
||||||
this.find({ where: { model: model.modelName, property: propertyQuery,
|
this.find({where: {model: model.modelName, property: propertyQuery,
|
||||||
accessType: accessTypeQuery }}, function(err, acls) {
|
accessType: accessTypeQuery}}, function(err, acls) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (callback) callback(err);
|
if (callback) callback(err);
|
||||||
return;
|
return;
|
||||||
|
@ -525,15 +519,15 @@ module.exports = function(ACL) {
|
||||||
this.resolveRelatedModels();
|
this.resolveRelatedModels();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ACL.ROLE:
|
case ACL.ROLE:
|
||||||
this.roleModel.findOne({ where: { or: [{ name: id }, { id: id }] }}, cb);
|
this.roleModel.findOne({where: {or: [{name: id}, {id: id}]}}, cb);
|
||||||
break;
|
break;
|
||||||
case ACL.USER:
|
case ACL.USER:
|
||||||
this.userModel.findOne(
|
this.userModel.findOne(
|
||||||
{ where: { or: [{ username: id }, { email: id }, { id: id }] }}, cb);
|
{where: {or: [{username: id}, {email: id}, {id: id}]}}, cb);
|
||||||
break;
|
break;
|
||||||
case ACL.APP:
|
case ACL.APP:
|
||||||
this.applicationModel.findOne(
|
this.applicationModel.findOne(
|
||||||
{ where: { or: [{ name: id }, { email: id }, { id: id }] }}, cb);
|
{where: {or: [{name: id}, {email: id}, {id: id}]}}, cb);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
process.nextTick(function() {
|
process.nextTick(function() {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var utils = require('../../lib/utils');
|
var utils = require('../../lib/utils');
|
||||||
|
|
||||||
|
@ -70,18 +71,6 @@ function generateKey(hmacKey, algorithm, encoding) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = function(Application) {
|
module.exports = function(Application) {
|
||||||
// Workaround for https://github.com/strongloop/loopback/issues/292
|
|
||||||
Application.definition.rawProperties.created.default =
|
|
||||||
Application.definition.properties.created.default = function() {
|
|
||||||
return new Date();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Workaround for https://github.com/strongloop/loopback/issues/292
|
|
||||||
Application.definition.rawProperties.modified.default =
|
|
||||||
Application.definition.properties.modified.default = function() {
|
|
||||||
return new Date();
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* A hook to generate keys before creation
|
* A hook to generate keys before creation
|
||||||
* @param next
|
* @param next
|
||||||
|
@ -126,7 +115,7 @@ module.exports = function(Application) {
|
||||||
}
|
}
|
||||||
cb = cb || utils.createPromiseCallback();
|
cb = cb || utils.createPromiseCallback();
|
||||||
|
|
||||||
var props = { owner: owner, name: name };
|
var props = {owner: owner, name: name};
|
||||||
for (var p in options) {
|
for (var p in options) {
|
||||||
if (!(p in props)) {
|
if (!(p in props)) {
|
||||||
props[p] = options[p];
|
props[p] = options[p];
|
||||||
|
|
|
@ -118,7 +118,13 @@
|
||||||
"description": "Status of the application, production/sandbox/disabled"
|
"description": "Status of the application, production/sandbox/disabled"
|
||||||
},
|
},
|
||||||
|
|
||||||
"created": "date",
|
"created": {
|
||||||
"modified": "date"
|
"type": "date",
|
||||||
|
"defaultFn": "now"
|
||||||
|
},
|
||||||
|
"modified": {
|
||||||
|
"type": "date",
|
||||||
|
"defaultFn": "now"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,13 @@
|
||||||
* Module Dependencies.
|
* Module Dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
var PersistedModel = require('../../lib/loopback').PersistedModel;
|
var PersistedModel = require('../../lib/loopback').PersistedModel;
|
||||||
var loopback = require('../../lib/loopback');
|
var loopback = require('../../lib/loopback');
|
||||||
var utils = require('../../lib/utils');
|
var utils = require('../../lib/utils');
|
||||||
var crypto = require('crypto');
|
var crypto = require('crypto');
|
||||||
var CJSON = { stringify: require('canonical-json') };
|
var CJSON = {stringify: require('canonical-json')};
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var debug = require('debug')('loopback:change');
|
var debug = require('debug')('loopback:change');
|
||||||
|
@ -113,7 +114,7 @@ module.exports = function(Change) {
|
||||||
|
|
||||||
var msg = g.f('Cannot rectify %s changes:\n%s', modelName, desc);
|
var 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);
|
||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
|
@ -404,7 +405,7 @@ module.exports = function(Change) {
|
||||||
callback = callback || utils.createPromiseCallback();
|
callback = callback || utils.createPromiseCallback();
|
||||||
|
|
||||||
if (!Array.isArray(remoteChanges) || remoteChanges.length === 0) {
|
if (!Array.isArray(remoteChanges) || remoteChanges.length === 0) {
|
||||||
callback(null, { deltas: [], conflicts: [] });
|
callback(null, {deltas: [], conflicts: []});
|
||||||
return callback.promise;
|
return callback.promise;
|
||||||
}
|
}
|
||||||
var remoteChangeIndex = {};
|
var remoteChangeIndex = {};
|
||||||
|
@ -419,7 +420,7 @@ module.exports = function(Change) {
|
||||||
this.find({
|
this.find({
|
||||||
where: {
|
where: {
|
||||||
modelName: modelName,
|
modelName: modelName,
|
||||||
modelId: { inq: modelIds },
|
modelId: {inq: modelIds},
|
||||||
},
|
},
|
||||||
}, function(err, allLocalChanges) {
|
}, function(err, allLocalChanges) {
|
||||||
if (err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
@ -674,7 +675,7 @@ module.exports = function(Change) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
conflict.SourceModel.updateLastChange(
|
conflict.SourceModel.updateLastChange(
|
||||||
conflict.modelId,
|
conflict.modelId,
|
||||||
{ prev: targetChange.rev },
|
{prev: targetChange.rev},
|
||||||
cb);
|
cb);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -708,7 +709,7 @@ module.exports = function(Change) {
|
||||||
}
|
}
|
||||||
var inst = new conflict.SourceModel(
|
var inst = new conflict.SourceModel(
|
||||||
target.toObject(),
|
target.toObject(),
|
||||||
{ persisted: true });
|
{persisted: true});
|
||||||
inst.save(done);
|
inst.save(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Module Dependencies.
|
* Module Dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,8 +42,8 @@ module.exports = function(Checkpoint) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Checkpoint._getSingleton = function(cb) {
|
Checkpoint._getSingleton = function(cb) {
|
||||||
var query = { limit: 1 }; // match all instances, return only one
|
var query = {limit: 1}; // match all instances, return only one
|
||||||
var initialData = { seq: 1 };
|
var initialData = {seq: 1};
|
||||||
this.findOrCreate(query, initialData, cb);
|
this.findOrCreate(query, initialData, cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ module.exports = function(Checkpoint) {
|
||||||
var originalSeq = cp.seq;
|
var 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) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
// possible outcomes
|
// possible outcomes
|
||||||
// 1) seq was updated to seq+1 - exactly what we wanted!
|
// 1) seq was updated to seq+1 - exactly what we wanted!
|
||||||
|
|
|
@ -3,20 +3,21 @@
|
||||||
// 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
|
||||||
|
|
||||||
/**
|
'use strict';
|
||||||
* Email model. Extends LoopBack base [Model](#model-new-model).
|
|
||||||
* @property {String} to Email addressee. Required.
|
|
||||||
* @property {String} from Email sender address. Required.
|
|
||||||
* @property {String} subject Email subject string. Required.
|
|
||||||
* @property {String} text Text body of email.
|
|
||||||
* @property {String} html HTML body of email.
|
|
||||||
*
|
|
||||||
* @class Email
|
|
||||||
* @inherits {Model}
|
|
||||||
*/
|
|
||||||
|
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Email model. Extends LoopBack base [Model](#model-new-model).
|
||||||
|
* @property {String} to Email addressee. Required.
|
||||||
|
* @property {String} from Email sender address. Required.
|
||||||
|
* @property {String} subject Email subject string. Required.
|
||||||
|
* @property {String} text Text body of email.
|
||||||
|
* @property {String} html HTML body of email.
|
||||||
|
*
|
||||||
|
* @class Email
|
||||||
|
* @inherits {Model}
|
||||||
|
*/
|
||||||
|
|
||||||
module.exports = function(Email) {
|
module.exports = function(Email) {
|
||||||
/**
|
/**
|
||||||
* Send an email with the given `options`.
|
* Send an email with the given `options`.
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
// Copyright IBM Corp. 2014,2016. All Rights Reserved.
|
||||||
|
// Node module: loopback
|
||||||
|
// This file is licensed under the MIT License.
|
||||||
|
// License text available at https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,52 +170,52 @@ module.exports = function(KeyValueModel) {
|
||||||
this.remoteMethod('get', {
|
this.remoteMethod('get', {
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'key', type: 'string', required: true,
|
arg: 'key', type: 'string', required: true,
|
||||||
http: { source: 'path' },
|
http: {source: 'path'},
|
||||||
},
|
},
|
||||||
returns: { arg: 'value', type: 'any', root: true },
|
returns: {arg: 'value', type: 'any', root: true},
|
||||||
http: { path: '/:key', verb: 'get' },
|
http: {path: '/:key', verb: 'get'},
|
||||||
rest: { after: convertNullToNotFoundError },
|
rest: {after: convertNullToNotFoundError},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.remoteMethod('set', {
|
this.remoteMethod('set', {
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'key', type: 'string', required: true,
|
{arg: 'key', type: 'string', required: true,
|
||||||
http: { source: 'path' }},
|
http: {source: 'path'}},
|
||||||
{ arg: 'value', type: 'any', required: true,
|
{arg: 'value', type: 'any', required: true,
|
||||||
http: { source: 'body' }},
|
http: {source: 'body'}},
|
||||||
{ arg: 'ttl', type: 'number',
|
{arg: 'ttl', type: 'number',
|
||||||
http: { source: 'query' },
|
http: {source: 'query'},
|
||||||
description: 'time to live in milliseconds' },
|
description: 'time to live in milliseconds'},
|
||||||
],
|
],
|
||||||
http: { path: '/:key', verb: 'put' },
|
http: {path: '/:key', verb: 'put'},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.remoteMethod('expire', {
|
this.remoteMethod('expire', {
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'key', type: 'string', required: true,
|
{arg: 'key', type: 'string', required: true,
|
||||||
http: { source: 'path' }},
|
http: {source: 'path'}},
|
||||||
{ arg: 'ttl', type: 'number', required: true,
|
{arg: 'ttl', type: 'number', required: true,
|
||||||
http: { source: 'form' }},
|
http: {source: 'form'}},
|
||||||
],
|
],
|
||||||
http: { path: '/:key/expire', verb: 'put' },
|
http: {path: '/:key/expire', verb: 'put'},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.remoteMethod('ttl', {
|
this.remoteMethod('ttl', {
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'key', type: 'string', required: true,
|
arg: 'key', type: 'string', required: true,
|
||||||
http: { source: 'path' },
|
http: {source: 'path'},
|
||||||
},
|
},
|
||||||
returns: { arg: 'value', type: 'any', root: true },
|
returns: {arg: 'value', type: 'any', root: true},
|
||||||
http: { path: '/:key/ttl', verb: 'get' },
|
http: {path: '/:key/ttl', verb: 'get'},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.remoteMethod('keys', {
|
this.remoteMethod('keys', {
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'filter', type: 'object', required: false,
|
arg: 'filter', type: 'object', required: false,
|
||||||
http: { source: 'query' },
|
http: {source: 'query'},
|
||||||
},
|
},
|
||||||
returns: { arg: 'keys', type: ['string'], root: true },
|
returns: {arg: 'keys', type: ['string'], root: true},
|
||||||
http: { path: '/keys', verb: 'get' },
|
http: {path: '/keys', verb: 'get'},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../../lib/loopback');
|
var loopback = require('../../lib/loopback');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../../lib/loopback');
|
var loopback = require('../../lib/loopback');
|
||||||
var debug = require('debug')('loopback:security:role');
|
var debug = require('debug')('loopback:security:role');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
@ -20,18 +21,6 @@ assert(RoleMapping, 'RoleMapping model must be defined before Role model');
|
||||||
* @header Role object
|
* @header Role object
|
||||||
*/
|
*/
|
||||||
module.exports = function(Role) {
|
module.exports = function(Role) {
|
||||||
// Workaround for https://github.com/strongloop/loopback/issues/292
|
|
||||||
Role.definition.rawProperties.created.default =
|
|
||||||
Role.definition.properties.created.default = function() {
|
|
||||||
return new Date();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Workaround for https://github.com/strongloop/loopback/issues/292
|
|
||||||
Role.definition.rawProperties.modified.default =
|
|
||||||
Role.definition.properties.modified.default = function() {
|
|
||||||
return new Date();
|
|
||||||
};
|
|
||||||
|
|
||||||
Role.resolveRelatedModels = function() {
|
Role.resolveRelatedModels = function() {
|
||||||
if (!this.userModel) {
|
if (!this.userModel) {
|
||||||
var reg = this.registry;
|
var reg = this.registry;
|
||||||
|
@ -98,7 +87,7 @@ 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;
|
var ids;
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -108,7 +97,7 @@ module.exports = function(Role) {
|
||||||
return m.principalId;
|
return m.principalId;
|
||||||
});
|
});
|
||||||
query.where = query.where || {};
|
query.where = query.where || {};
|
||||||
query.where.id = { inq: ids };
|
query.where.id = {inq: ids};
|
||||||
model.find(query, function(err, models) {
|
model.find(query, function(err, models) {
|
||||||
callback(err, models);
|
callback(err, models);
|
||||||
});
|
});
|
||||||
|
@ -330,7 +319,7 @@ module.exports = function(Role) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var roleMappingModel = this.roleMappingModel;
|
var 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);
|
||||||
return;
|
return;
|
||||||
|
@ -353,8 +342,8 @@ module.exports = function(Role) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (principalType && principalId) {
|
if (principalType && principalId) {
|
||||||
roleMappingModel.findOne({ where: { roleId: roleId,
|
roleMappingModel.findOne({where: {roleId: roleId,
|
||||||
principalType: principalType, principalId: principalId }},
|
principalType: principalType, principalId: principalId}},
|
||||||
function(err, result) {
|
function(err, result) {
|
||||||
debug('Role mapping found: %j', result);
|
debug('Role mapping found: %j', result);
|
||||||
done(!err && result); // The only arg is the result
|
done(!err && result); // The only arg is the result
|
||||||
|
@ -429,8 +418,8 @@ 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) {
|
||||||
roleMappingModel.find({ where: { principalType: principalType,
|
roleMappingModel.find({where: {principalType: principalType,
|
||||||
principalId: principalId }}, function(err, mappings) {
|
principalId: principalId}}, function(err, mappings) {
|
||||||
debug('Role mappings found: %s %j', err, mappings);
|
debug('Role mappings found: %s %j', err, mappings);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (done) done(err);
|
if (done) done(err);
|
||||||
|
@ -451,5 +440,5 @@ module.exports = function(Role) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Role.validatesUniquenessOf('name', { message: 'already exists' });
|
Role.validatesUniquenessOf('name', {message: 'already exists'});
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,8 +13,12 @@
|
||||||
},
|
},
|
||||||
"description": "string",
|
"description": "string",
|
||||||
|
|
||||||
"created": "date",
|
"created": {
|
||||||
"modified": "date"
|
"defaultFn": "now"
|
||||||
|
},
|
||||||
|
"modified": {
|
||||||
|
"defaultFn": "now"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
"principals": {
|
"principals": {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var loopback = require('../../lib/loopback');
|
var loopback = require('../../lib/loopback');
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ module.exports = function(Scope) {
|
||||||
assert(aclModel,
|
assert(aclModel,
|
||||||
'ACL model must be defined before Scope.checkPermission is called');
|
'ACL model must be defined before Scope.checkPermission is called');
|
||||||
|
|
||||||
this.findOne({ where: { name: scope }}, function(err, scope) {
|
this.findOne({where: {name: scope}}, function(err, scope) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (callback) callback(err);
|
if (callback) callback(err);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Module Dependencies.
|
* Module Dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
var isEmail = require('isemail');
|
var isEmail = require('isemail');
|
||||||
var loopback = require('../../lib/loopback');
|
var loopback = require('../../lib/loopback');
|
||||||
|
@ -219,7 +220,7 @@ module.exports = function(User) {
|
||||||
return fn.promise;
|
return fn.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.findOne({ where: query }, function(err, user) {
|
self.findOne({where: query}, function(err, user) {
|
||||||
var defaultError = new Error(g.f('login failed'));
|
var defaultError = new Error(g.f('login failed'));
|
||||||
defaultError.statusCode = 401;
|
defaultError.statusCode = 401;
|
||||||
defaultError.code = 'LOGIN_FAILED';
|
defaultError.code = 'LOGIN_FAILED';
|
||||||
|
@ -306,14 +307,14 @@ module.exports = function(User) {
|
||||||
User.observe('before delete', function(ctx, next) {
|
User.observe('before delete', function(ctx, next) {
|
||||||
var AccessToken = ctx.Model.relations.accessTokens.modelTo;
|
var AccessToken = ctx.Model.relations.accessTokens.modelTo;
|
||||||
var pkName = ctx.Model.definition.idName() || 'id';
|
var 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]; });
|
var ids = list.map(function(u) { return u[pkName]; });
|
||||||
ctx.where = {};
|
ctx.where = {};
|
||||||
ctx.where[pkName] = { inq: ids };
|
ctx.where[pkName] = {inq: ids};
|
||||||
|
|
||||||
AccessToken.destroyAll({ userId: { inq: ids }}, next);
|
AccessToken.destroyAll({userId: {inq: ids}}, next);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -431,7 +432,8 @@ module.exports = function(User) {
|
||||||
options.templateFn = options.templateFn || createVerificationEmailBody;
|
options.templateFn = options.templateFn || createVerificationEmailBody;
|
||||||
|
|
||||||
// Email model
|
// Email model
|
||||||
var Email = options.mailer || this.constructor.email || registry.getModelByType(loopback.Email);
|
var Email =
|
||||||
|
options.mailer || this.constructor.email || registry.getModelByType(loopback.Email);
|
||||||
|
|
||||||
// Set a default token generation function if one is not provided
|
// Set a default token generation function if one is not provided
|
||||||
var tokenGenerator = options.generateVerificationToken || User.generateVerificationToken;
|
var tokenGenerator = options.generateVerificationToken || User.generateVerificationToken;
|
||||||
|
@ -479,7 +481,7 @@ module.exports = function(User) {
|
||||||
if (err) {
|
if (err) {
|
||||||
fn(err);
|
fn(err);
|
||||||
} else {
|
} else {
|
||||||
fn(null, { email: email, token: user.verificationToken, uid: user.id });
|
fn(null, {email: email, token: user.verificationToken, uid: user.id});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -493,7 +495,6 @@ module.exports = function(User) {
|
||||||
cb(null, body);
|
cb(null, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A default verification token generator which accepts the user the token is
|
* A default verification token generator which accepts the user the token is
|
||||||
* being generated for and a callback function to indicate completion.
|
* being generated for and a callback function to indicate completion.
|
||||||
|
@ -584,7 +585,7 @@ module.exports = function(User) {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
UserModel.findOne({ where: { email: options.email }}, function(err, user) {
|
UserModel.findOne({where: {email: options.email}}, function(err, user) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
|
@ -603,7 +604,7 @@ module.exports = function(User) {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
user.accessTokens.create({ ttl: ttl }, function(err, accessToken) {
|
user.accessTokens.create({ttl: ttl}, function(err, accessToken) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
|
@ -699,11 +700,11 @@ module.exports = function(User) {
|
||||||
UserModel.observe('before save', function beforeEmailUpdate(ctx, next) {
|
UserModel.observe('before save', function beforeEmailUpdate(ctx, next) {
|
||||||
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 where = ctx.where || { id: ctx.instance.id };
|
var where = ctx.where || {id: ctx.instance.id};
|
||||||
ctx.Model.find({ where: where }, function(err, userInstances) {
|
ctx.Model.find({where: where}, 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) {
|
||||||
return { id: u.id, email: u.email };
|
return {id: u.id, email: u.email};
|
||||||
});
|
});
|
||||||
if (ctx.instance) {
|
if (ctx.instance) {
|
||||||
var emailChanged = ctx.instance.email !== ctx.hookState.originalUserData[0].email;
|
var emailChanged = ctx.instance.email !== ctx.hookState.originalUserData[0].email;
|
||||||
|
@ -735,7 +736,7 @@ module.exports = function(User) {
|
||||||
return u.id;
|
return u.id;
|
||||||
});
|
});
|
||||||
if (!idsToExpire.length) return next();
|
if (!idsToExpire.length) return next();
|
||||||
AccessToken.deleteAll({ userId: { inq: idsToExpire }}, next);
|
AccessToken.deleteAll({userId: {inq: idsToExpire}}, next);
|
||||||
});
|
});
|
||||||
|
|
||||||
UserModel.remoteMethod(
|
UserModel.remoteMethod(
|
||||||
|
@ -743,10 +744,10 @@ module.exports = function(User) {
|
||||||
{
|
{
|
||||||
description: 'Login a user with username/email and password.',
|
description: 'Login a user with username/email and password.',
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'credentials', type: 'object', required: true, http: { source: 'body' }},
|
{arg: 'credentials', type: 'object', required: true, http: {source: 'body'}},
|
||||||
{ arg: 'include', type: ['string'], http: { source: 'query' },
|
{arg: 'include', type: ['string'], http: {source: 'query'},
|
||||||
description: 'Related objects to include in the response. ' +
|
description: 'Related objects to include in the response. ' +
|
||||||
'See the description of return value for more details.' },
|
'See the description of return value for more details.'},
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
arg: 'accessToken', type: 'object', root: true,
|
arg: 'accessToken', type: 'object', root: true,
|
||||||
|
@ -757,7 +758,7 @@ module.exports = function(User) {
|
||||||
' - `user` - `U+007BUserU+007D` - Data of the currently logged in user. ' +
|
' - `user` - `U+007BUserU+007D` - Data of the currently logged in user. ' +
|
||||||
'{{(`include=user`)}}\n\n'),
|
'{{(`include=user`)}}\n\n'),
|
||||||
},
|
},
|
||||||
http: { verb: 'post' },
|
http: {verb: 'post'},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -766,7 +767,7 @@ 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', required: true, http: function(ctx) {
|
{arg: 'access_token', type: 'string', required: true, http: function(ctx) {
|
||||||
var req = ctx && ctx.req;
|
var req = ctx && ctx.req;
|
||||||
var accessToken = req && req.accessToken;
|
var accessToken = req && req.accessToken;
|
||||||
var tokenID = accessToken && accessToken.id;
|
var tokenID = accessToken && accessToken.id;
|
||||||
|
@ -776,7 +777,7 @@ module.exports = function(User) {
|
||||||
'from request headers.',
|
'from request headers.',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
http: { verb: 'all' },
|
http: {verb: 'all'},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -785,11 +786,11 @@ module.exports = function(User) {
|
||||||
{
|
{
|
||||||
description: 'Confirm a user registration with email verification token.',
|
description: 'Confirm a user registration with email verification token.',
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'uid', type: 'string', required: true },
|
{arg: 'uid', type: 'string', required: true},
|
||||||
{ arg: 'token', type: 'string', required: true },
|
{arg: 'token', type: 'string', required: true},
|
||||||
{ arg: 'redirect', type: 'string' },
|
{arg: 'redirect', type: 'string'},
|
||||||
],
|
],
|
||||||
http: { verb: 'get', path: '/confirm' },
|
http: {verb: 'get', path: '/confirm'},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -798,9 +799,9 @@ module.exports = function(User) {
|
||||||
{
|
{
|
||||||
description: 'Reset password for a user with email.',
|
description: 'Reset password for a user with email.',
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'options', type: 'object', required: true, http: { source: 'body' }},
|
{arg: 'options', type: 'object', required: true, http: {source: 'body'}},
|
||||||
],
|
],
|
||||||
http: { verb: 'post', path: '/reset' },
|
http: {verb: 'post', path: '/reset'},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -838,8 +839,8 @@ module.exports = function(User) {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Regular(Non-realm) users validation
|
// Regular(Non-realm) users validation
|
||||||
UserModel.validatesUniquenessOf('email', { message: 'Email already exists' });
|
UserModel.validatesUniquenessOf('email', {message: 'Email already exists'});
|
||||||
UserModel.validatesUniquenessOf('username', { message: 'User already exists' });
|
UserModel.validatesUniquenessOf('username', {message: 'User already exists'});
|
||||||
}
|
}
|
||||||
|
|
||||||
return UserModel;
|
return UserModel;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
var loopback = require('../../');
|
var loopback = require('../../');
|
||||||
var client = loopback();
|
var client = loopback();
|
||||||
|
|
|
@ -3,18 +3,19 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../../');
|
var loopback = require('../../');
|
||||||
|
|
||||||
var CartItem = exports.CartItem = loopback.PersistedModel.extend('CartItem', {
|
var 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,
|
||||||
qty: { type: Number, default: 0 },
|
qty: {type: Number, default: 0},
|
||||||
cartId: Number,
|
cartId: Number,
|
||||||
});
|
});
|
||||||
|
|
||||||
CartItem.sum = function(cartId, callback) {
|
CartItem.sum = function(cartId, callback) {
|
||||||
this.find({ where: { cartId: 1 }}, function(err, items) {
|
this.find({where: {cartId: 1}}, function(err, items) {
|
||||||
var total = items
|
var total = items
|
||||||
.map(function(item) {
|
.map(function(item) {
|
||||||
return item.total();
|
return item.total();
|
||||||
|
@ -29,8 +30,8 @@ CartItem.sum = function(cartId, callback) {
|
||||||
|
|
||||||
CartItem.remoteMethod('sum',
|
CartItem.remoteMethod('sum',
|
||||||
{
|
{
|
||||||
accepts: { arg: 'cartId', type: 'number' },
|
accepts: {arg: 'cartId', type: 'number'},
|
||||||
returns: { arg: 'total', type: 'number' },
|
returns: {arg: 'total', type: 'number'},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../../');
|
var loopback = require('../../');
|
||||||
var server = module.exports = loopback();
|
var server = module.exports = loopback();
|
||||||
var CartItem = require('./models').CartItem;
|
var CartItem = require('./models').CartItem;
|
||||||
|
@ -17,9 +18,9 @@ CartItem.attachTo(memory);
|
||||||
|
|
||||||
// test data
|
// test data
|
||||||
CartItem.create([
|
CartItem.create([
|
||||||
{ item: 'red hat', qty: 6, price: 19.99, cartId: 1 },
|
{item: 'red hat', qty: 6, price: 19.99, cartId: 1},
|
||||||
{ item: 'green shirt', qty: 1, price: 14.99, cartId: 1 },
|
{item: 'green shirt', qty: 1, price: 14.99, cartId: 1},
|
||||||
{ item: 'orange pants', qty: 58, price: 9.99, cartId: 1 },
|
{item: 'orange pants', qty: 58, price: 9.99, cartId: 1},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
CartItem.sum(1, function(err, total) {
|
CartItem.sum(1, function(err, total) {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
var loopback = require('../../');
|
var loopback = require('../../');
|
||||||
var app = loopback();
|
var app = loopback();
|
||||||
|
@ -13,13 +14,13 @@ var schema = {
|
||||||
name: String,
|
name: String,
|
||||||
};
|
};
|
||||||
|
|
||||||
app.dataSource('db', { connector: 'memory' });
|
app.dataSource('db', {connector: 'memory'});
|
||||||
var Color = app.registry.createModel('color', schema);
|
var Color = app.registry.createModel('color', schema);
|
||||||
app.model(Color, { dataSource: 'db' });
|
app.model(Color, {dataSource: 'db'});
|
||||||
|
|
||||||
Color.create({ name: 'red' });
|
Color.create({name: 'red'});
|
||||||
Color.create({ name: 'green' });
|
Color.create({name: 'green'});
|
||||||
Color.create({ name: 'blue' });
|
Color.create({name: 'blue'});
|
||||||
|
|
||||||
app.listen(3000);
|
app.listen(3000);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
var loopback = require('../../');
|
var loopback = require('../../');
|
||||||
var app = loopback();
|
var app = loopback();
|
||||||
|
@ -19,7 +20,7 @@ app.use(function saveHostToContext(req, res, next) {
|
||||||
|
|
||||||
app.use(loopback.rest());
|
app.use(loopback.rest());
|
||||||
|
|
||||||
var Color = loopback.createModel('color', { 'name': String });
|
var Color = loopback.createModel('color', {'name': String});
|
||||||
Color.beforeRemote('**', function(ctx, unused, next) {
|
Color.beforeRemote('**', function(ctx, unused, next) {
|
||||||
// Inside LoopBack code, you can read the property from the context
|
// Inside LoopBack code, you can read the property from the context
|
||||||
var ns = loopback.getCurrentContext();
|
var ns = loopback.getCurrentContext();
|
||||||
|
@ -27,8 +28,8 @@ Color.beforeRemote('**', function(ctx, unused, next) {
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.dataSource('db', { connector: 'memory' });
|
app.dataSource('db', {connector: 'memory'});
|
||||||
app.model(Color, { dataSource: 'db' });
|
app.model(Color, {dataSource: 'db'});
|
||||||
|
|
||||||
app.listen(3000, function() {
|
app.listen(3000, function() {
|
||||||
g.log('A list of colors is available at {{http://localhost:3000/colors}}');
|
g.log('A list of colors is available at {{http://localhost:3000/colors}}');
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
var models = require('../../lib/models');
|
var models = require('../../lib/models');
|
||||||
var loopback = require('../../');
|
var loopback = require('../../');
|
||||||
|
@ -10,15 +11,14 @@ var app = loopback();
|
||||||
|
|
||||||
app.use(loopback.rest());
|
app.use(loopback.rest());
|
||||||
|
|
||||||
var dataSource = loopback.createDataSource('db', { connector: loopback.Memory });
|
var dataSource = loopback.createDataSource('db', {connector: loopback.Memory});
|
||||||
|
|
||||||
var Application = models.Application(dataSource);
|
var Application = models.Application(dataSource);
|
||||||
|
|
||||||
app.model(Application);
|
app.model(Application);
|
||||||
|
|
||||||
|
var data = {pushSettings: [
|
||||||
var data = { pushSettings: [
|
{'platform': 'apns',
|
||||||
{ 'platform': 'apns',
|
|
||||||
'apns': {
|
'apns': {
|
||||||
'pushOptions': {
|
'pushOptions': {
|
||||||
'gateway': 'gateway.sandbox.push.apple.com',
|
'gateway': 'gateway.sandbox.push.apple.com',
|
||||||
|
@ -34,14 +34,13 @@ var data = { pushSettings: [
|
||||||
'interval': 300,
|
'interval': 300,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
] };
|
]};
|
||||||
|
|
||||||
Application.create(data, function(err, data) {
|
Application.create(data, function(err, data) {
|
||||||
g.log('Created: %s', data.toObject());
|
g.log('Created: %s', data.toObject());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Application.register('rfeng', 'MyApp', {description: g.f('My first mobile application')},
|
||||||
Application.register('rfeng', 'MyApp', { description: g.f('My first mobile application') },
|
|
||||||
function(err, result) {
|
function(err, result) {
|
||||||
console.log(result.toObject());
|
console.log(result.toObject());
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../../');
|
var loopback = require('../../');
|
||||||
var app = loopback();
|
var app = loopback();
|
||||||
var db = app.dataSource('db', { connector: 'memory' });
|
var db = app.dataSource('db', {connector: 'memory'});
|
||||||
var Color = app.registry.createModel('color', {}, { trackChanges: true });
|
var 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 });
|
var Color2 = app.registry.createModel('color2', {}, {trackChanges: true});
|
||||||
app.model(Color2, { dataSource: 'db' });
|
app.model(Color2, {dataSource: 'db'});
|
||||||
var target = Color2;
|
var target = Color2;
|
||||||
var source = Color;
|
var source = Color;
|
||||||
var SPEED = process.env.SPEED || 100;
|
var SPEED = process.env.SPEED || 100;
|
||||||
|
@ -70,9 +71,9 @@ run(steps);
|
||||||
|
|
||||||
function createSomeInitialSourceData() {
|
function createSomeInitialSourceData() {
|
||||||
Color.create([
|
Color.create([
|
||||||
{ name: 'red' },
|
{name: 'red'},
|
||||||
{ name: 'blue' },
|
{name: 'blue'},
|
||||||
{ name: 'green' },
|
{name: 'green'},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,11 +99,11 @@ function updateSomeTargetData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createMoreSourceData() {
|
function createMoreSourceData() {
|
||||||
Color.create({ name: 'orange' });
|
Color.create({name: 'orange'});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createEvenMoreSourceData() {
|
function createEvenMoreSourceData() {
|
||||||
Color.create({ name: 'black' });
|
Color.create({name: 'black'});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSomeSourceDataCausingAConflict() {
|
function updateSomeSourceDataCausingAConflict() {
|
||||||
|
@ -118,9 +119,9 @@ function deleteAllSourceData() {
|
||||||
|
|
||||||
function createSomeNewSourceData() {
|
function createSomeNewSourceData() {
|
||||||
Color.create([
|
Color.create([
|
||||||
{ name: 'violet' },
|
{name: 'violet'},
|
||||||
{ name: 'amber' },
|
{name: 'amber'},
|
||||||
{ name: 'olive' },
|
{name: 'olive'},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,22 +3,22 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
var loopback = require('../../');
|
var loopback = require('../../');
|
||||||
var app = loopback();
|
var app = loopback();
|
||||||
|
|
||||||
app.use(loopback.rest());
|
app.use(loopback.rest());
|
||||||
|
|
||||||
|
var dataSource = app.dataSource('db', {adapter: 'memory'});
|
||||||
var dataSource = app.dataSource('db', { adapter: 'memory' });
|
|
||||||
|
|
||||||
var Color = dataSource.define('color', {
|
var Color = dataSource.define('color', {
|
||||||
'name': String,
|
'name': String,
|
||||||
});
|
});
|
||||||
|
|
||||||
Color.create({ name: 'red' });
|
Color.create({name: 'red'});
|
||||||
Color.create({ name: 'green' });
|
Color.create({name: 'green'});
|
||||||
Color.create({ name: 'blue' });
|
Color.create({name: 'blue'});
|
||||||
|
|
||||||
Color.all(function() {
|
Color.all(function() {
|
||||||
console.log(arguments);
|
console.log(arguments);
|
||||||
|
|
1
index.js
1
index.js
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
/**
|
/**
|
||||||
* loopback ~ public api
|
* loopback ~ public api
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var loopback = require('./loopback');
|
var loopback = require('./loopback');
|
||||||
var debug = require('debug')('loopback:security:access-context');
|
var debug = require('debug')('loopback:security:access-context');
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('./globalize');
|
var g = require('./globalize');
|
||||||
var DataSource = require('loopback-datasource-juggler').DataSource;
|
var DataSource = require('loopback-datasource-juggler').DataSource;
|
||||||
var Registry = require('./registry');
|
var Registry = require('./registry');
|
||||||
|
@ -484,7 +485,7 @@ function setSharedMethodSharedProperties(model, app, modelConfigs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
// set sharedMethod.shared using the merged settings
|
// set sharedMethod.shared using the merged settings
|
||||||
var sharedMethods = model.sharedClass.methods({ includeDisabled: true });
|
var sharedMethods = model.sharedClass.methods({includeDisabled: true});
|
||||||
sharedMethods.forEach(function(sharedMethod) {
|
sharedMethods.forEach(function(sharedMethod) {
|
||||||
// use the specific setting if it exists
|
// use the specific setting if it exists
|
||||||
var hasSpecificSetting = settings.hasOwnProperty(sharedMethod.name);
|
var hasSpecificSetting = settings.hasOwnProperty(sharedMethod.name);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(registry) {
|
module.exports = function(registry) {
|
||||||
// NOTE(bajtos) we must use static require() due to browserify limitations
|
// NOTE(bajtos) we must use static require() due to browserify limitations
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Expose `Connector`.
|
* Expose `Connector`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = Connector;
|
module.exports = Connector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Dependencies.
|
* Dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../globalize');
|
var g = require('../globalize');
|
||||||
var mailer = require('nodemailer');
|
var mailer = require('nodemailer');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Expose `Memory`.
|
* Expose `Memory`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = Memory;
|
module.exports = Memory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('./globalize');
|
var g = require('./globalize');
|
||||||
var juggler = require('loopback-datasource-juggler');
|
var juggler = require('loopback-datasource-juggler');
|
||||||
var remoting = require('strong-remoting');
|
var remoting = require('strong-remoting');
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var SG = require('strong-globalize');
|
var SG = require('strong-globalize');
|
||||||
|
|
||||||
SG.SetRootDir(path.join(__dirname, '..'), { autonomousMsgLoading: 'all' });
|
SG.SetRootDir(path.join(__dirname, '..'), {autonomousMsgLoading: 'all'});
|
||||||
module.exports = SG();
|
module.exports = SG();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
var loopbackExpress = require('./server-app');
|
var loopbackExpress = require('./server-app');
|
||||||
var proto = require('./application');
|
var proto = require('./application');
|
||||||
|
@ -93,6 +94,8 @@ function createApplication(options) {
|
||||||
// and thus browserify can process them (include connectors in the bundle)
|
// and thus browserify can process them (include connectors in the bundle)
|
||||||
app.connector('memory', loopback.Memory);
|
app.connector('memory', loopback.Memory);
|
||||||
app.connector('remote', loopback.Remote);
|
app.connector('remote', loopback.Remote);
|
||||||
|
app.connector('kv-memory',
|
||||||
|
require('loopback-datasource-juggler/lib/connectors/kv-memory'));
|
||||||
|
|
||||||
if (loopback.localRegistry || options && options.localRegistry === true) {
|
if (loopback.localRegistry || options && options.localRegistry === true) {
|
||||||
// setup the app registry
|
// setup the app registry
|
||||||
|
@ -179,7 +182,7 @@ loopback.remoteMethod = function(fn, options) {
|
||||||
fn[key] = options[key];
|
fn[key] = options[key];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
fn.http = fn.http || { verb: 'get' };
|
fn.http = fn.http || {verb: 'get'};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
114
lib/model.js
114
lib/model.js
|
@ -6,7 +6,7 @@
|
||||||
/*!
|
/*!
|
||||||
* Module Dependencies.
|
* Module Dependencies.
|
||||||
*/
|
*/
|
||||||
|
'use strict';
|
||||||
var g = require('./globalize');
|
var g = require('./globalize');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var RemoteObjects = require('strong-remoting');
|
var RemoteObjects = require('strong-remoting');
|
||||||
|
@ -180,16 +180,16 @@ module.exports = function(registry) {
|
||||||
|
|
||||||
var idDesc = ModelCtor.modelName + ' id';
|
var 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},
|
||||||
// {arg: 'instance', type: 'object', http: {source: 'body'}}
|
// {arg: 'instance', type: 'object', http: {source: 'body'}}
|
||||||
];
|
];
|
||||||
|
|
||||||
ModelCtor.sharedCtor.http = [
|
ModelCtor.sharedCtor.http = [
|
||||||
{ path: '/:id' },
|
{path: '/:id'},
|
||||||
];
|
];
|
||||||
|
|
||||||
ModelCtor.sharedCtor.returns = { root: true };
|
ModelCtor.sharedCtor.returns = {root: true};
|
||||||
|
|
||||||
// before remote hook
|
// before remote hook
|
||||||
ModelCtor.beforeRemote = function(name, fn) {
|
ModelCtor.beforeRemote = function(name, fn) {
|
||||||
|
@ -326,7 +326,7 @@ module.exports = function(registry) {
|
||||||
|
|
||||||
Model._getAccessTypeForMethod = function(method) {
|
Model._getAccessTypeForMethod = function(method) {
|
||||||
if (typeof method === 'string') {
|
if (typeof method === 'string') {
|
||||||
method = { name: method };
|
method = {name: method};
|
||||||
}
|
}
|
||||||
assert(
|
assert(
|
||||||
typeof method === 'object',
|
typeof method === 'object',
|
||||||
|
@ -463,11 +463,11 @@ module.exports = function(registry) {
|
||||||
var pathName = (relation.options.http && relation.options.http.path) || relationName;
|
var 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},
|
||||||
accepts: { arg: 'refresh', type: 'boolean', http: { source: 'query' }},
|
accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}},
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
description: format('Fetches belongsTo relation %s.', relationName),
|
description: format('Fetches belongsTo relation %s.', relationName),
|
||||||
returns: { arg: relationName, type: modelName, root: true },
|
returns: {arg: relationName, type: modelName, root: true},
|
||||||
}, fn);
|
}, fn);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -488,35 +488,35 @@ module.exports = function(registry) {
|
||||||
|
|
||||||
define('__get__' + relationName, {
|
define('__get__' + relationName, {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
http: { verb: 'get', path: '/' + pathName },
|
http: {verb: 'get', path: '/' + pathName},
|
||||||
accepts: { arg: 'refresh', type: 'boolean', http: { source: 'query' }},
|
accepts: {arg: 'refresh', type: 'boolean', http: {source: 'query'}},
|
||||||
description: format('Fetches hasOne relation %s.', relationName),
|
description: format('Fetches hasOne relation %s.', relationName),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
returns: { arg: relationName, type: relation.modelTo.modelName, root: true },
|
returns: {arg: relationName, type: relation.modelTo.modelName, root: true},
|
||||||
rest: { after: convertNullToNotFoundError.bind(null, toModelName) },
|
rest: {after: convertNullToNotFoundError.bind(null, toModelName)},
|
||||||
});
|
});
|
||||||
|
|
||||||
define('__create__' + relationName, {
|
define('__create__' + relationName, {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
http: { verb: 'post', path: '/' + pathName },
|
http: {verb: 'post', path: '/' + pathName},
|
||||||
accepts: { arg: 'data', type: 'object', model: toModelName, http: { source: 'body' }},
|
accepts: {arg: 'data', type: 'object', model: toModelName, http: {source: 'body'}},
|
||||||
description: format('Creates a new instance in %s of this model.', relationName),
|
description: format('Creates a new instance in %s of this model.', relationName),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
returns: { arg: 'data', type: toModelName, root: true },
|
returns: {arg: 'data', type: toModelName, root: true},
|
||||||
});
|
});
|
||||||
|
|
||||||
define('__update__' + relationName, {
|
define('__update__' + relationName, {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
http: { verb: 'put', path: '/' + pathName },
|
http: {verb: 'put', path: '/' + pathName},
|
||||||
accepts: { arg: 'data', type: 'object', model: toModelName, http: { source: 'body' }},
|
accepts: {arg: 'data', type: 'object', model: toModelName, http: {source: 'body'}},
|
||||||
description: format('Update %s of this model.', relationName),
|
description: format('Update %s of this model.', relationName),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
returns: { arg: 'data', type: toModelName, root: true },
|
returns: {arg: 'data', type: toModelName, root: true},
|
||||||
});
|
});
|
||||||
|
|
||||||
define('__destroy__' + relationName, {
|
define('__destroy__' + relationName, {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
http: { verb: 'delete', path: '/' + pathName },
|
http: {verb: 'delete', path: '/' + pathName},
|
||||||
description: format('Deletes %s of this model.', relationName),
|
description: format('Deletes %s of this model.', relationName),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
});
|
});
|
||||||
|
@ -529,25 +529,25 @@ module.exports = function(registry) {
|
||||||
var findByIdFunc = this.prototype['__findById__' + relationName];
|
var 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'},
|
||||||
accepts: { arg: 'fk', type: 'any',
|
accepts: {arg: 'fk', type: 'any',
|
||||||
description: format('Foreign key for %s', relationName),
|
description: format('Foreign key for %s', relationName),
|
||||||
required: true,
|
required: true,
|
||||||
http: { source: 'path' }},
|
http: {source: 'path'}},
|
||||||
description: format('Find a related item by id for %s.', relationName),
|
description: format('Find a related item by id for %s.', relationName),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
returns: { arg: 'result', type: toModelName, root: true },
|
returns: {arg: 'result', type: toModelName, root: true},
|
||||||
rest: { after: convertNullToNotFoundError.bind(null, toModelName) },
|
rest: {after: convertNullToNotFoundError.bind(null, toModelName)},
|
||||||
}, findByIdFunc);
|
}, findByIdFunc);
|
||||||
|
|
||||||
var destroyByIdFunc = this.prototype['__destroyById__' + relationName];
|
var 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'},
|
||||||
accepts: { arg: 'fk', type: 'any',
|
accepts: {arg: 'fk', type: 'any',
|
||||||
description: format('Foreign key for %s', relationName),
|
description: format('Foreign key for %s', relationName),
|
||||||
required: true,
|
required: true,
|
||||||
http: { source: 'path' }},
|
http: {source: 'path'}},
|
||||||
description: format('Delete a related item by id for %s.', relationName),
|
description: format('Delete a related item by id for %s.', relationName),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
returns: [],
|
returns: [],
|
||||||
|
@ -556,17 +556,17 @@ module.exports = function(registry) {
|
||||||
var updateByIdFunc = this.prototype['__updateById__' + relationName];
|
var 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'},
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'fk', type: 'any',
|
{arg: 'fk', type: 'any',
|
||||||
description: format('Foreign key for %s', relationName),
|
description: format('Foreign key for %s', relationName),
|
||||||
required: true,
|
required: true,
|
||||||
http: { source: 'path' }},
|
http: {source: 'path'}},
|
||||||
{ arg: 'data', type: 'object', model: toModelName, http: { source: 'body' }},
|
{arg: 'data', type: 'object', model: toModelName, http: {source: 'body'}},
|
||||||
],
|
],
|
||||||
description: format('Update a related item by id for %s.', relationName),
|
description: format('Update a related item by id for %s.', relationName),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
returns: { arg: 'result', type: toModelName, root: true },
|
returns: {arg: 'result', type: toModelName, root: true},
|
||||||
}, updateByIdFunc);
|
}, updateByIdFunc);
|
||||||
|
|
||||||
if (relation.modelThrough || relation.type === 'referencesMany') {
|
if (relation.modelThrough || relation.type === 'referencesMany') {
|
||||||
|
@ -577,31 +577,31 @@ module.exports = function(registry) {
|
||||||
// Restrict: only hasManyThrough relation can have additional properties
|
// Restrict: only hasManyThrough relation can have additional properties
|
||||||
accepts.push({
|
accepts.push({
|
||||||
arg: 'data', type: 'object', model: modelThrough.modelName,
|
arg: 'data', type: 'object', model: modelThrough.modelName,
|
||||||
http: { source: 'body' },
|
http: {source: 'body'},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var addFunc = this.prototype['__link__' + relationName];
|
var 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'},
|
||||||
accepts: [{ arg: 'fk', type: 'any',
|
accepts: [{arg: 'fk', type: 'any',
|
||||||
description: format('Foreign key for %s', relationName),
|
description: format('Foreign key for %s', relationName),
|
||||||
required: true,
|
required: true,
|
||||||
http: { source: 'path' }}].concat(accepts),
|
http: {source: 'path'}}].concat(accepts),
|
||||||
description: format('Add a related item by id for %s.', relationName),
|
description: format('Add a related item by id for %s.', relationName),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
returns: { arg: relationName, type: modelThrough.modelName, root: true },
|
returns: {arg: relationName, type: modelThrough.modelName, root: true},
|
||||||
}, addFunc);
|
}, addFunc);
|
||||||
|
|
||||||
var removeFunc = this.prototype['__unlink__' + relationName];
|
var 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'},
|
||||||
accepts: { arg: 'fk', type: 'any',
|
accepts: {arg: 'fk', type: 'any',
|
||||||
description: format('Foreign key for %s', relationName),
|
description: format('Foreign key for %s', relationName),
|
||||||
required: true,
|
required: true,
|
||||||
http: { source: 'path' }},
|
http: {source: 'path'}},
|
||||||
description: format('Remove the %s relation to an item by id.', relationName),
|
description: format('Remove the %s relation to an item by id.', relationName),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
returns: [],
|
returns: [],
|
||||||
|
@ -612,14 +612,14 @@ module.exports = function(registry) {
|
||||||
var existsFunc = this.prototype['__exists__' + relationName];
|
var 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'},
|
||||||
accepts: { arg: 'fk', type: 'any',
|
accepts: {arg: 'fk', type: 'any',
|
||||||
description: format('Foreign key for %s', relationName),
|
description: format('Foreign key for %s', relationName),
|
||||||
required: true,
|
required: true,
|
||||||
http: { source: 'path' }},
|
http: {source: 'path'}},
|
||||||
description: format('Check the existence of %s relation to an item by id.', relationName),
|
description: format('Check the existence of %s relation to an item by id.', relationName),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
returns: { arg: 'exists', type: 'boolean', root: true },
|
returns: {arg: 'exists', type: 'boolean', root: true},
|
||||||
rest: {
|
rest: {
|
||||||
// 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) {
|
||||||
|
@ -658,37 +658,37 @@ module.exports = function(registry) {
|
||||||
|
|
||||||
define('__get__' + scopeName, {
|
define('__get__' + scopeName, {
|
||||||
isStatic: isStatic,
|
isStatic: isStatic,
|
||||||
http: { verb: 'get', path: '/' + pathName },
|
http: {verb: 'get', path: '/' + pathName},
|
||||||
accepts: { arg: 'filter', type: 'object' },
|
accepts: {arg: 'filter', type: 'object'},
|
||||||
description: format('Queries %s of %s.', scopeName, this.modelName),
|
description: format('Queries %s of %s.', scopeName, this.modelName),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
returns: { arg: scopeName, type: [toModelName], root: true },
|
returns: {arg: scopeName, type: [toModelName], root: true},
|
||||||
});
|
});
|
||||||
|
|
||||||
define('__create__' + scopeName, {
|
define('__create__' + scopeName, {
|
||||||
isStatic: isStatic,
|
isStatic: isStatic,
|
||||||
http: { verb: 'post', path: '/' + pathName },
|
http: {verb: 'post', path: '/' + pathName},
|
||||||
accepts: { arg: 'data', type: 'object', model: toModelName, http: { source: 'body' }},
|
accepts: {arg: 'data', type: 'object', model: toModelName, http: {source: 'body'}},
|
||||||
description: format('Creates a new instance in %s of this model.', scopeName),
|
description: format('Creates a new instance in %s of this model.', scopeName),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
returns: { arg: 'data', type: toModelName, root: true },
|
returns: {arg: 'data', type: toModelName, root: true},
|
||||||
});
|
});
|
||||||
|
|
||||||
define('__delete__' + scopeName, {
|
define('__delete__' + scopeName, {
|
||||||
isStatic: isStatic,
|
isStatic: isStatic,
|
||||||
http: { verb: 'delete', path: '/' + pathName },
|
http: {verb: 'delete', path: '/' + pathName},
|
||||||
description: format('Deletes all %s of this model.', scopeName),
|
description: format('Deletes all %s of this model.', scopeName),
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
});
|
});
|
||||||
|
|
||||||
define('__count__' + scopeName, {
|
define('__count__' + scopeName, {
|
||||||
isStatic: isStatic,
|
isStatic: isStatic,
|
||||||
http: { verb: 'get', path: '/' + pathName + '/count' },
|
http: {verb: 'get', path: '/' + pathName + '/count'},
|
||||||
accepts: { arg: 'where', type: 'object',
|
accepts: {arg: 'where', type: 'object',
|
||||||
description: 'Criteria to match model instances' },
|
description: 'Criteria to match model instances'},
|
||||||
description: format('Counts %s of %s.', scopeName, this.modelName),
|
description: format('Counts %s of %s.', scopeName, this.modelName),
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
returns: { arg: 'count', type: 'number' },
|
returns: {arg: 'count', type: 'number'},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -732,7 +732,7 @@ module.exports = function(registry) {
|
||||||
httpPath = pathName + '/:' + paramName;
|
httpPath = pathName + '/:' + paramName;
|
||||||
acceptArgs = [
|
acceptArgs = [
|
||||||
{
|
{
|
||||||
arg: paramName, type: 'any', http: { source: 'path' },
|
arg: paramName, type: 'any', http: {source: 'path'},
|
||||||
description: format('Foreign key for %s.', relation.name),
|
description: format('Foreign key for %s.', relation.name),
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
/*!
|
/*!
|
||||||
* Module Dependencies.
|
* Module Dependencies.
|
||||||
*/
|
*/
|
||||||
|
'use strict';
|
||||||
var g = require('./globalize');
|
var g = require('./globalize');
|
||||||
var runtime = require('./runtime');
|
var runtime = require('./runtime');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
@ -642,10 +642,10 @@ module.exports = function(registry) {
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'data', type: 'object', model: typeName, allowArray: true,
|
arg: 'data', type: 'object', model: typeName, allowArray: true,
|
||||||
description: 'Model instance data',
|
description: 'Model instance data',
|
||||||
http: { source: 'body' },
|
http: {source: 'body'},
|
||||||
},
|
},
|
||||||
returns: { arg: 'data', type: typeName, root: true },
|
returns: {arg: 'data', type: typeName, root: true},
|
||||||
http: { verb: 'post', path: '/' },
|
http: {verb: 'post', path: '/'},
|
||||||
});
|
});
|
||||||
|
|
||||||
var upsertOptions = {
|
var upsertOptions = {
|
||||||
|
@ -654,15 +654,15 @@ module.exports = function(registry) {
|
||||||
'into the data source.',
|
'into the data source.',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'data', type: 'object', model: typeName, http: { source: 'body' },
|
arg: 'data', type: 'object', model: typeName, http: {source: 'body'},
|
||||||
description: 'Model instance data',
|
description: 'Model instance data',
|
||||||
},
|
},
|
||||||
returns: { arg: 'data', type: typeName, root: true },
|
returns: {arg: 'data', type: typeName, root: true},
|
||||||
http: [{ verb: 'patch', path: '/' }],
|
http: [{verb: 'patch', path: '/'}],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!options.replaceOnPUT) {
|
if (!options.replaceOnPUT) {
|
||||||
upsertOptions.http.unshift({ verb: 'put', path: '/' });
|
upsertOptions.http.unshift({verb: 'put', path: '/'});
|
||||||
}
|
}
|
||||||
setRemoting(PersistedModel, 'patchOrCreate', upsertOptions);
|
setRemoting(PersistedModel, 'patchOrCreate', upsertOptions);
|
||||||
|
|
||||||
|
@ -671,15 +671,15 @@ module.exports = function(registry) {
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'data', type: 'object', model: typeName,
|
arg: 'data', type: 'object', model: typeName,
|
||||||
http: { source: 'body' },
|
http: {source: 'body'},
|
||||||
description: 'Model instance data',
|
description: 'Model instance data',
|
||||||
},
|
},
|
||||||
returns: { arg: 'data', type: typeName, root: true },
|
returns: {arg: 'data', type: typeName, root: true},
|
||||||
http: [{ verb: 'post', path: '/replaceOrCreate' }],
|
http: [{verb: 'post', path: '/replaceOrCreate'}],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.replaceOnPUT) {
|
if (options.replaceOnPUT) {
|
||||||
replaceOrCreateOptions.http.push({ verb: 'put', path: '/' });
|
replaceOrCreateOptions.http.push({verb: 'put', path: '/'});
|
||||||
}
|
}
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'replaceOrCreate', replaceOrCreateOptions);
|
setRemoting(PersistedModel, 'replaceOrCreate', replaceOrCreateOptions);
|
||||||
|
@ -690,23 +690,23 @@ module.exports = function(registry) {
|
||||||
'the data source based on the where criteria.',
|
'the data source based on the where criteria.',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'where', type: 'object', http: { source: 'query' },
|
{arg: 'where', type: 'object', http: {source: 'query'},
|
||||||
description: 'Criteria to match model instances' },
|
description: 'Criteria to match model instances'},
|
||||||
{ arg: 'data', type: 'object', model: typeName, http: { source: 'body' },
|
{arg: 'data', type: 'object', model: typeName, http: {source: 'body'},
|
||||||
description: 'An object of model property name/value pairs' },
|
description: 'An object of model property name/value pairs'},
|
||||||
],
|
],
|
||||||
returns: { arg: 'data', type: typeName, root: true },
|
returns: {arg: 'data', type: typeName, root: true},
|
||||||
http: { verb: 'post', path: '/upsertWithWhere' },
|
http: {verb: 'post', path: '/upsertWithWhere'},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'exists', {
|
setRemoting(PersistedModel, 'exists', {
|
||||||
description: 'Check whether a model instance exists in the data source.',
|
description: 'Check whether a model instance exists in the data source.',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: { arg: 'id', type: 'any', description: 'Model id', required: true },
|
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true},
|
||||||
returns: { arg: 'exists', type: 'boolean' },
|
returns: {arg: 'exists', type: 'boolean'},
|
||||||
http: [
|
http: [
|
||||||
{ verb: 'get', path: '/:id/exists' },
|
{verb: 'get', path: '/:id/exists'},
|
||||||
{ verb: 'head', path: '/:id' },
|
{verb: 'head', path: '/:id'},
|
||||||
],
|
],
|
||||||
rest: {
|
rest: {
|
||||||
// After hook to map exists to 200/404 for HEAD
|
// After hook to map exists to 200/404 for HEAD
|
||||||
|
@ -734,66 +734,65 @@ module.exports = function(registry) {
|
||||||
description: 'Find a model instance by {{id}} from the data source.',
|
description: 'Find a model instance by {{id}} from the data source.',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'id', type: 'any', description: 'Model id', required: true,
|
{arg: 'id', type: 'any', description: 'Model id', required: true,
|
||||||
http: { source: 'path' }},
|
http: {source: 'path'}},
|
||||||
{ arg: 'filter', type: 'object',
|
{arg: 'filter', type: 'object',
|
||||||
description: 'Filter defining fields and include' },
|
description: 'Filter defining fields and include'},
|
||||||
],
|
],
|
||||||
returns: { arg: 'data', type: typeName, root: true },
|
returns: {arg: 'data', type: typeName, root: true},
|
||||||
http: { verb: 'get', path: '/:id' },
|
http: {verb: 'get', path: '/:id'},
|
||||||
rest: { after: convertNullToNotFoundError },
|
rest: {after: convertNullToNotFoundError},
|
||||||
});
|
});
|
||||||
|
|
||||||
var replaceByIdOptions = {
|
var 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: [
|
||||||
{ arg: 'id', type: 'any', description: 'Model id', required: true,
|
{arg: 'id', type: 'any', description: 'Model id', required: true,
|
||||||
http: { source: 'path' }},
|
http: {source: 'path'}},
|
||||||
{ arg: 'data', type: 'object', model: typeName, http: { source: 'body' }, description:
|
{arg: 'data', type: 'object', model: typeName, http: {source: 'body'}, description:
|
||||||
'Model instance data' },
|
'Model instance data'},
|
||||||
],
|
],
|
||||||
returns: { arg: 'data', type: typeName, root: true },
|
returns: {arg: 'data', type: typeName, root: true},
|
||||||
http: [{ verb: 'post', path: '/:id/replace' }],
|
http: [{verb: 'post', path: '/:id/replace'}],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.replaceOnPUT) {
|
if (options.replaceOnPUT) {
|
||||||
replaceByIdOptions.http.push({ verb: 'put', path: '/:id' });
|
replaceByIdOptions.http.push({verb: 'put', path: '/:id'});
|
||||||
}
|
}
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'replaceById', replaceByIdOptions);
|
setRemoting(PersistedModel, 'replaceById', replaceByIdOptions);
|
||||||
|
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'find', {
|
setRemoting(PersistedModel, 'find', {
|
||||||
description: 'Find all instances of the model matched by filter from the data source.',
|
description: 'Find all instances of the model matched by filter from the data source.',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: { arg: 'filter', type: 'object', description:
|
accepts: {arg: 'filter', type: 'object', description:
|
||||||
'Filter defining fields, where, include, order, offset, and limit' },
|
'Filter defining fields, where, include, order, offset, and limit'},
|
||||||
returns: { arg: 'data', type: [typeName], root: true },
|
returns: {arg: 'data', type: [typeName], root: true},
|
||||||
http: { verb: 'get', path: '/' },
|
http: {verb: 'get', path: '/'},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'findOne', {
|
setRemoting(PersistedModel, 'findOne', {
|
||||||
description: 'Find first instance of the model matched by filter from the data source.',
|
description: 'Find first instance of the model matched by filter from the data source.',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: { arg: 'filter', type: 'object', description:
|
accepts: {arg: 'filter', type: 'object', description:
|
||||||
'Filter defining fields, where, include, order, offset, and limit' },
|
'Filter defining fields, where, include, order, offset, and limit'},
|
||||||
returns: { arg: 'data', type: typeName, root: true },
|
returns: {arg: 'data', type: typeName, root: true},
|
||||||
http: { verb: 'get', path: '/findOne' },
|
http: {verb: 'get', path: '/findOne'},
|
||||||
rest: { after: convertNullToNotFoundError },
|
rest: {after: convertNullToNotFoundError},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'destroyAll', {
|
setRemoting(PersistedModel, 'destroyAll', {
|
||||||
description: 'Delete all matching records.',
|
description: 'Delete all matching records.',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: { arg: 'where', type: 'object', description: 'filter.where object' },
|
accepts: {arg: 'where', type: 'object', description: 'filter.where object'},
|
||||||
returns: {
|
returns: {
|
||||||
arg: 'count',
|
arg: 'count',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The number of instances deleted',
|
description: 'The number of instances deleted',
|
||||||
root: true,
|
root: true,
|
||||||
},
|
},
|
||||||
http: { verb: 'del', path: '/' },
|
http: {verb: 'del', path: '/'},
|
||||||
shared: false,
|
shared: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -802,10 +801,10 @@ module.exports = function(registry) {
|
||||||
description: 'Update instances of the model matched by {{where}} from the data source.',
|
description: 'Update instances of the model matched by {{where}} from the data source.',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'where', type: 'object', http: { source: 'query' },
|
{arg: 'where', type: 'object', http: {source: 'query'},
|
||||||
description: 'Criteria to match model instances' },
|
description: 'Criteria to match model instances'},
|
||||||
{ arg: 'data', type: 'object', model: typeName, http: { source: 'body' },
|
{arg: 'data', type: 'object', model: typeName, http: {source: 'body'},
|
||||||
description: 'An object of model property name/value pairs' },
|
description: 'An object of model property name/value pairs'},
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
arg: 'info',
|
arg: 'info',
|
||||||
|
@ -818,25 +817,25 @@ module.exports = function(registry) {
|
||||||
},
|
},
|
||||||
root: true,
|
root: true,
|
||||||
},
|
},
|
||||||
http: { verb: 'post', path: '/update' },
|
http: {verb: 'post', path: '/update'},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'deleteById', {
|
setRemoting(PersistedModel, 'deleteById', {
|
||||||
aliases: ['destroyById', 'removeById'],
|
aliases: ['destroyById', 'removeById'],
|
||||||
description: 'Delete a model instance by {{id}} from the data source.',
|
description: 'Delete a model instance by {{id}} from the data source.',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: { arg: 'id', type: 'any', description: 'Model id', required: true,
|
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true,
|
||||||
http: { source: 'path' }},
|
http: {source: 'path'}},
|
||||||
http: { verb: 'del', path: '/:id' },
|
http: {verb: 'del', path: '/:id'},
|
||||||
returns: { arg: 'count', type: 'object', root: true },
|
returns: {arg: 'count', type: 'object', root: true},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'count', {
|
setRemoting(PersistedModel, 'count', {
|
||||||
description: 'Count instances of the model matched by where from the data source.',
|
description: 'Count instances of the model matched by where from the data source.',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: { arg: 'where', type: 'object', description: 'Criteria to match model instances' },
|
accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
|
||||||
returns: { arg: 'count', type: 'number' },
|
returns: {arg: 'count', type: 'number'},
|
||||||
http: { verb: 'get', path: '/count' },
|
http: {verb: 'get', path: '/count'},
|
||||||
});
|
});
|
||||||
|
|
||||||
var updateAttributesOptions = {
|
var updateAttributesOptions = {
|
||||||
|
@ -846,17 +845,17 @@ module.exports = function(registry) {
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'data', type: 'object', model: typeName,
|
arg: 'data', type: 'object', model: typeName,
|
||||||
http: { source: 'body' },
|
http: {source: 'body'},
|
||||||
description: 'An object of model property name/value pairs',
|
description: 'An object of model property name/value pairs',
|
||||||
},
|
},
|
||||||
returns: { arg: 'data', type: typeName, root: true },
|
returns: {arg: 'data', type: typeName, root: true},
|
||||||
http: [{ verb: 'patch', path: '/' }],
|
http: [{verb: 'patch', path: '/'}],
|
||||||
};
|
};
|
||||||
|
|
||||||
setRemoting(PersistedModel.prototype, 'patchAttributes', updateAttributesOptions);
|
setRemoting(PersistedModel.prototype, 'patchAttributes', updateAttributesOptions);
|
||||||
|
|
||||||
if (!options.replaceOnPUT) {
|
if (!options.replaceOnPUT) {
|
||||||
updateAttributesOptions.http.unshift({ verb: 'put', path: '/' });
|
updateAttributesOptions.http.unshift({verb: 'put', path: '/'});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.trackChanges || options.enableRemoteReplication) {
|
if (options.trackChanges || options.enableRemoteReplication) {
|
||||||
|
@ -864,12 +863,12 @@ module.exports = function(registry) {
|
||||||
description: 'Get a set of deltas and conflicts since the given checkpoint.',
|
description: 'Get a set of deltas and conflicts since the given checkpoint.',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'since', type: 'number', description: 'Find deltas since this checkpoint' },
|
{arg: 'since', type: 'number', description: 'Find deltas since this checkpoint'},
|
||||||
{ arg: 'remoteChanges', type: 'array', description: 'an array of change objects',
|
{arg: 'remoteChanges', type: 'array', description: 'an array of change objects',
|
||||||
http: { source: 'body' }},
|
http: {source: 'body'}},
|
||||||
],
|
],
|
||||||
returns: { arg: 'result', type: 'object', root: true },
|
returns: {arg: 'result', type: 'object', root: true},
|
||||||
http: { verb: 'post', path: '/diff' },
|
http: {verb: 'post', path: '/diff'},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'changes', {
|
setRemoting(PersistedModel, 'changes', {
|
||||||
|
@ -877,13 +876,13 @@ module.exports = function(registry) {
|
||||||
'Provide a filter object to reduce the number of results returned.',
|
'Provide a filter object to reduce the number of results returned.',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'since', type: 'number', description:
|
{arg: 'since', type: 'number', description:
|
||||||
'Only return changes since this checkpoint' },
|
'Only return changes since this checkpoint'},
|
||||||
{ arg: 'filter', type: 'object', description:
|
{arg: 'filter', type: 'object', description:
|
||||||
'Only include changes that match this filter' },
|
'Only include changes that match this filter'},
|
||||||
],
|
],
|
||||||
returns: { arg: 'changes', type: 'array', root: true },
|
returns: {arg: 'changes', type: 'array', root: true},
|
||||||
http: { verb: 'get', path: '/changes' },
|
http: {verb: 'get', path: '/changes'},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'checkpoint', {
|
setRemoting(PersistedModel, 'checkpoint', {
|
||||||
|
@ -893,15 +892,15 @@ module.exports = function(registry) {
|
||||||
// We need to allow this method for users that don't have full
|
// We need to allow this method for users that don't have full
|
||||||
// WRITE permissions.
|
// WRITE permissions.
|
||||||
accessType: 'REPLICATE',
|
accessType: 'REPLICATE',
|
||||||
returns: { arg: 'checkpoint', type: 'object', root: true },
|
returns: {arg: 'checkpoint', type: 'object', root: true},
|
||||||
http: { verb: 'post', path: '/checkpoint' },
|
http: {verb: 'post', path: '/checkpoint'},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'currentCheckpoint', {
|
setRemoting(PersistedModel, 'currentCheckpoint', {
|
||||||
description: 'Get the current checkpoint.',
|
description: 'Get the current checkpoint.',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
returns: { arg: 'checkpoint', type: 'object', root: true },
|
returns: {arg: 'checkpoint', type: 'object', root: true},
|
||||||
http: { verb: 'get', path: '/checkpoint' },
|
http: {verb: 'get', path: '/checkpoint'},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'createUpdates', {
|
setRemoting(PersistedModel, 'createUpdates', {
|
||||||
|
@ -910,27 +909,27 @@ module.exports = function(registry) {
|
||||||
// It is called by the replication algorithm to compile a list
|
// It is called by the replication algorithm to compile a list
|
||||||
// of changes to apply on the target.
|
// of changes to apply on the target.
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: { arg: 'deltas', type: 'array', http: { source: 'body' }},
|
accepts: {arg: 'deltas', type: 'array', http: {source: 'body'}},
|
||||||
returns: { arg: 'updates', type: 'array', root: true },
|
returns: {arg: 'updates', type: 'array', root: true},
|
||||||
http: { verb: 'post', path: '/create-updates' },
|
http: {verb: 'post', path: '/create-updates'},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'bulkUpdate', {
|
setRemoting(PersistedModel, 'bulkUpdate', {
|
||||||
description: 'Run multiple updates at once. Note: this is not atomic.',
|
description: 'Run multiple updates at once. Note: this is not atomic.',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: { arg: 'updates', type: 'array' },
|
accepts: {arg: 'updates', type: 'array'},
|
||||||
http: { verb: 'post', path: '/bulk-update' },
|
http: {verb: 'post', path: '/bulk-update'},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'findLastChange', {
|
setRemoting(PersistedModel, 'findLastChange', {
|
||||||
description: 'Get the most recent change record for this instance.',
|
description: 'Get the most recent change record for this instance.',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'id', type: 'any', required: true, http: { source: 'path' },
|
arg: 'id', type: 'any', required: true, http: {source: 'path'},
|
||||||
description: 'Model id',
|
description: 'Model id',
|
||||||
},
|
},
|
||||||
returns: { arg: 'result', type: this.Change.modelName, root: true },
|
returns: {arg: 'result', type: this.Change.modelName, root: true},
|
||||||
http: { verb: 'get', path: '/:id/changes/last' },
|
http: {verb: 'get', path: '/:id/changes/last'},
|
||||||
});
|
});
|
||||||
|
|
||||||
setRemoting(PersistedModel, 'updateLastChange', {
|
setRemoting(PersistedModel, 'updateLastChange', {
|
||||||
|
@ -940,16 +939,16 @@ module.exports = function(registry) {
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
arg: 'id', type: 'any', required: true, http: { source: 'path' },
|
arg: 'id', type: 'any', required: true, http: {source: 'path'},
|
||||||
description: 'Model id',
|
description: 'Model id',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'data', type: 'object', model: typeName, http: { source: 'body' },
|
arg: 'data', type: 'object', model: typeName, http: {source: 'body'},
|
||||||
description: 'An object of Change property name/value pairs',
|
description: 'An object of Change property name/value pairs',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
returns: { arg: 'result', type: this.Change.modelName, root: true },
|
returns: {arg: 'result', type: this.Change.modelName, root: true},
|
||||||
http: { verb: 'put', path: '/:id/changes/last' },
|
http: {verb: 'put', path: '/:id/changes/last'},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -957,8 +956,8 @@ module.exports = function(registry) {
|
||||||
description: 'Create a change stream.',
|
description: 'Create a change stream.',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
http: [
|
http: [
|
||||||
{ verb: 'post', path: '/change-stream' },
|
{verb: 'post', path: '/change-stream'},
|
||||||
{ verb: 'get', path: '/change-stream' },
|
{verb: 'get', path: '/change-stream'},
|
||||||
],
|
],
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'options',
|
arg: 'options',
|
||||||
|
@ -1021,8 +1020,8 @@ module.exports = function(registry) {
|
||||||
filter.fields[idName] = true;
|
filter.fields[idName] = true;
|
||||||
|
|
||||||
// TODO(ritch) this whole thing could be optimized a bit more
|
// TODO(ritch) this whole thing could be optimized a bit more
|
||||||
Change.find({ where: {
|
Change.find({where: {
|
||||||
checkpoint: { gte: since },
|
checkpoint: {gte: since},
|
||||||
modelName: this.modelName,
|
modelName: this.modelName,
|
||||||
}}, function(err, changes) {
|
}}, function(err, changes) {
|
||||||
if (err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
@ -1030,7 +1029,7 @@ module.exports = function(registry) {
|
||||||
var ids = changes.map(function(change) {
|
var 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) {
|
var modelIds = models.map(function(m) {
|
||||||
|
@ -1097,7 +1096,7 @@ module.exports = function(registry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof since !== 'object') {
|
if (typeof since !== 'object') {
|
||||||
since = { source: since, target: since };
|
since = {source: since, target: since};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof options === 'function') {
|
if (typeof options === 'function') {
|
||||||
|
@ -1268,7 +1267,7 @@ module.exports = function(registry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
var newCheckpoints = { source: newSourceCp, target: newTargetCp };
|
var newCheckpoints = {source: newSourceCp, target: newTargetCp};
|
||||||
callback(null, conflicts, newCheckpoints, updates);
|
callback(null, conflicts, newCheckpoints, updates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1291,7 +1290,7 @@ module.exports = function(registry) {
|
||||||
deltas.forEach(function(change) {
|
deltas.forEach(function(change) {
|
||||||
change = new Change(change);
|
change = new Change(change);
|
||||||
var type = change.type();
|
var type = change.type();
|
||||||
var update = { type: type, change: change };
|
var update = {type: type, change: change};
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Change.CREATE:
|
case Change.CREATE:
|
||||||
case Change.UPDATE:
|
case Change.UPDATE:
|
||||||
|
@ -1383,7 +1382,7 @@ module.exports = function(registry) {
|
||||||
if (conflicts.length) {
|
if (conflicts.length) {
|
||||||
err = new Error(g.f('Conflict'));
|
err = new Error(g.f('Conflict'));
|
||||||
err.statusCode = 409;
|
err.statusCode = 409;
|
||||||
err.details = { conflicts: conflicts };
|
err.details = {conflicts: conflicts};
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
|
@ -1395,8 +1394,8 @@ module.exports = function(registry) {
|
||||||
var idName = Model.dataSource.idName(Model.modelName);
|
var idName = Model.dataSource.idName(Model.modelName);
|
||||||
var affectedIds = updates.map(function(u) { return u.change.modelId; });
|
var affectedIds = updates.map(function(u) { return u.change.modelId; });
|
||||||
var whereAffected = {};
|
var 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 = {};
|
var dataLookup = {};
|
||||||
affectedList.forEach(function(it) {
|
affectedList.forEach(function(it) {
|
||||||
|
@ -1742,7 +1741,7 @@ module.exports = function(registry) {
|
||||||
|
|
||||||
PersistedModel.findLastChange = function(id, cb) {
|
PersistedModel.findLastChange = function(id, cb) {
|
||||||
var Change = this.getChangeModel();
|
var 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) {
|
||||||
|
@ -1778,7 +1777,7 @@ module.exports = function(registry) {
|
||||||
|
|
||||||
var idName = this.getIdName();
|
var idName = this.getIdName();
|
||||||
var Model = this;
|
var Model = this;
|
||||||
var changes = new PassThrough({ objectMode: true });
|
var changes = new PassThrough({objectMode: true});
|
||||||
var writeable = true;
|
var writeable = true;
|
||||||
|
|
||||||
changes.destroy = function() {
|
changes.destroy = function() {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('./globalize');
|
var g = require('./globalize');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var extend = require('util')._extend;
|
var extend = require('util')._extend;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var runtime = exports;
|
var runtime = exports;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('./globalize');
|
var g = require('./globalize');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
|
@ -11,7 +12,7 @@ var mergePhaseNameLists = require('loopback-phase').mergePhaseNameLists;
|
||||||
var debug = require('debug')('loopback:app');
|
var debug = require('debug')('loopback:app');
|
||||||
var stableSortInPlace = require('stable').inplace;
|
var stableSortInPlace = require('stable').inplace;
|
||||||
|
|
||||||
var BUILTIN_MIDDLEWARE = { builtin: true };
|
var BUILTIN_MIDDLEWARE = {builtin: true};
|
||||||
|
|
||||||
var proto = {};
|
var proto = {};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
exports.createPromiseCallback = createPromiseCallback;
|
exports.createPromiseCallback = createPromiseCallback;
|
||||||
var Promise = require('bluebird');
|
var Promise = require('bluebird');
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
"chai": "^3.5.0",
|
"chai": "^3.5.0",
|
||||||
"cookie-parser": "^1.3.4",
|
"cookie-parser": "^1.3.4",
|
||||||
"es5-shim": "^4.1.0",
|
"es5-shim": "^4.1.0",
|
||||||
"eslint-config-loopback": "^1.0.0",
|
"eslint-config-loopback": "^5.0.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",
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
|
|
||||||
module.exports = function() {
|
module.exports = function() {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(options) {
|
module.exports = function(options) {
|
||||||
throw new Error('loopback.errorHandler is no longer available.' +
|
throw new Error('loopback.errorHandler is no longer available.' +
|
||||||
' Please use the module "strong-error-handler" instead.');
|
' Please use the module "strong-error-handler" instead.');
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var favicon = require('serve-favicon');
|
var favicon = require('serve-favicon');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var g = require('../../lib/globalize');
|
var g = require('../../lib/globalize');
|
||||||
var loopback = require('../../lib/loopback');
|
var loopback = require('../../lib/loopback');
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
|
@ -49,7 +50,7 @@ function rest() {
|
||||||
|
|
||||||
if (app.isAuthEnabled) {
|
if (app.isAuthEnabled) {
|
||||||
var AccessToken = registry.getModelByType('AccessToken');
|
var AccessToken = registry.getModelByType('AccessToken');
|
||||||
handlers.push(loopback.token({ model: AccessToken, app: app }));
|
handlers.push(loopback.token({model: AccessToken, app: app}));
|
||||||
}
|
}
|
||||||
|
|
||||||
handlers.push(function(req, res, next) {
|
handlers.push(function(req, res, next) {
|
||||||
|
|
|
@ -13,4 +13,5 @@
|
||||||
* for the full list of available options.
|
* for the full list of available options.
|
||||||
* @header loopback.static(root, [options])
|
* @header loopback.static(root, [options])
|
||||||
*/
|
*/
|
||||||
|
'use strict';
|
||||||
module.exports = require('express').static;
|
module.exports = require('express').static;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Export the middleware.
|
* Export the middleware.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = status;
|
module.exports = status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../../lib/loopback');
|
var loopback = require('../../lib/loopback');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var debug = require('debug')('loopback:middleware:token');
|
var debug = require('debug')('loopback:middleware:token');
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
* See discussion in Connect pull request #954 for more details
|
* See discussion in Connect pull request #954 for more details
|
||||||
* https://github.com/senchalabs/connect/pull/954.
|
* https://github.com/senchalabs/connect/pull/954.
|
||||||
*/
|
*/
|
||||||
|
'use strict';
|
||||||
module.exports = urlNotFound;
|
module.exports = urlNotFound;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,14 +3,15 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../');
|
var loopback = require('../');
|
||||||
var lt = require('./helpers/loopback-testing-helper');
|
var lt = require('./helpers/loopback-testing-helper');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var ACCESS_CONTROL_APP = path.join(__dirname, 'fixtures', 'access-control');
|
var ACCESS_CONTROL_APP = path.join(__dirname, 'fixtures', 'access-control');
|
||||||
var app = require(path.join(ACCESS_CONTROL_APP, 'server/server.js'));
|
var app = require(path.join(ACCESS_CONTROL_APP, 'server/server.js'));
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var USER = { email: 'test@test.test', password: 'test' };
|
var USER = {email: 'test@test.test', password: 'test'};
|
||||||
var CURRENT_USER = { email: 'current@test.test', password: 'test' };
|
var CURRENT_USER = {email: 'current@test.test', password: 'test'};
|
||||||
var debug = require('debug')('loopback:test:access-control.integration');
|
var debug = require('debug')('loopback:test:access-control.integration');
|
||||||
|
|
||||||
describe('access control - integration', function() {
|
describe('access control - integration', function() {
|
||||||
|
@ -146,7 +147,7 @@ describe('access control - integration', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('/banks', function() {
|
describe('/banks', function() {
|
||||||
var SPECIAL_USER = { email: 'special@test.test', password: 'test' };
|
var 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
|
||||||
|
|
|
@ -3,15 +3,20 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var assert = require('assert');
|
||||||
|
var expect = require('chai').expect;
|
||||||
var cookieParser = require('cookie-parser');
|
var cookieParser = require('cookie-parser');
|
||||||
var LoopBackContext = require('loopback-context');
|
var LoopBackContext = require('loopback-context');
|
||||||
var contextMiddleware = require('loopback-context').perRequest;
|
var contextMiddleware = require('loopback-context').perRequest;
|
||||||
var loopback = require('../');
|
var loopback = require('../');
|
||||||
var extend = require('util')._extend;
|
var extend = require('util')._extend;
|
||||||
var session = require('express-session');
|
var session = require('express-session');
|
||||||
|
var request = require('supertest');
|
||||||
|
var app = loopback();
|
||||||
|
|
||||||
var Token = loopback.AccessToken.extend('MyToken');
|
var Token = loopback.AccessToken.extend('MyToken');
|
||||||
var ds = loopback.createDataSource({ connector: loopback.Memory });
|
var ds = loopback.createDataSource({connector: loopback.Memory});
|
||||||
Token.attachTo(ds);
|
Token.attachTo(ds);
|
||||||
var ACL = loopback.ACL;
|
var ACL = loopback.ACL;
|
||||||
|
|
||||||
|
@ -50,7 +55,7 @@ describe('loopback.token(options)', function() {
|
||||||
var tokenId = this.token.id;
|
var tokenId = this.token.id;
|
||||||
var app = createTestApp(
|
var app = createTestApp(
|
||||||
this.token,
|
this.token,
|
||||||
{ token: { searchDefaultTokenKeys: false }},
|
{token: {searchDefaultTokenKeys: false}},
|
||||||
done);
|
done);
|
||||||
var agent = request.agent(app);
|
var agent = request.agent(app);
|
||||||
|
|
||||||
|
@ -158,7 +163,7 @@ describe('loopback.token(options)', function() {
|
||||||
.set('authorization', id)
|
.set('authorization', id)
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
assert(!err);
|
assert(!err);
|
||||||
assert.deepEqual(res.body, { userId: userId });
|
assert.deepEqual(res.body, {userId: userId});
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -174,7 +179,7 @@ describe('loopback.token(options)', function() {
|
||||||
.set('authorization', id)
|
.set('authorization', id)
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
assert(!err);
|
assert(!err);
|
||||||
assert.deepEqual(res.body, { userId: userId, state: 1 });
|
assert.deepEqual(res.body, {userId: userId, state: 1});
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -190,20 +195,20 @@ describe('loopback.token(options)', function() {
|
||||||
.set('authorization', id)
|
.set('authorization', id)
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
assert(!err);
|
assert(!err);
|
||||||
assert.deepEqual(res.body, { userId: userId, state: 1 });
|
assert.deepEqual(res.body, {userId: userId, state: 1});
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should skip when req.token is already present', function(done) {
|
it('should skip when req.token is already present', function(done) {
|
||||||
var tokenStub = { id: 'stub id' };
|
var tokenStub = {id: 'stub id'};
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
req.accessToken = tokenStub;
|
req.accessToken = tokenStub;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
app.use(loopback.token({ model: Token }));
|
app.use(loopback.token({model: Token}));
|
||||||
app.get('/', function(req, res, next) {
|
app.get('/', function(req, res, next) {
|
||||||
res.send(req.accessToken);
|
res.send(req.accessToken);
|
||||||
});
|
});
|
||||||
|
@ -223,13 +228,13 @@ describe('loopback.token(options)', function() {
|
||||||
describe('loading multiple instances of token middleware', function() {
|
describe('loading multiple instances of token middleware', function() {
|
||||||
it('should skip when req.token is already present and no further options are set',
|
it('should skip when req.token is already present and no further options are set',
|
||||||
function(done) {
|
function(done) {
|
||||||
var tokenStub = { id: 'stub id' };
|
var tokenStub = {id: 'stub id'};
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
req.accessToken = tokenStub;
|
req.accessToken = tokenStub;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
app.use(loopback.token({ model: Token }));
|
app.use(loopback.token({model: Token}));
|
||||||
app.get('/', function(req, res, next) {
|
app.get('/', function(req, res, next) {
|
||||||
res.send(req.accessToken);
|
res.send(req.accessToken);
|
||||||
});
|
});
|
||||||
|
@ -249,7 +254,7 @@ describe('loopback.token(options)', function() {
|
||||||
it('should not overwrite valid existing token (has "id" property) ' +
|
it('should 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' };
|
var tokenStub = {id: 'stub id'};
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
req.accessToken = tokenStub;
|
req.accessToken = tokenStub;
|
||||||
|
|
||||||
|
@ -279,7 +284,7 @@ describe('loopback.token(options)', function() {
|
||||||
' when enableDoubkecheck is true',
|
' when enableDoubkecheck is true',
|
||||||
function(done) {
|
function(done) {
|
||||||
var token = this.token;
|
var token = this.token;
|
||||||
|
var app = loopback();
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
req.accessToken = null;
|
req.accessToken = null;
|
||||||
next();
|
next();
|
||||||
|
@ -313,8 +318,8 @@ describe('loopback.token(options)', function() {
|
||||||
'and overwriteExistingToken options are truthy',
|
'and overwriteExistingToken options are truthy',
|
||||||
function(done) {
|
function(done) {
|
||||||
var token = this.token;
|
var token = this.token;
|
||||||
var tokenStub = { id: 'stub id' };
|
var tokenStub = {id: 'stub id'};
|
||||||
|
var app = loopback();
|
||||||
app.use(function(req, res, next) {
|
app.use(function(req, res, next) {
|
||||||
req.accessToken = tokenStub;
|
req.accessToken = tokenStub;
|
||||||
|
|
||||||
|
@ -385,7 +390,7 @@ describe('AccessToken', function() {
|
||||||
// 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;
|
||||||
|
|
||||||
Token.create({ userId: '123', ttl: -1 }, function(err, token) {
|
Token.create({userId: '123', ttl: -1}, function(err, token) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
token.validate(function(err, isValid) {
|
token.validate(function(err, isValid) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
@ -402,7 +407,7 @@ describe('AccessToken', function() {
|
||||||
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;
|
var expectedTokenId = this.token.id;
|
||||||
var req = mockRequest({
|
var req = mockRequest({
|
||||||
headers: { 'authorization': expectedTokenId },
|
headers: {'authorization': expectedTokenId},
|
||||||
});
|
});
|
||||||
|
|
||||||
Token.findForRequest(req, function(err, token) {
|
Token.findForRequest(req, function(err, token) {
|
||||||
|
@ -435,7 +440,7 @@ describe('app.enableAuth()', function() {
|
||||||
var app;
|
var app;
|
||||||
beforeEach(function setupAuthWithModels() {
|
beforeEach(function setupAuthWithModels() {
|
||||||
app = loopback();
|
app = loopback();
|
||||||
app.enableAuth({ dataSource: ds });
|
app.enableAuth({dataSource: ds});
|
||||||
});
|
});
|
||||||
beforeEach(createTestingToken);
|
beforeEach(createTestingToken);
|
||||||
|
|
||||||
|
@ -458,7 +463,7 @@ describe('app.enableAuth()', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('prevent remote call with app setting status on denied ACL', function(done) {
|
it('prevent remote call with app setting status on denied ACL', function(done) {
|
||||||
createTestAppAndRequest(this.token, { app: { aclErrorStatus: 403 }}, done)
|
createTestAppAndRequest(this.token, {app: {aclErrorStatus: 403}}, done)
|
||||||
.del('/tests/123')
|
.del('/tests/123')
|
||||||
.expect(403)
|
.expect(403)
|
||||||
.set('authorization', this.token.id)
|
.set('authorization', this.token.id)
|
||||||
|
@ -476,7 +481,7 @@ describe('app.enableAuth()', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('prevent remote call with app setting status on denied ACL', function(done) {
|
it('prevent remote call with app setting status on denied ACL', function(done) {
|
||||||
createTestAppAndRequest(this.token, { model: { aclErrorStatus: 404 }}, done)
|
createTestAppAndRequest(this.token, {model: {aclErrorStatus: 404}}, done)
|
||||||
.del('/tests/123')
|
.del('/tests/123')
|
||||||
.expect(404)
|
.expect(404)
|
||||||
.set('authorization', this.token.id)
|
.set('authorization', this.token.id)
|
||||||
|
@ -512,22 +517,22 @@ describe('app.enableAuth()', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('stores token in the context', function(done) {
|
it('stores token in the context', function(done) {
|
||||||
var TestModel = loopback.createModel('TestModel', { base: 'Model' });
|
var TestModel = loopback.createModel('TestModel', {base: 'Model'});
|
||||||
TestModel.getToken = function(cb) {
|
TestModel.getToken = function(cb) {
|
||||||
var ctx = LoopBackContext.getCurrentContext();
|
var ctx = LoopBackContext.getCurrentContext();
|
||||||
cb(null, ctx && ctx.get('accessToken') || null);
|
cb(null, ctx && ctx.get('accessToken') || null);
|
||||||
};
|
};
|
||||||
TestModel.remoteMethod('getToken', {
|
TestModel.remoteMethod('getToken', {
|
||||||
returns: { arg: 'token', type: 'object' },
|
returns: {arg: 'token', type: 'object'},
|
||||||
http: { verb: 'GET', path: '/token' },
|
http: {verb: 'GET', path: '/token'},
|
||||||
});
|
});
|
||||||
|
|
||||||
var app = loopback();
|
var app = loopback();
|
||||||
app.model(TestModel, { dataSource: null });
|
app.model(TestModel, {dataSource: null});
|
||||||
|
|
||||||
app.enableAuth();
|
app.enableAuth();
|
||||||
app.use(contextMiddleware());
|
app.use(contextMiddleware());
|
||||||
app.use(loopback.token({ model: Token }));
|
app.use(loopback.token({model: Token}));
|
||||||
app.use(loopback.rest());
|
app.use(loopback.rest());
|
||||||
|
|
||||||
var token = this.token;
|
var token = this.token;
|
||||||
|
@ -556,7 +561,7 @@ describe('app.enableAuth()', function() {
|
||||||
saveUninitialized: true,
|
saveUninitialized: true,
|
||||||
resave: true,
|
resave: true,
|
||||||
}));
|
}));
|
||||||
app.use(loopback.token({ model: Token }));
|
app.use(loopback.token({model: Token}));
|
||||||
app.get('/', function(req, res) { res.send('OK'); });
|
app.get('/', function(req, res) { res.send('OK'); });
|
||||||
app.use(loopback.rest());
|
app.use(loopback.rest());
|
||||||
|
|
||||||
|
@ -572,7 +577,7 @@ describe('app.enableAuth()', function() {
|
||||||
|
|
||||||
function createTestingToken(done) {
|
function createTestingToken(done) {
|
||||||
var test = this;
|
var 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);
|
||||||
|
|
||||||
test.token = token;
|
test.token = token;
|
||||||
|
@ -602,10 +607,10 @@ function createTestApp(testToken, settings, done) {
|
||||||
|
|
||||||
app.use(cookieParser('secret'));
|
app.use(cookieParser('secret'));
|
||||||
app.use(loopback.token(tokenSettings));
|
app.use(loopback.token(tokenSettings));
|
||||||
app.set('remoting', { errorHandler: { debug: true, log: false }});
|
app.set('remoting', {errorHandler: {debug: true, log: false}});
|
||||||
app.get('/token', function(req, res) {
|
app.get('/token', function(req, res) {
|
||||||
res.cookie('authorization', testToken.id, { signed: true });
|
res.cookie('authorization', testToken.id, {signed: true});
|
||||||
res.cookie('access_token', testToken.id, { signed: true });
|
res.cookie('access_token', testToken.id, {signed: true});
|
||||||
res.end();
|
res.end();
|
||||||
});
|
});
|
||||||
app.get('/', function(req, res) {
|
app.get('/', function(req, res) {
|
||||||
|
@ -621,7 +626,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 };
|
var 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 !== '/') {
|
||||||
|
@ -661,14 +666,14 @@ function createTestApp(testToken, settings, done) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function givenLocalTokenModel() {
|
function givenLocalTokenModel() {
|
||||||
var app = loopback({ localRegistry: true, loadBuiltinModels: true });
|
var app = loopback({localRegistry: true, loadBuiltinModels: true});
|
||||||
app.dataSource('db', { connector: 'memory' });
|
app.dataSource('db', {connector: 'memory'});
|
||||||
|
|
||||||
var User = app.registry.getModel('User');
|
var User = app.registry.getModel('User');
|
||||||
app.model(User, { dataSource: 'db' });
|
app.model(User, {dataSource: 'db'});
|
||||||
|
|
||||||
var Token = app.registry.getModel('AccessToken');
|
var Token = app.registry.getModel('AccessToken');
|
||||||
app.model(Token, { dataSource: 'db' });
|
app.model(Token, {dataSource: 'db'});
|
||||||
|
|
||||||
return Token;
|
return Token;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,20 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var loopback = require('../index');
|
var loopback = require('../index');
|
||||||
var Scope = loopback.Scope;
|
var Scope = loopback.Scope;
|
||||||
var ACL = loopback.ACL;
|
var ACL = loopback.ACL;
|
||||||
|
var request = require('supertest');
|
||||||
var Role = loopback.Role;
|
var Role = loopback.Role;
|
||||||
var RoleMapping = loopback.RoleMapping;
|
var RoleMapping = loopback.RoleMapping;
|
||||||
var User = loopback.User;
|
var User = loopback.User;
|
||||||
var testModel;
|
var testModel;
|
||||||
|
|
||||||
|
// Speed up the password hashing algorithm for tests
|
||||||
|
User.settings.saltWorkFactor = 4;
|
||||||
|
|
||||||
function checkResult(err, result) {
|
function checkResult(err, result) {
|
||||||
// console.log(err, result);
|
// console.log(err, result);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
@ -19,12 +24,12 @@ function checkResult(err, result) {
|
||||||
|
|
||||||
var ds = null;
|
var ds = null;
|
||||||
before(function() {
|
before(function() {
|
||||||
ds = loopback.createDataSource({ connector: loopback.Memory });
|
ds = loopback.createDataSource({connector: loopback.Memory});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('security scopes', function() {
|
describe('security scopes', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
var ds = this.ds = loopback.createDataSource({ connector: loopback.Memory });
|
var ds = this.ds = loopback.createDataSource({connector: loopback.Memory});
|
||||||
testModel = loopback.PersistedModel.extend('testModel');
|
testModel = loopback.PersistedModel.extend('testModel');
|
||||||
ACL.attachTo(ds);
|
ACL.attachTo(ds);
|
||||||
Role.attachTo(ds);
|
Role.attachTo(ds);
|
||||||
|
@ -35,7 +40,7 @@ describe('security scopes', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow access to models for the given scope by wildcard', function() {
|
it('should allow access to models for the given scope by wildcard', function() {
|
||||||
Scope.create({ name: 'userScope', description: 'access user information' },
|
Scope.create({name: 'userScope', description: 'access user information'},
|
||||||
function(err, scope) {
|
function(err, scope) {
|
||||||
ACL.create({
|
ACL.create({
|
||||||
principalType: ACL.SCOPE, principalId: scope.id,
|
principalType: ACL.SCOPE, principalId: scope.id,
|
||||||
|
@ -50,14 +55,14 @@ describe('security scopes', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow access to models for the given scope', function() {
|
it('should allow access to models for the given scope', function() {
|
||||||
Scope.create({ name: 'testModelScope', description: 'access testModel information' },
|
Scope.create({name: 'testModelScope', description: 'access testModel information'},
|
||||||
function(err, scope) {
|
function(err, scope) {
|
||||||
ACL.create({
|
ACL.create({
|
||||||
principalType: ACL.SCOPE, principalId: scope.id,
|
principalType: ACL.SCOPE, principalId: scope.id,
|
||||||
model: 'testModel', property: 'name',
|
model: 'testModel', property: 'name',
|
||||||
accessType: ACL.READ, permission: ACL.ALLOW,
|
accessType: ACL.READ, permission: ACL.ALLOW,
|
||||||
}, function(err, resource) {
|
}, function(err, resource) {
|
||||||
ACL.create({ principalType: ACL.SCOPE, principalId: scope.id,
|
ACL.create({principalType: ACL.SCOPE, principalId: scope.id,
|
||||||
model: 'testModel', property: 'name',
|
model: 'testModel', property: 'name',
|
||||||
accessType: ACL.WRITE, permission: ACL.DENY,
|
accessType: ACL.WRITE, permission: ACL.DENY,
|
||||||
}, function(err, resource) {
|
}, function(err, resource) {
|
||||||
|
@ -117,11 +122,11 @@ 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);
|
var perm = ACL.resolvePermission(acls, req);
|
||||||
assert.deepEqual(perm, { model: 'account',
|
assert.deepEqual(perm, {model: 'account',
|
||||||
property: 'find',
|
property: 'find',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
permission: 'ALLOW',
|
permission: 'ALLOW',
|
||||||
methodNames: [] });
|
methodNames: []});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow access to models for the given principal by wildcard', function() {
|
it('should allow access to models for the given principal by wildcard', function() {
|
||||||
|
@ -197,16 +202,16 @@ describe('security ACLs', function() {
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
acls: [
|
acls: [
|
||||||
{ principalType: ACL.USER, principalId: 'u001',
|
{principalType: ACL.USER, principalId: 'u001',
|
||||||
accessType: ACL.WRITE, permission: ACL.DENY },
|
accessType: ACL.WRITE, permission: ACL.DENY},
|
||||||
{ principalType: ACL.USER, principalId: 'u001',
|
{principalType: ACL.USER, principalId: 'u001',
|
||||||
accessType: ACL.ALL, permission: ACL.ALLOW },
|
accessType: ACL.ALL, permission: ACL.ALLOW},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
acls: [
|
acls: [
|
||||||
{ principalType: ACL.USER, principalId: 'u001',
|
{principalType: ACL.USER, principalId: 'u001',
|
||||||
accessType: ACL.ALL, permission: ACL.ALLOW },
|
accessType: ACL.ALL, permission: ACL.ALLOW},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -231,20 +236,20 @@ describe('security ACLs', function() {
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
acls: [
|
acls: [
|
||||||
{ principalType: ACL.USER, principalId: 'u001',
|
{principalType: ACL.USER, principalId: 'u001',
|
||||||
accessType: ACL.WRITE, permission: ACL.DENY },
|
accessType: ACL.WRITE, permission: ACL.DENY},
|
||||||
{ principalType: ACL.USER, principalId: 'u001',
|
{principalType: ACL.USER, principalId: 'u001',
|
||||||
accessType: ACL.ALL, permission: ACL.ALLOW },
|
accessType: ACL.ALL, permission: ACL.ALLOW},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
acls: [
|
acls: [
|
||||||
{ principalType: ACL.USER, principalId: 'u001',
|
{principalType: ACL.USER, principalId: 'u001',
|
||||||
accessType: ACL.ALL, permission: ACL.ALLOW },
|
accessType: ACL.ALL, permission: ACL.ALLOW},
|
||||||
{ principalType: ACL.USER, principalId: 'u002',
|
{principalType: ACL.USER, principalId: 'u002',
|
||||||
accessType: ACL.EXECUTE, permission: ACL.ALLOW },
|
accessType: ACL.EXECUTE, permission: ACL.ALLOW},
|
||||||
{ principalType: ACL.USER, principalId: 'u003',
|
{principalType: ACL.USER, principalId: 'u003',
|
||||||
accessType: ACL.EXECUTE, permission: ACL.DENY },
|
accessType: ACL.EXECUTE, permission: ACL.DENY},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -285,20 +290,20 @@ describe('security ACLs', function() {
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
acls: [
|
acls: [
|
||||||
{ principalType: ACL.USER, principalId: 'u001',
|
{principalType: ACL.USER, principalId: 'u001',
|
||||||
accessType: ACL.WRITE, permission: ACL.DENY },
|
accessType: ACL.WRITE, permission: ACL.DENY},
|
||||||
{ principalType: ACL.USER, principalId: 'u001',
|
{principalType: ACL.USER, principalId: 'u001',
|
||||||
accessType: ACL.ALL, permission: ACL.ALLOW },
|
accessType: ACL.ALL, permission: ACL.ALLOW},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
acls: [
|
acls: [
|
||||||
{ principalType: ACL.USER, principalId: 'u001', property: 'name',
|
{principalType: ACL.USER, principalId: 'u001', property: 'name',
|
||||||
accessType: ACL.ALL, permission: ACL.ALLOW },
|
accessType: ACL.ALL, permission: ACL.ALLOW},
|
||||||
{ principalType: ACL.USER, principalId: 'u002', property: 'findOne',
|
{principalType: ACL.USER, principalId: 'u002', property: 'findOne',
|
||||||
accessType: ACL.ALL, permission: ACL.ALLOW },
|
accessType: ACL.ALL, permission: ACL.ALLOW},
|
||||||
{ principalType: ACL.USER, principalId: 'u003', property: ['findOne', 'findById'],
|
{principalType: ACL.USER, principalId: 'u003', property: ['findOne', 'findById'],
|
||||||
accessType: ACL.ALL, permission: ACL.ALLOW },
|
accessType: ACL.ALL, permission: ACL.ALLOW},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -318,7 +323,7 @@ describe('security ACLs', function() {
|
||||||
var log = function() {};
|
var 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;
|
var userId = user.id;
|
||||||
|
@ -328,16 +333,16 @@ describe('security ACLs', function() {
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
acls: [
|
acls: [
|
||||||
{ principalType: ACL.USER, principalId: userId,
|
{principalType: ACL.USER, principalId: userId,
|
||||||
accessType: ACL.WRITE, permission: ACL.DENY },
|
accessType: ACL.WRITE, permission: ACL.DENY},
|
||||||
{ principalType: ACL.USER, principalId: userId,
|
{principalType: ACL.USER, principalId: userId,
|
||||||
accessType: ACL.ALL, permission: ACL.ALLOW },
|
accessType: ACL.ALL, permission: ACL.ALLOW},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
acls: [
|
acls: [
|
||||||
{ principalType: ACL.USER, principalId: userId,
|
{principalType: ACL.USER, principalId: userId,
|
||||||
accessType: ACL.ALL, permission: ACL.ALLOW },
|
accessType: ACL.ALL, permission: ACL.ALLOW},
|
||||||
],
|
],
|
||||||
defaultPermission: 'DENY',
|
defaultPermission: 'DENY',
|
||||||
});
|
});
|
||||||
|
@ -349,10 +354,10 @@ describe('security ACLs', function() {
|
||||||
}, function(err, acl) {
|
}, function(err, acl) {
|
||||||
log('ACL 1: ', acl.toObject());
|
log('ACL 1: ', acl.toObject());
|
||||||
|
|
||||||
Role.create({ name: 'MyRole' }, function(err, myRole) {
|
Role.create({name: 'MyRole'}, function(err, myRole) {
|
||||||
log('Role: ', myRole.toObject());
|
log('Role: ', myRole.toObject());
|
||||||
|
|
||||||
myRole.principals.create({ principalType: RoleMapping.USER, principalId: userId },
|
myRole.principals.create({principalType: RoleMapping.USER, principalId: userId},
|
||||||
function(err, p) {
|
function(err, p) {
|
||||||
log('Principal added to role: ', p.toObject());
|
log('Principal added to role: ', p.toObject());
|
||||||
|
|
||||||
|
@ -365,7 +370,7 @@ describe('security ACLs', function() {
|
||||||
|
|
||||||
ACL.checkAccessForContext({
|
ACL.checkAccessForContext({
|
||||||
principals: [
|
principals: [
|
||||||
{ type: ACL.USER, id: userId },
|
{type: ACL.USER, id: userId},
|
||||||
],
|
],
|
||||||
model: 'Customer',
|
model: 'Customer',
|
||||||
property: 'name',
|
property: 'name',
|
||||||
|
@ -376,7 +381,7 @@ describe('security ACLs', function() {
|
||||||
|
|
||||||
ACL.checkAccessForContext({
|
ACL.checkAccessForContext({
|
||||||
principals: [
|
principals: [
|
||||||
{ type: ACL.ROLE, id: Role.EVERYONE },
|
{type: ACL.ROLE, id: Role.EVERYONE},
|
||||||
],
|
],
|
||||||
model: 'Customer',
|
model: 'Customer',
|
||||||
property: 'name',
|
property: 'name',
|
||||||
|
@ -400,10 +405,10 @@ describe('access check', function() {
|
||||||
var beforeHookCalled = false;
|
var 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}});
|
||||||
app.enableAuth();
|
app.enableAuth();
|
||||||
app.dataSource('test', { connector: 'memory' });
|
app.dataSource('test', {connector: 'memory'});
|
||||||
app.model(MyTestModel, { dataSource: 'test' });
|
app.model(MyTestModel, {dataSource: 'test'});
|
||||||
|
|
||||||
// fake / spy on the checkAccess method
|
// fake / spy on the checkAccess method
|
||||||
MyTestModel.checkAccess = function() {
|
MyTestModel.checkAccess = function() {
|
||||||
|
|
|
@ -3,6 +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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var assert = require('assert');
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
|
@ -14,6 +16,7 @@ var PersistedModel = loopback.PersistedModel;
|
||||||
var describe = require('./util/describe');
|
var describe = require('./util/describe');
|
||||||
var expect = require('chai').expect;
|
var expect = require('chai').expect;
|
||||||
var it = require('./util/it');
|
var it = require('./util/it');
|
||||||
|
var request = require('supertest');
|
||||||
|
|
||||||
describe('app', function() {
|
describe('app', function() {
|
||||||
var app;
|
var app;
|
||||||
|
@ -309,7 +312,7 @@ describe('app', function() {
|
||||||
it('sets req.baseUrl and req.originalUrl', function(done) {
|
it('sets req.baseUrl and req.originalUrl', function(done) {
|
||||||
var reqProps;
|
var 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};
|
||||||
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
@ -317,7 +320,7 @@ describe('app', function() {
|
||||||
executeMiddlewareHandlers(app, '/test/url', function(err) {
|
executeMiddlewareHandlers(app, '/test/url', function(err) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(reqProps).to.eql({ baseUrl: '', originalUrl: '/test/url' });
|
expect(reqProps).to.eql({baseUrl: '', originalUrl: '/test/url'});
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -451,7 +454,7 @@ 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 = [];
|
var steps = [];
|
||||||
var expectedConfig = { key: 'value' };
|
var expectedConfig = {key: 'value'};
|
||||||
|
|
||||||
var handlerFactory = function() {
|
var handlerFactory = function() {
|
||||||
var args = Array.prototype.slice.apply(arguments);
|
var args = Array.prototype.slice.apply(arguments);
|
||||||
|
@ -495,7 +498,7 @@ describe('app', function() {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
phase: 'routes:before',
|
phase: 'routes:before',
|
||||||
methods: ['get', 'head'],
|
methods: ['get', 'head'],
|
||||||
params: { x: 1 },
|
params: {x: 1},
|
||||||
});
|
});
|
||||||
|
|
||||||
// This should be skipped as the verb doesn't match
|
// This should be skipped as the verb doesn't match
|
||||||
|
@ -503,7 +506,7 @@ describe('app', function() {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
phase: 'routes:before',
|
phase: 'routes:before',
|
||||||
methods: ['post'],
|
methods: ['post'],
|
||||||
params: { x: 2 },
|
params: {x: 2},
|
||||||
});
|
});
|
||||||
|
|
||||||
executeMiddlewareHandlers(app, function(err) {
|
executeMiddlewareHandlers(app, function(err) {
|
||||||
|
@ -513,7 +516,7 @@ describe('app', function() {
|
||||||
['before'],
|
['before'],
|
||||||
[expectedConfig],
|
[expectedConfig],
|
||||||
['after', 2],
|
['after', 2],
|
||||||
[{ x: 1 }],
|
[{x: 1}],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -618,13 +621,13 @@ describe('app', function() {
|
||||||
var app, db, MyTestModel;
|
var 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}});
|
||||||
db = loopback.createDataSource({ connector: loopback.Memory });
|
db = loopback.createDataSource({connector: loopback.Memory});
|
||||||
MyTestModel = app.registry.createModel('MyTestModel');
|
MyTestModel = app.registry.createModel('MyTestModel');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Expose a `Model` to remote clients', function() {
|
it('Expose a `Model` to remote clients', function() {
|
||||||
var Color = PersistedModel.extend('color', { name: String });
|
var Color = PersistedModel.extend('color', {name: String});
|
||||||
app.model(Color);
|
app.model(Color);
|
||||||
Color.attachTo(db);
|
Color.attachTo(db);
|
||||||
|
|
||||||
|
@ -632,14 +635,14 @@ 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 });
|
var 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 });
|
var 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; });
|
var classes = app.remotes().classes().map(function(c) { return c.name; });
|
||||||
|
@ -647,7 +650,7 @@ describe('app', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('registers existing models to app.models', function() {
|
it('registers existing models to app.models', function() {
|
||||||
var Color = db.createModel('color', { name: String });
|
var 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);
|
||||||
|
@ -656,7 +659,7 @@ describe('app', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('emits a `modelRemoted` event', function() {
|
it('emits a `modelRemoted` event', function() {
|
||||||
var Color = PersistedModel.extend('color', { name: String });
|
var Color = PersistedModel.extend('color', {name: String});
|
||||||
Color.shared = true;
|
Color.shared = true;
|
||||||
var remotedClass;
|
var remotedClass;
|
||||||
app.on('modelRemoted', function(sharedClass) {
|
app.on('modelRemoted', function(sharedClass) {
|
||||||
|
@ -668,7 +671,7 @@ describe('app', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('emits a `remoteMethodDisabled` event', function() {
|
it('emits a `remoteMethodDisabled` event', function() {
|
||||||
var Color = PersistedModel.extend('color', { name: String });
|
var Color = PersistedModel.extend('color', {name: String});
|
||||||
Color.shared = true;
|
Color.shared = true;
|
||||||
var remoteMethodDisabledClass, disabledRemoteMethod;
|
var remoteMethodDisabledClass, disabledRemoteMethod;
|
||||||
app.on('remoteMethodDisabled', function(sharedClass, methodName) {
|
app.on('remoteMethodDisabled', function(sharedClass, methodName) {
|
||||||
|
@ -687,7 +690,7 @@ describe('app', function() {
|
||||||
app.use(loopback.rest());
|
app.use(loopback.rest());
|
||||||
request(app).get('/colors').expect(404, function(err, res) {
|
request(app).get('/colors').expect(404, function(err, res) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
var Color = PersistedModel.extend('color', { name: String });
|
var Color = PersistedModel.extend('color', {name: String});
|
||||||
app.model(Color);
|
app.model(Color);
|
||||||
Color.attachTo(db);
|
Color.attachTo(db);
|
||||||
request(app).get('/colors').expect(200, done);
|
request(app).get('/colors').expect(200, done);
|
||||||
|
@ -695,13 +698,13 @@ describe('app', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts null dataSource', function(done) {
|
it('accepts null dataSource', function(done) {
|
||||||
app.model(MyTestModel, { dataSource: null });
|
app.model(MyTestModel, {dataSource: null});
|
||||||
expect(MyTestModel.dataSource).to.eql(null);
|
expect(MyTestModel.dataSource).to.eql(null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts false dataSource', function(done) {
|
it('accepts false dataSource', function(done) {
|
||||||
app.model(MyTestModel, { dataSource: false });
|
app.model(MyTestModel, {dataSource: false});
|
||||||
expect(MyTestModel.getDataSource()).to.eql(null);
|
expect(MyTestModel.getDataSource()).to.eql(null);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -720,7 +723,7 @@ describe('app', function() {
|
||||||
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');
|
var previousModel = loopback.registry.findModel('TestModel');
|
||||||
app.dataSource('db', { connector: 'memory' });
|
app.dataSource('db', {connector: 'memory'});
|
||||||
|
|
||||||
if (previousModel) {
|
if (previousModel) {
|
||||||
delete previousModel.dataSource;
|
delete previousModel.dataSource;
|
||||||
|
@ -728,16 +731,16 @@ describe('app', function() {
|
||||||
|
|
||||||
assert(!previousModel || !previousModel.dataSource);
|
assert(!previousModel || !previousModel.dataSource);
|
||||||
var TestModel = app.registry.createModel('TestModel');
|
var 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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
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');
|
var 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();
|
var anotherApp = loopback();
|
||||||
expect(anotherApp.models.Color).to.equal(undefined);
|
expect(anotherApp.models.Color).to.equal(undefined);
|
||||||
|
@ -746,7 +749,7 @@ describe('app', function() {
|
||||||
|
|
||||||
describe('app.dataSources', function() {
|
describe('app.dataSources', 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();
|
var anotherApp = loopback();
|
||||||
expect(anotherApp.datasources.ds).to.equal(undefined);
|
expect(anotherApp.datasources.ds).to.equal(undefined);
|
||||||
|
@ -756,7 +759,7 @@ describe('app', function() {
|
||||||
describe('app.dataSource', function() {
|
describe('app.dataSource', function() {
|
||||||
it('looks up the connector in `app.connectors`', function() {
|
it('looks up the connector in `app.connectors`', function() {
|
||||||
app.connector('custom', loopback.Memory);
|
app.connector('custom', loopback.Memory);
|
||||||
app.dataSource('custom', { connector: 'custom' });
|
app.dataSource('custom', {connector: 'custom'});
|
||||||
expect(app.dataSources.custom.name).to.equal(loopback.Memory.name);
|
expect(app.dataSources.custom.name).to.equal(loopback.Memory.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -766,12 +769,12 @@ describe('app', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(function() {
|
expect(function() {
|
||||||
app.dataSource('bad-ds', { connector: 'throwing' });
|
app.dataSource('bad-ds', {connector: 'throwing'});
|
||||||
}).to.throw(/bad-ds.*throwing/);
|
}).to.throw(/bad-ds.*throwing/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('adds app reference to the data source object', function() {
|
it('adds app reference to the data source object', function() {
|
||||||
app.dataSource('ds', { connector: 'memory' });
|
app.dataSource('ds', {connector: 'memory'});
|
||||||
expect(app.datasources.ds.app).to.not.equal(undefined);
|
expect(app.datasources.ds.app).to.not.equal(undefined);
|
||||||
expect(app.datasources.ds.app).to.equal(app);
|
expect(app.datasources.ds.app).to.equal(app);
|
||||||
});
|
});
|
||||||
|
@ -864,11 +867,11 @@ 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'];
|
var AUTH_MODELS = ['User', 'ACL', 'AccessToken', 'Role', 'RoleMapping'];
|
||||||
var app = loopback({ localRegistry: true, loadBuiltinModels: true });
|
var 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' });
|
var 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);
|
||||||
|
|
||||||
|
@ -880,12 +883,12 @@ describe('app', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
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 });
|
var app = loopback({localRegistry: true, loadBuiltinModels: true});
|
||||||
var db = app.dataSource('db', { connector: 'memory' });
|
var db = app.dataSource('db', {connector: 'memory'});
|
||||||
var Customer = app.registry.createModel('Customer', {}, { base: 'User' });
|
var Customer = app.registry.createModel('Customer', {}, {base: 'User'});
|
||||||
app.model(Customer, { dataSource: 'db' });
|
app.model(Customer, {dataSource: 'db'});
|
||||||
|
|
||||||
app.enableAuth({ dataSource: 'db' });
|
app.enableAuth({dataSource: 'db'});
|
||||||
|
|
||||||
expect(Object.keys(app.models)).to.not.include('User');
|
expect(Object.keys(app.models)).to.not.include('User');
|
||||||
});
|
});
|
||||||
|
@ -980,15 +983,15 @@ describe('app', function() {
|
||||||
var app, db;
|
var app, db;
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
app = loopback();
|
app = loopback();
|
||||||
db = loopback.createDataSource({ connector: loopback.Memory });
|
db = loopback.createDataSource({connector: loopback.Memory});
|
||||||
});
|
});
|
||||||
|
|
||||||
it.onServer('normalizes the http path', function(done) {
|
it.onServer('normalizes the http path', function(done) {
|
||||||
var UserAccount = PersistedModel.extend(
|
var UserAccount = PersistedModel.extend(
|
||||||
'UserAccount',
|
'UserAccount',
|
||||||
{ name: String },
|
{name: String},
|
||||||
{
|
{
|
||||||
remoting: { normalizeHttpPath: true },
|
remoting: {normalizeHttpPath: true},
|
||||||
});
|
});
|
||||||
app.model(UserAccount);
|
app.model(UserAccount);
|
||||||
UserAccount.attachTo(db);
|
UserAccount.attachTo(db);
|
||||||
|
|
|
@ -3,12 +3,16 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var expect = require('chai').expect;
|
||||||
|
var 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;
|
var test = this;
|
||||||
var app = loopback({ localRegistry: true });
|
var app = loopback({localRegistry: true});
|
||||||
var ds = app.dataSource('ds', { connector: 'memory' });
|
var ds = app.dataSource('ds', {connector: 'memory'});
|
||||||
var Score = app.registry.createModel('Score');
|
var Score = app.registry.createModel('Score');
|
||||||
this.Score = app.model(Score, {
|
this.Score = app.model(Score, {
|
||||||
dataSource: 'ds',
|
dataSource: 'ds',
|
||||||
|
@ -27,13 +31,13 @@ describe('PersistedModel.createChangeStream()', function() {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
Score.create({ team: 'foo' });
|
Score.create({team: 'foo'});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should detect update', function(done) {
|
it('should detect update', function(done) {
|
||||||
var Score = this.Score;
|
var 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) {
|
||||||
expect(change.type).to.equal('update');
|
expect(change.type).to.equal('update');
|
||||||
|
@ -50,7 +54,7 @@ describe('PersistedModel.createChangeStream()', function() {
|
||||||
|
|
||||||
it('should detect delete', function(done) {
|
it('should detect delete', function(done) {
|
||||||
var Score = this.Score;
|
var 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) {
|
||||||
expect(change.type).to.equal('remove');
|
expect(change.type).to.equal('remove');
|
||||||
|
@ -69,8 +73,8 @@ describe('PersistedModel.createChangeStream()', function() {
|
||||||
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;
|
var test = this;
|
||||||
var app = loopback({ localRegistry: true });
|
var app = loopback({localRegistry: true});
|
||||||
var db = app.dataSource('ds', { connector: 'memory' });
|
var db = app.dataSource('ds', {connector: 'memory'});
|
||||||
var ps = app.dataSource('ps', {
|
var ps = app.dataSource('ps', {
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
port: '12345',
|
port: '12345',
|
||||||
|
|
|
@ -3,8 +3,11 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var assert = require('assert');
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var expect = require('chai').expect;
|
var expect = require('chai').expect;
|
||||||
|
var loopback = require('../');
|
||||||
|
|
||||||
var Change, TestModel;
|
var Change, TestModel;
|
||||||
|
|
||||||
|
@ -15,7 +18,7 @@ describe('Change', function() {
|
||||||
});
|
});
|
||||||
TestModel = loopback.PersistedModel.extend('ChangeTestModel',
|
TestModel = loopback.PersistedModel.extend('ChangeTestModel',
|
||||||
{
|
{
|
||||||
id: { id: true, type: 'string', defaultFn: 'guid' },
|
id: {id: true, type: 'string', defaultFn: 'guid'},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
trackChanges: true,
|
trackChanges: true,
|
||||||
|
@ -475,20 +478,20 @@ describe('Change', function() {
|
||||||
describe('Change.diff(modelName, since, remoteChanges, callback)', function() {
|
describe('Change.diff(modelName, since, remoteChanges, callback)', function() {
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
Change.create([
|
Change.create([
|
||||||
{ rev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1 },
|
{rev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1},
|
||||||
{ rev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1 },
|
{rev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1},
|
||||||
{ rev: 'bat', modelName: this.modelName, modelId: 11, checkpoint: 1 },
|
{rev: 'bat', modelName: this.modelName, modelId: 11, checkpoint: 1},
|
||||||
], done);
|
], done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return delta and conflict lists', function(done) {
|
it('should return delta and conflict lists', function(done) {
|
||||||
var remoteChanges = [
|
var 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
|
||||||
{ rev: 'bar', prev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1 },
|
{rev: 'bar', prev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1},
|
||||||
// a conflict => should result in a conflict
|
// a conflict => should result in a conflict
|
||||||
{ rev: 'bat2', prev: 'bat0', modelName: this.modelName, modelId: 11, checkpoint: 1 },
|
{rev: 'bat2', prev: 'bat0', modelName: this.modelName, modelId: 11, checkpoint: 1},
|
||||||
];
|
];
|
||||||
|
|
||||||
Change.diff(this.modelName, 0, remoteChanges, function(err, diff) {
|
Change.diff(this.modelName, 0, remoteChanges, function(err, diff) {
|
||||||
|
@ -504,11 +507,11 @@ 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 = [
|
var 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
|
||||||
{ rev: 'bar', prev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1 },
|
{rev: 'bar', prev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1},
|
||||||
// a conflict => should result in a conflict
|
// a conflict => should result in a conflict
|
||||||
{ rev: 'bat2', prev: 'bat0', modelName: this.modelName, modelId: 11, checkpoint: 1 },
|
{rev: 'bat2', prev: 'bat0', modelName: this.modelName, modelId: 11, checkpoint: 1},
|
||||||
];
|
];
|
||||||
|
|
||||||
Change.diff(this.modelName, 0, remoteChanges)
|
Change.diff(this.modelName, 0, remoteChanges)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var loopback = require('../');
|
var loopback = require('../');
|
||||||
var expect = require('chai').expect;
|
var expect = require('chai').expect;
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var assert = require('assert');
|
||||||
|
var loopback = require('../');
|
||||||
|
|
||||||
describe('DataSource', function() {
|
describe('DataSource', function() {
|
||||||
var memory;
|
var memory;
|
||||||
|
|
||||||
|
@ -16,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 });
|
var 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');
|
||||||
|
@ -42,13 +46,13 @@ describe('DataSource', function() {
|
||||||
|
|
||||||
it('should honor settings.base', function() {
|
it('should honor settings.base', function() {
|
||||||
var Base = memory.createModel('base');
|
var Base = memory.createModel('base');
|
||||||
var Color = memory.createModel('color', { name: String }, { base: Base });
|
var 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 });
|
var 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);
|
||||||
});
|
});
|
||||||
|
@ -65,7 +69,7 @@ describe('DataSource', function() {
|
||||||
connector: new Connector(),
|
connector: new Connector(),
|
||||||
});
|
});
|
||||||
|
|
||||||
var Color = ds.createModel('color', { name: String });
|
var 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');
|
||||||
});
|
});
|
||||||
|
@ -116,3 +120,19 @@ describe('DataSource', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var assertValidDataSource = function(dataSource) {
|
||||||
|
// has methods
|
||||||
|
assert.isFunc(dataSource, 'createModel');
|
||||||
|
assert.isFunc(dataSource, 'discoverModelDefinitions');
|
||||||
|
assert.isFunc(dataSource, 'discoverSchema');
|
||||||
|
assert.isFunc(dataSource, 'enableRemote');
|
||||||
|
assert.isFunc(dataSource, 'disableRemote');
|
||||||
|
assert.isFunc(dataSource, 'defineOperation');
|
||||||
|
assert.isFunc(dataSource, 'operations');
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.isFunc = function(obj, name) {
|
||||||
|
assert(obj, 'cannot assert function ' + name + ' on object that doesnt exist');
|
||||||
|
assert(typeof obj[name] === 'function', name + ' is not a function');
|
||||||
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var loopback = require('../../');
|
var loopback = require('../../');
|
||||||
var models = require('../fixtures/e2e/models');
|
var models = require('../fixtures/e2e/models');
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var loopback = require('../../');
|
var loopback = require('../../');
|
||||||
var models = require('../fixtures/e2e/models');
|
var models = require('../fixtures/e2e/models');
|
||||||
|
@ -33,7 +34,7 @@ describe('Replication', function() {
|
||||||
LocalTestModel.replicate(0, TestModel, function() {
|
LocalTestModel.replicate(0, TestModel, function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
TestModel.findOne({ n: RANDOM }, function(err, found) {
|
TestModel.findOne({n: RANDOM}, function(err, found) {
|
||||||
assert.equal(created.id, found.id);
|
assert.equal(created.id, found.id);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../');
|
var loopback = require('../');
|
||||||
var MyEmail;
|
var MyEmail;
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
@ -10,37 +11,37 @@ var 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: [
|
var 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: [
|
var 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: [
|
var 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:
|
var connector = new MailConnector({transport:
|
||||||
{ type: 'smtp', service: 'gmail' },
|
{type: 'smtp', service: 'gmail'},
|
||||||
});
|
});
|
||||||
|
|
||||||
assert(connector.transportForName('smtp'));
|
assert(connector.transportForName('smtp'));
|
||||||
});
|
});
|
||||||
|
|
||||||
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:
|
var connector = new MailConnector({transport:
|
||||||
{ type: 'smtp', service: 'ses-us-east-1', alias: 'ses-smtp' },
|
{type: 'smtp', service: 'ses-us-east-1', alias: 'ses-smtp'},
|
||||||
});
|
});
|
||||||
|
|
||||||
assert(connector.transportForName('ses-smtp'));
|
assert(connector.transportForName('ses-smtp'));
|
||||||
|
@ -52,7 +53,7 @@ describe('Email and SMTP', function() {
|
||||||
MyEmail = loopback.Email.extend('my-email');
|
MyEmail = loopback.Email.extend('my-email');
|
||||||
var ds = loopback.createDataSource('email', {
|
var ds = loopback.createDataSource('email', {
|
||||||
connector: loopback.Mail,
|
connector: loopback.Mail,
|
||||||
transports: [{ type: 'STUB' }],
|
transports: [{type: 'STUB'}],
|
||||||
});
|
});
|
||||||
MyEmail.attachTo(ds);
|
MyEmail.attachTo(ds);
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../');
|
var loopback = require('../');
|
||||||
var app;
|
var app;
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../../../..');
|
var loopback = require('../../../..');
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var app = module.exports = loopback({
|
var app = module.exports = loopback({
|
||||||
|
@ -14,7 +15,7 @@ var errorHandler = require('strong-error-handler');
|
||||||
boot(app, __dirname);
|
boot(app, __dirname);
|
||||||
|
|
||||||
var apiPath = '/api';
|
var 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());
|
||||||
|
|
||||||
app.use(loopback.urlNotFound());
|
app.use(loopback.urlNotFound());
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../../../../index');
|
var loopback = require('../../../../index');
|
||||||
var PersistedModel = loopback.PersistedModel;
|
var PersistedModel = loopback.PersistedModel;
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../../../../index');
|
var loopback = require('../../../../index');
|
||||||
var app = module.exports = loopback({ localRegistry: true });
|
var app = module.exports = loopback({localRegistry: true});
|
||||||
var models = require('./models');
|
var models = require('./models');
|
||||||
var TestModel = models.TestModel;
|
var TestModel = models.TestModel;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(Todo) {
|
module.exports = function(Todo) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var loopback = require('../../../../../index');
|
var loopback = require('../../../../../index');
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(Todo) {
|
module.exports = function(Todo) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var loopback = require('../../../../../index');
|
var loopback = require('../../../../../index');
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(Todo) {
|
module.exports = function(Todo) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var loopback = require('../../../../../index');
|
var loopback = require('../../../../../index');
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(Todo) {
|
module.exports = function(Todo) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var loopback = require('../../../../../index');
|
var loopback = require('../../../../../index');
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(Todo) {
|
module.exports = function(Todo) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var loopback = require('../../../../../index');
|
var loopback = require('../../../../../index');
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(Todo) {
|
module.exports = function(Todo) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var loopback = require('../../../../../index');
|
var loopback = require('../../../../../index');
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(Todo) {
|
module.exports = function(Todo) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var loopback = require('../../../../../index');
|
var loopback = require('../../../../../index');
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(Todo) {
|
module.exports = function(Todo) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var loopback = require('../../../../../index');
|
var loopback = require('../../../../../index');
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(Todo) {
|
module.exports = function(Todo) {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var loopback = require('../../../../../index');
|
var loopback = require('../../../../../index');
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,5 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
process.loadedFooJS = true;
|
process.loadedFooJS = true;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(Bar) {
|
module.exports = function(Bar) {
|
||||||
process.loadedBarJS = true;
|
process.loadedBarJS = true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../../../../index');
|
var loopback = require('../../../../index');
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var app = module.exports = loopback({ localRegistry: true });
|
var app = module.exports = loopback({localRegistry: true});
|
||||||
var errorHandler = require('strong-error-handler');
|
var errorHandler = require('strong-error-handler');
|
||||||
|
|
||||||
boot(app, __dirname);
|
boot(app, __dirname);
|
||||||
|
|
|
@ -14,5 +14,6 @@
|
||||||
"principalType": "ROLE",
|
"principalType": "ROLE",
|
||||||
"principalId": "$owner"
|
"principalId": "$owner"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
}
|
"saltWorkFactor": 4
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../../../../index');
|
var loopback = require('../../../../index');
|
||||||
var boot = require('loopback-boot');
|
var boot = require('loopback-boot');
|
||||||
var app = module.exports = loopback({
|
var app = module.exports = loopback({
|
||||||
|
@ -13,7 +14,7 @@ var 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';
|
var apiPath = '/api';
|
||||||
app.use(apiPath, loopback.rest());
|
app.use(apiPath, loopback.rest());
|
||||||
app.use(loopback.urlNotFound());
|
app.use(loopback.urlNotFound());
|
||||||
|
|
|
@ -3,12 +3,17 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var assert = require('assert');
|
||||||
|
var loopback = require('../');
|
||||||
|
var 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 });
|
var here = new GeoPoint({lat: 10, lng: 10});
|
||||||
var there = new GeoPoint({ lat: 5, lng: 5 });
|
var there = new GeoPoint({lat: 5, lng: 5});
|
||||||
var distance = here.distanceTo(there, { type: 'meters' });
|
var distance = here.distanceTo(there, {type: 'meters'});
|
||||||
|
|
||||||
assert.equal(Math.floor(distance), 782777);
|
assert.equal(Math.floor(distance), 782777);
|
||||||
});
|
});
|
||||||
|
@ -16,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 });
|
var here = new GeoPoint({lat: 10, lng: 10});
|
||||||
var there = new GeoPoint({ lat: 5, lng: 5 });
|
var there = new GeoPoint({lat: 5, lng: 5});
|
||||||
var distance = GeoPoint.distanceBetween(here, there, { type: 'feet' });
|
var distance = GeoPoint.distanceBetween(here, there, {type: 'feet'});
|
||||||
|
|
||||||
assert.equal(Math.floor(distance), 2568169);
|
assert.equal(Math.floor(distance), 2568169);
|
||||||
});
|
});
|
||||||
|
@ -48,7 +53,7 @@ describe('GeoPoint', function() {
|
||||||
});
|
});
|
||||||
it('Create as Model property', function() {
|
it('Create as Model property', function() {
|
||||||
var Model = loopback.createModel('geo-model', {
|
var Model = loopback.createModel('geo-model', {
|
||||||
geo: { type: 'GeoPoint' },
|
geo: {type: 'GeoPoint'},
|
||||||
});
|
});
|
||||||
|
|
||||||
var m = new Model({
|
var m = new Model({
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var _describe = {};
|
var _describe = {};
|
||||||
var _it = {};
|
var _it = {};
|
||||||
var _beforeEach = {};
|
var _beforeEach = {};
|
||||||
|
@ -68,7 +69,7 @@ _beforeEach.givenModel = function(modelName, attrs, optionalHandler) {
|
||||||
var app = this.app;
|
var app = this.app;
|
||||||
var model = app.models[modelName];
|
var 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');
|
||||||
assert(model.dataSource, 'cannot test model ' + modelName +
|
assert(model.dataSource, 'cannot test model ' + modelName +
|
||||||
' without attached dataSource');
|
' without attached dataSource');
|
||||||
|
@ -135,7 +136,7 @@ _beforeEach.givenAnUnauthenticatedToken = function(attrs, optionalHandler) {
|
||||||
};
|
};
|
||||||
|
|
||||||
_beforeEach.givenAnAnonymousToken = function(attrs, optionalHandler) {
|
_beforeEach.givenAnAnonymousToken = function(attrs, optionalHandler) {
|
||||||
_beforeEach.givenModel('accessToken', { id: '$anonymous' }, optionalHandler);
|
_beforeEach.givenModel('accessToken', {id: '$anonymous'}, optionalHandler);
|
||||||
};
|
};
|
||||||
|
|
||||||
_describe.whenCalledRemotely = function(verb, url, data, cb) {
|
_describe.whenCalledRemotely = function(verb, url, data, cb) {
|
||||||
|
|
|
@ -3,14 +3,17 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var assert = require('assert');
|
||||||
var loopback = require('../');
|
var loopback = require('../');
|
||||||
|
var request = require('supertest');
|
||||||
|
|
||||||
describe('hidden properties', function() {
|
describe('hidden properties', function() {
|
||||||
beforeEach(function(done) {
|
beforeEach(function(done) {
|
||||||
var app = this.app = loopback();
|
var app = this.app = loopback();
|
||||||
var Product = this.Product = loopback.PersistedModel.extend('product',
|
var Product = this.Product = loopback.PersistedModel.extend('product',
|
||||||
{},
|
{},
|
||||||
{ hidden: ['secret'] }
|
{hidden: ['secret']}
|
||||||
);
|
);
|
||||||
Product.attachTo(loopback.memory());
|
Product.attachTo(loopback.memory());
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var expect = require('chai').expect;
|
||||||
|
var loopback = require('../');
|
||||||
var net = require('net');
|
var 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
|
||||||
|
@ -38,10 +42,10 @@ describe('loopback application', function() {
|
||||||
loopback.AccessToken.attachTo(db);
|
loopback.AccessToken.attachTo(db);
|
||||||
loopback.Role.attachTo(db);
|
loopback.Role.attachTo(db);
|
||||||
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');
|
var 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);
|
var body = new Buffer(0);
|
||||||
req.on('data', function(chunk) {
|
req.on('data', function(chunk) {
|
||||||
|
@ -57,15 +61,15 @@ describe('loopback application', function() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
loopback.remoteMethod(Streamer.read, {
|
loopback.remoteMethod(Streamer.read, {
|
||||||
http: { method: 'post' },
|
http: {method: 'post'},
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'req', type: 'Object', http: { source: 'req' }},
|
{arg: 'req', type: 'Object', http: {source: 'req'}},
|
||||||
{ arg: 'res', type: 'Object', http: { source: 'res' }},
|
{arg: 'res', type: 'Object', http: {source: 'res'}},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
app.enableAuth();
|
app.enableAuth();
|
||||||
app.use(loopback.token({ model: app.models.accessToken }));
|
app.use(loopback.token({model: app.models.accessToken}));
|
||||||
app.use(loopback.rest());
|
app.use(loopback.rest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
// Karma configuration
|
// Karma configuration
|
||||||
// http://karma-runner.github.io/0.12/config/configuration-file.html
|
// http://karma-runner.github.io/0.12/config/configuration-file.html
|
||||||
|
|
||||||
|
'use strict';
|
||||||
module.exports = function(config) {
|
module.exports = function(config) {
|
||||||
config.set({
|
config.set({
|
||||||
// enable / disable watching file and executing tests whenever any file changes
|
// enable / disable watching file and executing tests whenever any file changes
|
||||||
|
@ -111,6 +112,6 @@ module.exports = function(config) {
|
||||||
},
|
},
|
||||||
|
|
||||||
// Add browserify to preprocessors
|
// Add browserify to preprocessors
|
||||||
preprocessors: { 'test/*': ['browserify'] },
|
preprocessors: {'test/*': ['browserify']},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
'use strict';
|
||||||
var expect = require('chai').expect;
|
var expect = require('chai').expect;
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
var loopback = require('..');
|
var loopback = require('..');
|
||||||
var supertest = require('supertest');
|
var supertest = require('supertest');
|
||||||
|
|
||||||
var AN_OBJECT_VALUE = { name: 'an-object' };
|
var AN_OBJECT_VALUE = {name: 'an-object'};
|
||||||
|
|
||||||
describe('KeyValueModel', function() {
|
describe('KeyValueModel', function() {
|
||||||
var request, app, CacheItem;
|
var request, app, CacheItem;
|
||||||
|
@ -61,7 +62,7 @@ describe('KeyValueModel', function() {
|
||||||
CacheItem.set('expire-key', AN_OBJECT_VALUE, function(err) {
|
CacheItem.set('expire-key', AN_OBJECT_VALUE, function(err) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
request.put('/CacheItems/expire-key/expire')
|
request.put('/CacheItems/expire-key/expire')
|
||||||
.send({ ttl: 10 })
|
.send({ttl: 10})
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
|
@ -77,7 +78,7 @@ describe('KeyValueModel', function() {
|
||||||
|
|
||||||
it('returns 404 when expiring a key that does not exist', function(done) {
|
it('returns 404 when expiring a key that does not exist', function(done) {
|
||||||
request.put('/CacheItems/key-does-not-exist/expire')
|
request.put('/CacheItems/key-does-not-exist/expire')
|
||||||
.send({ ttl: 10 })
|
.send({ttl: 10})
|
||||||
.expect(404, done);
|
.expect(404, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -138,7 +139,7 @@ describe('KeyValueModel', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupAppAndCacheItem() {
|
function setupAppAndCacheItem() {
|
||||||
app = loopback({ localRegistry: true, loadBuiltinModels: true });
|
app = loopback({localRegistry: true, loadBuiltinModels: true});
|
||||||
app.use(loopback.rest());
|
app.use(loopback.rest());
|
||||||
|
|
||||||
CacheItem = app.registry.createModel({
|
CacheItem = app.registry.createModel({
|
||||||
|
@ -146,8 +147,8 @@ describe('KeyValueModel', function() {
|
||||||
base: 'KeyValueModel',
|
base: 'KeyValueModel',
|
||||||
});
|
});
|
||||||
|
|
||||||
app.dataSource('kv', { connector: 'kv-memory' });
|
app.dataSource('kv', {connector: 'kv-memory'});
|
||||||
app.model(CacheItem, { dataSource: 'kv' });
|
app.model(CacheItem, {dataSource: 'kv'});
|
||||||
}
|
}
|
||||||
|
|
||||||
var _server, _requestHandler; // eslint-disable-line one-var
|
var _server, _requestHandler; // eslint-disable-line one-var
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var it = require('./util/it');
|
var it = require('./util/it');
|
||||||
var describe = require('./util/describe');
|
var describe = require('./util/describe');
|
||||||
var Domain = require('domain');
|
var Domain = require('domain');
|
||||||
|
@ -61,8 +62,6 @@ describe('loopback', function() {
|
||||||
'User',
|
'User',
|
||||||
'ValidationError',
|
'ValidationError',
|
||||||
'application',
|
'application',
|
||||||
'arguments',
|
|
||||||
'caller',
|
|
||||||
'configureModel',
|
'configureModel',
|
||||||
'context',
|
'context',
|
||||||
'createContext',
|
'createContext',
|
||||||
|
@ -106,17 +105,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 });
|
var 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 });
|
var 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 });
|
var 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');
|
||||||
});
|
});
|
||||||
|
@ -150,7 +149,7 @@ describe('loopback', function() {
|
||||||
|
|
||||||
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 });
|
var Product = loopback.createModel('product', {price: Number});
|
||||||
|
|
||||||
Product.stats = function(fn) {
|
Product.stats = function(fn) {
|
||||||
// ...
|
// ...
|
||||||
|
@ -159,8 +158,8 @@ describe('loopback', function() {
|
||||||
loopback.remoteMethod(
|
loopback.remoteMethod(
|
||||||
Product.stats,
|
Product.stats,
|
||||||
{
|
{
|
||||||
returns: { arg: 'stats', type: 'array' },
|
returns: {arg: 'stats', type: 'array'},
|
||||||
http: { path: '/info', verb: 'get' },
|
http: {path: '/info', verb: 'get'},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -187,7 +186,7 @@ describe('loopback', function() {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
assert(MyCustomModel.super_ === MyModel);
|
assert(MyCustomModel.super_ === MyModel);
|
||||||
assert.deepEqual(MyCustomModel.settings.foo, { bar: 'bat', bat: 'baz' });
|
assert.deepEqual(MyCustomModel.settings.foo, {bar: 'bat', bat: 'baz'});
|
||||||
assert(MyCustomModel.super_.modelName === MyModel.modelName);
|
assert(MyCustomModel.super_.modelName === MyModel.modelName);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -237,11 +236,11 @@ describe('loopback', function() {
|
||||||
methods: {
|
methods: {
|
||||||
staticMethod: {
|
staticMethod: {
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
http: { path: '/static' },
|
http: {path: '/static'},
|
||||||
},
|
},
|
||||||
instanceMethod: {
|
instanceMethod: {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
http: { path: '/instance' },
|
http: {path: '/instance'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -331,7 +330,7 @@ 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 });
|
var db = loopback.createDataSource({connector: loopback.Memory});
|
||||||
var model = loopback.Model.extend(uniqueModelName);
|
var 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
|
||||||
|
@ -471,11 +470,11 @@ describe('loopback', function() {
|
||||||
methods: {
|
methods: {
|
||||||
staticMethod: {
|
staticMethod: {
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
http: { path: '/static' },
|
http: {path: '/static'},
|
||||||
},
|
},
|
||||||
instanceMethod: {
|
instanceMethod: {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
http: { path: '/instance' },
|
http: {path: '/instance'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -535,7 +534,7 @@ describe('loopback', function() {
|
||||||
dataSource: null,
|
dataSource: null,
|
||||||
methods: {
|
methods: {
|
||||||
staticMethod: {
|
staticMethod: {
|
||||||
http: { path: '/static' },
|
http: {path: '/static'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -551,7 +550,7 @@ describe('loopback', function() {
|
||||||
dataSource: null,
|
dataSource: null,
|
||||||
methods: {
|
methods: {
|
||||||
'prototype.instanceMethod': {
|
'prototype.instanceMethod': {
|
||||||
http: { path: '/instance' },
|
http: {path: '/instance'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -569,7 +568,7 @@ describe('loopback', function() {
|
||||||
methods: {
|
methods: {
|
||||||
'prototype.instanceMethod': {
|
'prototype.instanceMethod': {
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
http: { path: '/instance' },
|
http: {path: '/instance'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -584,7 +583,7 @@ describe('loopback', function() {
|
||||||
methods: {
|
methods: {
|
||||||
staticMethod: {
|
staticMethod: {
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
http: { path: '/static' },
|
http: {path: '/static'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -601,7 +600,7 @@ describe('loopback', function() {
|
||||||
methods: {
|
methods: {
|
||||||
'prototype.instanceMethod': {
|
'prototype.instanceMethod': {
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
http: { path: '/instance' },
|
http: {path: '/instance'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -621,7 +620,7 @@ describe('loopback', function() {
|
||||||
var Base = app.registry.createModel('Base', {}, {
|
var Base = app.registry.createModel('Base', {}, {
|
||||||
methods: {
|
methods: {
|
||||||
greet: {
|
greet: {
|
||||||
http: { path: '/greet' },
|
http: {path: '/greet'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -630,7 +629,7 @@ describe('loopback', function() {
|
||||||
base: 'Base',
|
base: 'Base',
|
||||||
methods: {
|
methods: {
|
||||||
hello: {
|
hello: {
|
||||||
http: { path: '/hello' },
|
http: {path: '/hello'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -644,7 +643,7 @@ describe('loopback', function() {
|
||||||
var Base = app.registry.createModel('Base', {}, {
|
var Base = app.registry.createModel('Base', {}, {
|
||||||
methods: {
|
methods: {
|
||||||
greet: {
|
greet: {
|
||||||
http: { path: '/greet' },
|
http: {path: '/greet'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -653,7 +652,7 @@ describe('loopback', function() {
|
||||||
base: 'Base',
|
base: 'Base',
|
||||||
methods: {
|
methods: {
|
||||||
greet: {
|
greet: {
|
||||||
http: { path: '/hello' },
|
http: {path: '/hello'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -662,13 +661,13 @@ describe('loopback', function() {
|
||||||
var customMethod = MyCustomModel.sharedClass.findMethodByName('greet');
|
var customMethod = MyCustomModel.sharedClass.findMethodByName('greet');
|
||||||
|
|
||||||
// Base Method
|
// Base Method
|
||||||
expect(baseMethod.http).to.eql({ path: '/greet' });
|
expect(baseMethod.http).to.eql({path: '/greet'});
|
||||||
expect(baseMethod.http.path).to.equal('/greet');
|
expect(baseMethod.http.path).to.equal('/greet');
|
||||||
expect(baseMethod.http.path).to.not.equal('/hello');
|
expect(baseMethod.http.path).to.not.equal('/hello');
|
||||||
|
|
||||||
// Custom Method
|
// Custom Method
|
||||||
expect(methodNames).to.include('greet');
|
expect(methodNames).to.include('greet');
|
||||||
expect(customMethod.http).to.eql({ path: '/hello' });
|
expect(customMethod.http).to.eql({path: '/hello'});
|
||||||
expect(customMethod.http.path).to.equal('/hello');
|
expect(customMethod.http.path).to.equal('/hello');
|
||||||
expect(customMethod.http.path).to.not.equal('/greet');
|
expect(customMethod.http.path).to.not.equal('/greet');
|
||||||
});
|
});
|
||||||
|
@ -679,7 +678,7 @@ describe('loopback', function() {
|
||||||
dataSource: null,
|
dataSource: null,
|
||||||
methods: {
|
methods: {
|
||||||
greet: {
|
greet: {
|
||||||
http: { path: '/greet' },
|
http: {path: '/greet'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -688,7 +687,7 @@ describe('loopback', function() {
|
||||||
base: 'Base',
|
base: 'Base',
|
||||||
methods: {
|
methods: {
|
||||||
hello: {
|
hello: {
|
||||||
http: { path: '/hello' },
|
http: {path: '/hello'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -709,7 +708,7 @@ describe('loopback', function() {
|
||||||
dataSource: null,
|
dataSource: null,
|
||||||
methods: {
|
methods: {
|
||||||
greet: {
|
greet: {
|
||||||
http: { path: '/greet' },
|
http: {path: '/greet'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -718,7 +717,7 @@ describe('loopback', function() {
|
||||||
dataSource: null,
|
dataSource: null,
|
||||||
methods: {
|
methods: {
|
||||||
hello: {
|
hello: {
|
||||||
http: { path: '/hello' },
|
http: {path: '/hello'},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -731,7 +730,7 @@ describe('loopback', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupLoopback() {
|
function setupLoopback() {
|
||||||
app = loopback({ localRegistry: true });
|
app = loopback({localRegistry: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAllMethodNamesWithoutClassName(Model) {
|
function getAllMethodNamesWithoutClassName(Model) {
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var assert = require('assert');
|
||||||
|
var 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
|
||||||
|
@ -25,9 +29,9 @@ describe('Memory Connector', function() {
|
||||||
var Product = memory.createModel('product', properties);
|
var Product = memory.createModel('product', properties);
|
||||||
|
|
||||||
Product.create([
|
Product.create([
|
||||||
{ name: 'apple', price: 0.79 },
|
{name: 'apple', price: 0.79},
|
||||||
{ name: 'pear', price: 1.29 },
|
{name: 'pear', price: 1.29},
|
||||||
{ name: 'orange', price: 0.59 },
|
{name: 'orange', price: 0.59},
|
||||||
], count);
|
], count);
|
||||||
|
|
||||||
function count() {
|
function count() {
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
--require ./test/support.js
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require(('../'));
|
var loopback = require(('../'));
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var Application = loopback.Application;
|
var Application = loopback.Application;
|
||||||
|
@ -16,7 +17,7 @@ describe('Application', function() {
|
||||||
|
|
||||||
it('honors `application.register` - promise variant', function(done) {
|
it('honors `application.register` - promise 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;
|
var app = result;
|
||||||
assert.equal(app.owner, 'rfeng');
|
assert.equal(app.owner, 'rfeng');
|
||||||
assert.equal(app.name, 'MyTestApp');
|
assert.equal(app.name, 'MyTestApp');
|
||||||
|
@ -28,7 +29,7 @@ describe('Application', function() {
|
||||||
|
|
||||||
it('honors `application.register` - promise variant', function(done) {
|
it('honors `application.register` - promise variant', function(done) {
|
||||||
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;
|
var app = result;
|
||||||
assert.equal(app.owner, 'rfeng');
|
assert.equal(app.owner, 'rfeng');
|
||||||
|
@ -43,9 +44,9 @@ describe('Application', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Create a new application', function(done) {
|
it('Create a new application', function(done) {
|
||||||
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;
|
var app = result;
|
||||||
assert.equal(app.owner, 'rfeng');
|
assert.equal(app.owner, 'rfeng');
|
||||||
assert.equal(app.name, 'MyApp1');
|
assert.equal(app.name, 'MyApp1');
|
||||||
|
@ -64,7 +65,7 @@ describe('Application', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Create a new application with push settings', function(done) {
|
it('Create a new application with push settings', function(done) {
|
||||||
Application.create({ owner: 'rfeng',
|
Application.create({owner: 'rfeng',
|
||||||
name: 'MyAppWithPush',
|
name: 'MyAppWithPush',
|
||||||
description: 'My push mobile application',
|
description: 'My push mobile application',
|
||||||
pushSettings: {
|
pushSettings: {
|
||||||
|
@ -116,7 +117,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;
|
var app = result;
|
||||||
assert.equal(app.owner, 'rfeng');
|
assert.equal(app.owner, 'rfeng');
|
||||||
assert.equal(app.name, 'MyApp2');
|
assert.equal(app.name, 'MyApp2');
|
||||||
|
@ -306,10 +307,10 @@ 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');
|
var MyApp = Application.extend('MyApp');
|
||||||
var ds = loopback.createDataSource({ connector: loopback.Memory });
|
var 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;
|
var app = result;
|
||||||
assert.equal(app.owner, 'rfeng');
|
assert.equal(app.owner, 'rfeng');
|
||||||
assert.equal(app.name, 'MyApp123');
|
assert.equal(app.name, 'MyApp123');
|
||||||
|
|
|
@ -3,6 +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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var assert = require('assert');
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var chai = require('chai');
|
var chai = require('chai');
|
||||||
var describe = require('./util/describe');
|
var describe = require('./util/describe');
|
||||||
|
@ -11,6 +13,9 @@ var ACL = loopback.ACL;
|
||||||
var defineModelTestsWithDataSource = require('./util/model-tests');
|
var defineModelTestsWithDataSource = require('./util/model-tests');
|
||||||
var PersistedModel = loopback.PersistedModel;
|
var PersistedModel = loopback.PersistedModel;
|
||||||
var sinonChai = require('sinon-chai');
|
var sinonChai = require('sinon-chai');
|
||||||
|
var Promise = require('bluebird');
|
||||||
|
var TaskEmitter = require('strong-task-emitter');
|
||||||
|
var request = require('supertest');
|
||||||
|
|
||||||
var expect = chai.expect;
|
var expect = chai.expect;
|
||||||
chai.use(sinonChai);
|
chai.use(sinonChai);
|
||||||
|
@ -40,10 +45,10 @@ describe('Model / PersistedModel', function() {
|
||||||
|
|
||||||
User.attachTo(dataSource);
|
User.attachTo(dataSource);
|
||||||
|
|
||||||
User.validatesUniquenessOf('email', { message: 'email is not unique' });
|
User.validatesUniquenessOf('email', {message: 'email is not unique'});
|
||||||
|
|
||||||
var joe = new User({ email: 'joe@joe.com' });
|
var joe = new User({email: 'joe@joe.com'});
|
||||||
var joe2 = new User({ email: 'joe@joe.com' });
|
var joe2 = new User({email: 'joe@joe.com'});
|
||||||
|
|
||||||
joe.save(function() {
|
joe.save(function() {
|
||||||
joe2.save(function(err) {
|
joe2.save(function(err) {
|
||||||
|
@ -58,7 +63,7 @@ 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 });
|
var MyModel = loopback.createModel('my-model', {name: String});
|
||||||
var dataSource = loopback.createDataSource({
|
var dataSource = loopback.createDataSource({
|
||||||
connector: loopback.Memory,
|
connector: loopback.Memory,
|
||||||
});
|
});
|
||||||
|
@ -77,11 +82,11 @@ describe.onServer('Remote Methods', function() {
|
||||||
var User, Post, dataSource, app;
|
var User, Post, dataSource, app;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
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}});
|
||||||
|
|
||||||
User = app.registry.createModel('user', {
|
User = app.registry.createModel('user', {
|
||||||
id: { id: true, type: String, defaultFn: 'guid' },
|
id: {id: true, type: String, defaultFn: 'guid'},
|
||||||
'first': String,
|
'first': String,
|
||||||
'last': String,
|
'last': String,
|
||||||
'age': Number,
|
'age': Number,
|
||||||
|
@ -94,17 +99,17 @@ describe.onServer('Remote Methods', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
Post = app.registry.createModel('post', {
|
Post = app.registry.createModel('post', {
|
||||||
id: { id: true, type: String, defaultFn: 'guid' },
|
id: {id: true, type: String, defaultFn: 'guid'},
|
||||||
title: String,
|
title: String,
|
||||||
content: String,
|
content: String,
|
||||||
}, {
|
}, {
|
||||||
trackChanges: true,
|
trackChanges: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
dataSource = app.dataSource('db', { connector: 'memory' });
|
dataSource = app.dataSource('db', {connector: 'memory'});
|
||||||
|
|
||||||
app.model(User, { dataSource: 'db' });
|
app.model(User, {dataSource: 'db'});
|
||||||
app.model(Post, { dataSource: 'db' });
|
app.model(Post, {dataSource: 'db'});
|
||||||
|
|
||||||
User.hasMany(Post);
|
User.hasMany(Post);
|
||||||
|
|
||||||
|
@ -118,11 +123,11 @@ describe.onServer('Remote Methods', function() {
|
||||||
|
|
||||||
User.remoteMethod('login', {
|
User.remoteMethod('login', {
|
||||||
accepts: [
|
accepts: [
|
||||||
{ arg: 'username', type: 'string', required: true },
|
{arg: 'username', type: 'string', required: true},
|
||||||
{ arg: 'password', type: 'string', required: true },
|
{arg: 'password', type: 'string', required: true},
|
||||||
],
|
],
|
||||||
returns: { arg: 'sessionId', type: 'any', root: true },
|
returns: {arg: 'sessionId', type: 'any', root: true},
|
||||||
http: { path: '/sign-in', verb: 'get' },
|
http: {path: '/sign-in', verb: 'get'},
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(loopback.rest());
|
app.use(loopback.rest());
|
||||||
|
@ -130,7 +135,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' };
|
var anObject = {first: 'June'};
|
||||||
request(app)
|
request(app)
|
||||||
.post('/users')
|
.post('/users')
|
||||||
// sends an object
|
// sends an object
|
||||||
|
@ -148,7 +153,7 @@ describe.onServer('Remote Methods', function() {
|
||||||
// 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 = [
|
var arrayOfObjects = [
|
||||||
{ first: 'John' }, { first: 'Jane' },
|
{first: 'John'}, {first: 'Jane'},
|
||||||
];
|
];
|
||||||
request(app)
|
request(app)
|
||||||
.post('/users')
|
.post('/users')
|
||||||
|
@ -169,11 +174,11 @@ describe.onServer('Remote Methods', function() {
|
||||||
describe('Model.destroyAll(callback)', function() {
|
describe('Model.destroyAll(callback)', function() {
|
||||||
it('Delete all Model instances from data source', function(done) {
|
it('Delete all Model instances from data source', function(done) {
|
||||||
(new TaskEmitter())
|
(new TaskEmitter())
|
||||||
.task(User, 'create', { first: 'jill' })
|
.task(User, 'create', {first: 'jill'})
|
||||||
.task(User, 'create', { first: 'bob' })
|
.task(User, 'create', {first: 'bob'})
|
||||||
.task(User, 'create', { first: 'jan' })
|
.task(User, 'create', {first: 'jan'})
|
||||||
.task(User, 'create', { first: 'sam' })
|
.task(User, 'create', {first: 'sam'})
|
||||||
.task(User, 'create', { first: 'suzy' })
|
.task(User, 'create', {first: 'suzy'})
|
||||||
.on('done', function() {
|
.on('done', function() {
|
||||||
User.count(function(err, count) {
|
User.count(function(err, count) {
|
||||||
User.destroyAll(function() {
|
User.destroyAll(function() {
|
||||||
|
@ -192,10 +197,10 @@ describe.onServer('Remote Methods', 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();
|
var 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;
|
var id = user.id;
|
||||||
User.findById(id, function(err, user) {
|
User.findById(id, function(err, user) {
|
||||||
|
@ -210,9 +215,9 @@ 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();
|
var 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;
|
var id = user.id;
|
||||||
User.findById(id, function(err, user) {
|
User.findById(id, function(err, user) {
|
||||||
|
@ -258,7 +263,7 @@ describe.onServer('Remote Methods', function() {
|
||||||
it('Call the findById with filter.fields using HTTP / REST', function(done) {
|
it('Call the findById with filter.fields using HTTP / REST', function(done) {
|
||||||
request(app)
|
request(app)
|
||||||
.post('/users')
|
.post('/users')
|
||||||
.send({ first: 'x', last: 'y' })
|
.send({first: 'x', last: 'y'})
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
|
@ -284,7 +289,7 @@ describe.onServer('Remote Methods', function() {
|
||||||
it('Call the findById with filter.include using HTTP / REST', function(done) {
|
it('Call the findById with filter.include using HTTP / REST', function(done) {
|
||||||
request(app)
|
request(app)
|
||||||
.post('/users')
|
.post('/users')
|
||||||
.send({ first: 'x', last: 'y' })
|
.send({first: 'x', last: 'y'})
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
|
@ -294,7 +299,7 @@ describe.onServer('Remote Methods', function() {
|
||||||
assert(userId);
|
assert(userId);
|
||||||
request(app)
|
request(app)
|
||||||
.post('/users/' + userId + '/posts')
|
.post('/users/' + userId + '/posts')
|
||||||
.send({ title: 'T1', content: 'C1' })
|
.send({title: 'T1', content: 'C1'})
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
|
@ -332,7 +337,7 @@ describe.onServer('Remote Methods', function() {
|
||||||
// invoke save
|
// invoke save
|
||||||
request(app)
|
request(app)
|
||||||
.post('/users')
|
.post('/users')
|
||||||
.send({ data: { first: 'foo', last: 'bar' }})
|
.send({data: {first: 'foo', last: 'bar'}})
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
|
@ -360,7 +365,7 @@ describe.onServer('Remote Methods', function() {
|
||||||
// invoke save
|
// invoke save
|
||||||
request(app)
|
request(app)
|
||||||
.post('/users')
|
.post('/users')
|
||||||
.send({ data: { first: 'foo', last: 'bar' }})
|
.send({data: {first: 'foo', last: 'bar'}})
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
|
@ -392,7 +397,7 @@ describe.onServer('Remote Methods', function() {
|
||||||
// invoke save
|
// invoke save
|
||||||
request(app)
|
request(app)
|
||||||
.post('/users')
|
.post('/users')
|
||||||
.send({ data: { first: 'foo', last: 'bar' }})
|
.send({data: {first: 'foo', last: 'bar'}})
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
|
@ -447,7 +452,7 @@ describe.onServer('Remote Methods', function() {
|
||||||
// invoke save
|
// invoke save
|
||||||
request(app)
|
request(app)
|
||||||
.post('/users')
|
.post('/users')
|
||||||
.send({ data: { first: 'foo', last: 'bar' }})
|
.send({data: {first: 'foo', last: 'bar'}})
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
|
@ -479,7 +484,7 @@ describe.onServer('Remote Methods', function() {
|
||||||
// invoke save
|
// invoke save
|
||||||
request(app)
|
request(app)
|
||||||
.post('/users')
|
.post('/users')
|
||||||
.send({ data: { first: 'foo', last: 'bar' }})
|
.send({data: {first: 'foo', last: 'bar'}})
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.end(function(err, res) {
|
.end(function(err, res) {
|
||||||
|
@ -495,20 +500,20 @@ 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 });
|
var Book = dataSource.createModel('book', {title: String, author: String});
|
||||||
var Chapter = dataSource.createModel('chapter', { title: String });
|
var 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' });
|
var 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) {
|
||||||
assert.equal(count, 2);
|
assert.equal(count, 2);
|
||||||
book.chapters({ where: { title: 'Chapter 1' }}, function(err, chapters) {
|
book.chapters({where: {title: 'Chapter 1'}}, function(err, chapters) {
|
||||||
assert.equal(chapters.length, 1);
|
assert.equal(chapters.length, 1);
|
||||||
assert.equal(chapters[0].title, 'Chapter 1');
|
assert.equal(chapters[0].title, 'Chapter 1');
|
||||||
|
|
||||||
|
@ -525,8 +530,8 @@ describe.onServer('Remote Methods', function() {
|
||||||
it('Normalized properties passed in originally by loopback.createModel()', function() {
|
it('Normalized properties passed in originally by loopback.createModel()', function() {
|
||||||
var props = {
|
var 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},
|
||||||
d: Date,
|
d: Date,
|
||||||
g: loopback.GeoPoint,
|
g: loopback.GeoPoint,
|
||||||
};
|
};
|
||||||
|
@ -635,7 +640,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 };
|
var remoteMethod = {name: methodName};
|
||||||
assert.equal(
|
assert.equal(
|
||||||
User._getAccessTypeForMethod(remoteMethod),
|
User._getAccessTypeForMethod(remoteMethod),
|
||||||
expectedAccessType
|
expectedAccessType
|
||||||
|
@ -712,8 +717,8 @@ describe.onServer('Remote Methods', function() {
|
||||||
it('includes all aliases', function() {
|
it('includes all aliases', function() {
|
||||||
var app = loopback();
|
var app = loopback();
|
||||||
var model = PersistedModel.extend('PersistedModelForAliases');
|
var 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')
|
var metadata = app.handler('rest')
|
||||||
|
@ -760,8 +765,8 @@ describe.onServer('Remote Methods', function() {
|
||||||
it('emits a `remoteMethodDisabled` event', function() {
|
it('emits a `remoteMethodDisabled` event', function() {
|
||||||
var app = loopback();
|
var app = loopback();
|
||||||
var model = PersistedModel.extend('TestModelForDisablingRemoteMethod');
|
var 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();
|
var callbackSpy = require('sinon').spy();
|
||||||
var TestModel = app.models.TestModelForDisablingRemoteMethod;
|
var TestModel = app.models.TestModelForDisablingRemoteMethod;
|
||||||
|
@ -774,8 +779,8 @@ describe.onServer('Remote Methods', function() {
|
||||||
it('emits a `remoteMethodDisabled` event from disableRemoteMethodByName', function() {
|
it('emits a `remoteMethodDisabled` event from disableRemoteMethodByName', function() {
|
||||||
var app = loopback();
|
var app = loopback();
|
||||||
var model = PersistedModel.extend('TestModelForDisablingRemoteMethod');
|
var 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();
|
var callbackSpy = require('sinon').spy();
|
||||||
var TestModel = app.models.TestModelForDisablingRemoteMethod;
|
var TestModel = app.models.TestModelForDisablingRemoteMethod;
|
||||||
|
@ -791,11 +796,11 @@ describe.onServer('Remote Methods', function() {
|
||||||
beforeEach(function setup() {
|
beforeEach(function setup() {
|
||||||
app = loopback();
|
app = loopback();
|
||||||
TestModel = loopback.createModel('TestModelForGetApp'); // unique name
|
TestModel = loopback.createModel('TestModelForGetApp'); // unique name
|
||||||
app.dataSource('db', { connector: 'memory' });
|
app.dataSource('db', {connector: 'memory'});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls the callback when already attached', function(done) {
|
it('calls the callback when already attached', function(done) {
|
||||||
app.model(TestModel, { dataSource: 'db' });
|
app.model(TestModel, {dataSource: 'db'});
|
||||||
TestModel.getApp(function(err, a) {
|
TestModel.getApp(function(err, a) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
|
@ -814,7 +819,7 @@ describe.onServer('Remote Methods', function() {
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
app.model(TestModel, { dataSource: 'db' });
|
app.model(TestModel, {dataSource: 'db'});
|
||||||
// fails on time-out when not implemented correctly
|
// fails on time-out when not implemented correctly
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,12 +3,17 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
var assert = require('assert');
|
||||||
|
var expect = require('chai').expect;
|
||||||
|
var 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();
|
var app = loopback();
|
||||||
var props = {};
|
var props = {};
|
||||||
var opts = { base: 'nonexistent' };
|
var 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`/);
|
||||||
});
|
});
|
||||||
|
@ -20,32 +25,32 @@ describe('Registry', function() {
|
||||||
var appBar = loopback();
|
var appBar = loopback();
|
||||||
var modelName = 'MyModel';
|
var modelName = 'MyModel';
|
||||||
var subModelName = 'Sub' + modelName;
|
var subModelName = 'Sub' + modelName;
|
||||||
var settings = { base: 'PersistedModel' };
|
var 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' });
|
var dsFoo = appFoo.dataSource('dsFoo', {connector: 'memory'});
|
||||||
var dsBar = appFoo.dataSource('dsBar', { connector: 'memory' });
|
var dsBar = appFoo.dataSource('dsBar', {connector: 'memory'});
|
||||||
|
|
||||||
var FooModel = appFoo.registry.createModel(modelName, {}, settings);
|
var FooModel = appFoo.registry.createModel(modelName, {}, settings);
|
||||||
appFoo.model(FooModel, { dataSource: dsFoo });
|
appFoo.model(FooModel, {dataSource: dsFoo});
|
||||||
|
|
||||||
var FooSubModel = appFoo.registry.createModel(subModelName, {}, settings);
|
var FooSubModel = appFoo.registry.createModel(subModelName, {}, settings);
|
||||||
appFoo.model(FooSubModel, { dataSource: dsFoo });
|
appFoo.model(FooSubModel, {dataSource: dsFoo});
|
||||||
|
|
||||||
var BarModel = appBar.registry.createModel(modelName, {}, settings);
|
var BarModel = appBar.registry.createModel(modelName, {}, settings);
|
||||||
appBar.model(BarModel, { dataSource: dsBar });
|
appBar.model(BarModel, {dataSource: dsBar});
|
||||||
|
|
||||||
var BarSubModel = appBar.registry.createModel(subModelName, {}, settings);
|
var BarSubModel = appBar.registry.createModel(subModelName, {}, settings);
|
||||||
appBar.model(BarSubModel, { dataSource: dsBar });
|
appBar.model(BarSubModel, {dataSource: dsBar});
|
||||||
|
|
||||||
FooModel.hasMany(FooSubModel);
|
FooModel.hasMany(FooSubModel);
|
||||||
BarModel.hasMany(BarSubModel);
|
BarModel.hasMany(BarSubModel);
|
||||||
|
|
||||||
expect(appFoo.models[modelName]).to.not.equal(appBar.models[modelName]);
|
expect(appFoo.models[modelName]).to.not.equal(appBar.models[modelName]);
|
||||||
|
|
||||||
BarModel.create({ name: 'bar' }, function(err, bar) {
|
BarModel.create({name: 'bar'}, function(err, bar) {
|
||||||
assert(!err);
|
assert(!err);
|
||||||
bar.subMyModels.create({ parent: 'bar' }, function(err) {
|
bar.subMyModels.create({parent: 'bar'}, function(err) {
|
||||||
assert(!err);
|
assert(!err);
|
||||||
FooSubModel.find(function(err, foos) {
|
FooSubModel.find(function(err, foos) {
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// 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
|
||||||
|
|
||||||
|
'use strict';
|
||||||
var loopback = require('../');
|
var loopback = require('../');
|
||||||
var lt = require('./helpers/loopback-testing-helper');
|
var lt = require('./helpers/loopback-testing-helper');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
@ -31,22 +32,22 @@ describe('relations - integration', function() {
|
||||||
|
|
||||||
describe('polymorphicHasMany', function() {
|
describe('polymorphicHasMany', function() {
|
||||||
before(function defineProductAndCategoryModels() {
|
before(function defineProductAndCategoryModels() {
|
||||||
var Team = app.registry.createModel('Team', { name: 'string' });
|
var Team = app.registry.createModel('Team', {name: 'string'});
|
||||||
var Reader = app.registry.createModel('Reader', { name: 'string' });
|
var Reader = app.registry.createModel('Reader', {name: 'string'});
|
||||||
var Picture = app.registry.createModel('Picture',
|
var 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'});
|
||||||
app.model(Reader, { dataSource: 'db' });
|
app.model(Reader, {dataSource: 'db'});
|
||||||
app.model(Picture, { dataSource: 'db' });
|
app.model(Picture, {dataSource: 'db'});
|
||||||
|
|
||||||
Reader.hasMany(Picture, { polymorphic: { // alternative syntax
|
Reader.hasMany(Picture, {polymorphic: { // alternative syntax
|
||||||
as: 'imageable', // if not set, default to: reference
|
as: 'imageable', // if not set, default to: reference
|
||||||
foreignKey: 'imageableId', // defaults to 'as + Id'
|
foreignKey: 'imageableId', // defaults to 'as + Id'
|
||||||
discriminator: 'imageableType', // defaults to 'as + Type'
|
discriminator: 'imageableType', // defaults to 'as + Type'
|
||||||
}});
|
}});
|
||||||
|
|
||||||
Picture.belongsTo('imageable', { polymorphic: {
|
Picture.belongsTo('imageable', {polymorphic: {
|
||||||
foreignKey: 'imageableId',
|
foreignKey: 'imageableId',
|
||||||
discriminator: 'imageableType',
|
discriminator: 'imageableType',
|
||||||
}});
|
}});
|
||||||
|
@ -56,18 +57,18 @@ describe('relations - integration', function() {
|
||||||
|
|
||||||
before(function createEvent(done) {
|
before(function createEvent(done) {
|
||||||
var test = this;
|
var 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);
|
||||||
|
|
||||||
test.team = team;
|
test.team = team;
|
||||||
app.models.Reader.create({ name: 'Reader 1' },
|
app.models.Reader.create({name: 'Reader 1'},
|
||||||
function(err, reader) {
|
function(err, reader) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
test.reader = reader;
|
test.reader = reader;
|
||||||
reader.pictures.create({ name: 'Picture 1' });
|
reader.pictures.create({name: 'Picture 1'});
|
||||||
reader.pictures.create({ name: 'Picture 2' });
|
reader.pictures.create({name: 'Picture 2'});
|
||||||
reader.team(test.team);
|
reader.team(test.team);
|
||||||
reader.save(done);
|
reader.save(done);
|
||||||
});
|
});
|
||||||
|
@ -82,14 +83,14 @@ 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;
|
var 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) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body.name).to.be.equal('Reader 1');
|
expect(res.body.name).to.be.equal('Reader 1');
|
||||||
expect(res.body.pictures).to.be.eql([
|
expect(res.body.pictures).to.be.eql([
|
||||||
{ name: 'Picture 1', id: 1, imageableId: 1, imageableType: 'Reader' },
|
{name: 'Picture 1', id: 1, imageableId: 1, imageableType: 'Reader'},
|
||||||
{ name: 'Picture 2', id: 2, imageableId: 1, imageableType: 'Reader' },
|
{name: 'Picture 2', id: 2, imageableId: 1, imageableType: 'Reader'},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -99,13 +100,13 @@ describe('relations - integration', function() {
|
||||||
it('includes the related parent model', function(done) {
|
it('includes the related parent model', function(done) {
|
||||||
var url = '/api/pictures';
|
var 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) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body[0].name).to.be.equal('Picture 1');
|
expect(res.body[0].name).to.be.equal('Picture 1');
|
||||||
expect(res.body[1].name).to.be.equal('Picture 2');
|
expect(res.body[1].name).to.be.equal('Picture 2');
|
||||||
expect(res.body[0].imageable).to.be.eql({ name: 'Reader 1', id: 1, teamId: 1 });
|
expect(res.body[0].imageable).to.be.eql({name: 'Reader 1', id: 1, teamId: 1});
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -114,9 +115,9 @@ 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';
|
var url = '/api/pictures';
|
||||||
this.get(url)
|
this.get(url)
|
||||||
.query({ 'filter': { 'include': {
|
.query({'filter': {'include': {
|
||||||
'relation': 'imageable',
|
'relation': 'imageable',
|
||||||
'scope': { 'include': 'team' },
|
'scope': {'include': 'team'},
|
||||||
}}})
|
}}})
|
||||||
.expect(200, function(err, res) {
|
.expect(200, function(err, res) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
@ -124,7 +125,7 @@ describe('relations - integration', function() {
|
||||||
expect(res.body[0].name).to.be.equal('Picture 1');
|
expect(res.body[0].name).to.be.equal('Picture 1');
|
||||||
expect(res.body[1].name).to.be.equal('Picture 2');
|
expect(res.body[1].name).to.be.equal('Picture 2');
|
||||||
expect(res.body[0].imageable.name).to.be.eql('Reader 1');
|
expect(res.body[0].imageable.name).to.be.eql('Reader 1');
|
||||||
expect(res.body[0].imageable.team).to.be.eql({ name: 'Team 1', id: 1 });
|
expect(res.body[0].imageable.team).to.be.eql({name: 'Team 1', id: 1});
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -239,7 +240,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;
|
var self = this;
|
||||||
self.request.put(self.url)
|
self.request.put(self.url)
|
||||||
.send({ active: true })
|
.send({active: true})
|
||||||
.end(function(err) {
|
.end(function(err) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
app.models.Widget.findById(self.widget.id, function(err, w) {
|
app.models.Widget.findById(self.widget.id, function(err, w) {
|
||||||
|
@ -453,7 +454,7 @@ describe('relations - integration', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
var NOW = Date.now();
|
var NOW = Date.now();
|
||||||
var data = { date: new Date(NOW) };
|
var 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() {
|
||||||
|
@ -661,14 +662,14 @@ describe('relations - integration', function() {
|
||||||
|
|
||||||
var product = app.registry.createModel(
|
var product = app.registry.createModel(
|
||||||
'product',
|
'product',
|
||||||
{ id: 'string', name: 'string' }
|
{id: 'string', name: 'string'}
|
||||||
);
|
);
|
||||||
var category = app.registry.createModel(
|
var category = app.registry.createModel(
|
||||||
'category',
|
'category',
|
||||||
{ id: 'string', name: 'string' }
|
{id: 'string', name: 'string'}
|
||||||
);
|
);
|
||||||
app.model(product, { dataSource: 'db' });
|
app.model(product, {dataSource: 'db'});
|
||||||
app.model(category, { dataSource: 'db' });
|
app.model(category, {dataSource: 'db'});
|
||||||
|
|
||||||
product.hasAndBelongsToMany(category);
|
product.hasAndBelongsToMany(category);
|
||||||
category.hasAndBelongsToMany(product);
|
category.hasAndBelongsToMany(product);
|
||||||
|
@ -690,11 +691,11 @@ describe('relations - integration', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(function createAnotherCategoryAndProduct(done) {
|
beforeEach(function createAnotherCategoryAndProduct(done) {
|
||||||
app.models.category.create({ name: 'another-category' },
|
app.models.category.create({name: 'another-category'},
|
||||||
function(err, cat) {
|
function(err, cat) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
cat.products.create({ name: 'another-product' }, done);
|
cat.products.create({name: 'another-product'}, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -784,23 +785,23 @@ describe('relations - integration', function() {
|
||||||
describe('embedsOne', function() {
|
describe('embedsOne', function() {
|
||||||
before(function defineGroupAndPosterModels() {
|
before(function defineGroupAndPosterModels() {
|
||||||
var group = app.registry.createModel('group',
|
var group = app.registry.createModel('group',
|
||||||
{ name: 'string' },
|
{name: 'string'},
|
||||||
{ plural: 'groups' }
|
{plural: 'groups'}
|
||||||
);
|
);
|
||||||
app.model(group, { dataSource: 'db' });
|
app.model(group, {dataSource: 'db'});
|
||||||
|
|
||||||
var poster = app.registry.createModel(
|
var poster = app.registry.createModel(
|
||||||
'poster',
|
'poster',
|
||||||
{ url: 'string' }
|
{url: 'string'}
|
||||||
);
|
);
|
||||||
app.model(poster, { dataSource: 'db' });
|
app.model(poster, {dataSource: 'db'});
|
||||||
|
|
||||||
group.embedsOne(poster, { as: 'cover' });
|
group.embedsOne(poster, {as: 'cover'});
|
||||||
});
|
});
|
||||||
|
|
||||||
before(function createImage(done) {
|
before(function createImage(done) {
|
||||||
var test = this;
|
var 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);
|
||||||
|
|
||||||
|
@ -818,10 +819,10 @@ describe('relations - integration', function() {
|
||||||
var url = '/api/groups/' + this.group.id + '/cover';
|
var url = '/api/groups/' + this.group.id + '/cover';
|
||||||
|
|
||||||
this.post(url)
|
this.post(url)
|
||||||
.send({ url: 'http://image.url' })
|
.send({url: 'http://image.url'})
|
||||||
.expect(200, function(err, res) {
|
.expect(200, function(err, res) {
|
||||||
expect(res.body).to.be.eql(
|
expect(res.body).to.be.eql(
|
||||||
{ url: 'http://image.url' }
|
{url: 'http://image.url'}
|
||||||
);
|
);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -837,7 +838,7 @@ describe('relations - integration', function() {
|
||||||
|
|
||||||
expect(res.body.name).to.be.equal('Group 1');
|
expect(res.body.name).to.be.equal('Group 1');
|
||||||
expect(res.body.poster).to.be.eql(
|
expect(res.body.poster).to.be.eql(
|
||||||
{ url: 'http://image.url' }
|
{url: 'http://image.url'}
|
||||||
);
|
);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -852,7 +853,7 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql(
|
expect(res.body).to.be.eql(
|
||||||
{ url: 'http://image.url' }
|
{url: 'http://image.url'}
|
||||||
);
|
);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -863,7 +864,7 @@ describe('relations - integration', function() {
|
||||||
var url = '/api/groups/' + this.group.id + '/cover';
|
var url = '/api/groups/' + this.group.id + '/cover';
|
||||||
|
|
||||||
this.put(url)
|
this.put(url)
|
||||||
.send({ url: 'http://changed.url' })
|
.send({url: 'http://changed.url'})
|
||||||
.expect(200, function(err, res) {
|
.expect(200, function(err, res) {
|
||||||
expect(res.body.url).to.be.equal('http://changed.url');
|
expect(res.body.url).to.be.equal('http://changed.url');
|
||||||
|
|
||||||
|
@ -879,7 +880,7 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql(
|
expect(res.body).to.be.eql(
|
||||||
{ url: 'http://changed.url' }
|
{url: 'http://changed.url'}
|
||||||
);
|
);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -901,29 +902,29 @@ describe('relations - integration', function() {
|
||||||
before(function defineProductAndCategoryModels() {
|
before(function defineProductAndCategoryModels() {
|
||||||
var todoList = app.registry.createModel(
|
var 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(
|
var todoItem = app.registry.createModel(
|
||||||
'todoItem',
|
'todoItem',
|
||||||
{ content: 'string' }, { forceId: false }
|
{content: 'string'}, {forceId: false}
|
||||||
);
|
);
|
||||||
app.model(todoItem, { dataSource: 'db' });
|
app.model(todoItem, {dataSource: 'db'});
|
||||||
|
|
||||||
todoList.embedsMany(todoItem, { as: 'items' });
|
todoList.embedsMany(todoItem, {as: 'items'});
|
||||||
});
|
});
|
||||||
|
|
||||||
before(function createTodoList(done) {
|
before(function createTodoList(done) {
|
||||||
var test = this;
|
var 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);
|
||||||
|
|
||||||
test.todoList = list;
|
test.todoList = list;
|
||||||
list.items.build({ content: 'Todo 1' });
|
list.items.build({content: 'Todo 1'});
|
||||||
list.items.build({ content: 'Todo 2' });
|
list.items.build({content: 'Todo 2'});
|
||||||
list.save(done);
|
list.save(done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -941,8 +942,8 @@ describe('relations - integration', function() {
|
||||||
|
|
||||||
expect(res.body.name).to.be.equal('List A');
|
expect(res.body.name).to.be.equal('List A');
|
||||||
expect(res.body.todoItems).to.be.eql([
|
expect(res.body.todoItems).to.be.eql([
|
||||||
{ content: 'Todo 1', id: 1 },
|
{content: 'Todo 1', id: 1},
|
||||||
{ content: 'Todo 2', id: 2 },
|
{content: 'Todo 2', id: 2},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -957,8 +958,8 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ content: 'Todo 1', id: 1 },
|
{content: 'Todo 1', id: 1},
|
||||||
{ content: 'Todo 2', id: 2 },
|
{content: 'Todo 2', id: 2},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -974,7 +975,7 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ content: 'Todo 2', id: 2 },
|
{content: 'Todo 2', id: 2},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -984,10 +985,10 @@ 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';
|
var url = '/api/todo-lists/' + this.todoList.id + '/items';
|
||||||
|
|
||||||
var expected = { content: 'Todo 3', id: 3 };
|
var expected = {content: 'Todo 3', id: 3};
|
||||||
|
|
||||||
this.post(url)
|
this.post(url)
|
||||||
.send({ content: 'Todo 3' })
|
.send({content: 'Todo 3'})
|
||||||
.expect(200, function(err, res) {
|
.expect(200, function(err, res) {
|
||||||
expect(res.body).to.be.eql(expected);
|
expect(res.body).to.be.eql(expected);
|
||||||
|
|
||||||
|
@ -1003,9 +1004,9 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ content: 'Todo 1', id: 1 },
|
{content: 'Todo 1', id: 1},
|
||||||
{ content: 'Todo 2', id: 2 },
|
{content: 'Todo 2', id: 2},
|
||||||
{ content: 'Todo 3', id: 3 },
|
{content: 'Todo 3', id: 3},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1020,7 +1021,7 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql(
|
expect(res.body).to.be.eql(
|
||||||
{ content: 'Todo 3', id: 3 }
|
{content: 'Todo 3', id: 3}
|
||||||
);
|
);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1045,8 +1046,8 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ content: 'Todo 1', id: 1 },
|
{content: 'Todo 1', id: 1},
|
||||||
{ content: 'Todo 3', id: 3 },
|
{content: 'Todo 3', id: 3},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1089,48 +1090,48 @@ describe('relations - integration', function() {
|
||||||
before(function defineProductAndCategoryModels() {
|
before(function defineProductAndCategoryModels() {
|
||||||
var recipe = app.registry.createModel(
|
var 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(
|
var 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(
|
var photo = app.registry.createModel(
|
||||||
'photo',
|
'photo',
|
||||||
{ name: 'string' }
|
{name: 'string'}
|
||||||
);
|
);
|
||||||
app.model(photo, { dataSource: 'db' });
|
app.model(photo, {dataSource: 'db'});
|
||||||
|
|
||||||
recipe.referencesMany(ingredient);
|
recipe.referencesMany(ingredient);
|
||||||
// contrived example for test:
|
// contrived example for test:
|
||||||
recipe.hasOne(photo, { as: 'picture', options: {
|
recipe.hasOne(photo, {as: 'picture', options: {
|
||||||
http: { path: 'image' },
|
http: {path: 'image'},
|
||||||
}});
|
}});
|
||||||
});
|
});
|
||||||
|
|
||||||
before(function createRecipe(done) {
|
before(function createRecipe(done) {
|
||||||
var test = this;
|
var 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);
|
||||||
|
|
||||||
test.recipe = recipe;
|
test.recipe = recipe;
|
||||||
recipe.ingredients.create({
|
recipe.ingredients.create({
|
||||||
name: 'Chocolate' },
|
name: 'Chocolate'},
|
||||||
function(err, ing) {
|
function(err, ing) {
|
||||||
test.ingredient1 = ing.id;
|
test.ingredient1 = ing.id;
|
||||||
recipe.picture.create({ name: 'Photo 1' }, done);
|
recipe.picture.create({name: 'Photo 1'}, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
before(function createIngredient(done) {
|
before(function createIngredient(done) {
|
||||||
var test = this;
|
var 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;
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1166,7 +1167,7 @@ describe('relations - integration', function() {
|
||||||
var test = this;
|
var test = this;
|
||||||
|
|
||||||
this.post(url)
|
this.post(url)
|
||||||
.send({ name: 'Butter' })
|
.send({name: 'Butter'})
|
||||||
.expect(200, function(err, res) {
|
.expect(200, function(err, res) {
|
||||||
expect(res.body.name).to.be.eql('Butter');
|
expect(res.body.name).to.be.eql('Butter');
|
||||||
test.ingredient3 = res.body.id;
|
test.ingredient3 = res.body.id;
|
||||||
|
@ -1184,9 +1185,9 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ name: 'Chocolate', id: test.ingredient1 },
|
{name: 'Chocolate', id: test.ingredient1},
|
||||||
{ name: 'Sugar', id: test.ingredient2 },
|
{name: 'Sugar', id: test.ingredient2},
|
||||||
{ name: 'Butter', id: test.ingredient3 },
|
{name: 'Butter', id: test.ingredient3},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1202,8 +1203,8 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ name: 'Chocolate', id: test.ingredient1 },
|
{name: 'Chocolate', id: test.ingredient1},
|
||||||
{ name: 'Butter', id: test.ingredient3 },
|
{name: 'Butter', id: test.ingredient3},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1220,7 +1221,7 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ name: 'Butter', id: test.ingredient3 },
|
{name: 'Butter', id: test.ingredient3},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1240,8 +1241,8 @@ describe('relations - integration', function() {
|
||||||
test.ingredient1, test.ingredient3,
|
test.ingredient1, test.ingredient3,
|
||||||
]);
|
]);
|
||||||
expect(res.body.ingredients).to.eql([
|
expect(res.body.ingredients).to.eql([
|
||||||
{ name: 'Chocolate', id: test.ingredient1 },
|
{name: 'Chocolate', id: test.ingredient1},
|
||||||
{ name: 'Butter', id: test.ingredient3 },
|
{name: 'Butter', id: test.ingredient3},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1258,7 +1259,7 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql(
|
expect(res.body).to.be.eql(
|
||||||
{ name: 'Butter', id: test.ingredient3 }
|
{name: 'Butter', id: test.ingredient3}
|
||||||
);
|
);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1302,8 +1303,8 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ name: 'Chocolate', id: test.ingredient1 },
|
{name: 'Chocolate', id: test.ingredient1},
|
||||||
{ name: 'Sugar', id: test.ingredient2 },
|
{name: 'Sugar', id: test.ingredient2},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1319,7 +1320,7 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ name: 'Chocolate', id: test.ingredient1 },
|
{name: 'Chocolate', id: test.ingredient1},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1334,7 +1335,7 @@ describe('relations - integration', function() {
|
||||||
this.put(url)
|
this.put(url)
|
||||||
.expect(200, function(err, res) {
|
.expect(200, function(err, res) {
|
||||||
expect(res.body).to.be.eql(
|
expect(res.body).to.be.eql(
|
||||||
{ name: 'Sugar', id: test.ingredient2 }
|
{name: 'Sugar', id: test.ingredient2}
|
||||||
);
|
);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1350,8 +1351,8 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ name: 'Chocolate', id: test.ingredient1 },
|
{name: 'Chocolate', id: test.ingredient1},
|
||||||
{ name: 'Sugar', id: test.ingredient2 },
|
{name: 'Sugar', id: test.ingredient2},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1378,7 +1379,7 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ name: 'Sugar', id: test.ingredient2 },
|
{name: 'Sugar', id: test.ingredient2},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1394,8 +1395,8 @@ describe('relations - integration', function() {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
expect(res.body).to.be.eql([
|
expect(res.body).to.be.eql([
|
||||||
{ name: 'Chocolate', id: test.ingredient1 },
|
{name: 'Chocolate', id: test.ingredient1},
|
||||||
{ name: 'Sugar', id: test.ingredient2 },
|
{name: 'Sugar', id: test.ingredient2},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1441,38 +1442,38 @@ describe('relations - integration', function() {
|
||||||
before(function defineModels() {
|
before(function defineModels() {
|
||||||
var Book = app.registry.createModel(
|
var 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(
|
var 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(
|
var 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(
|
var 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(
|
var Chapter = app.registry.createModel(
|
||||||
'Chapter',
|
'Chapter',
|
||||||
{ name: 'string' },
|
{name: 'string'},
|
||||||
{ plural: 'chapters' }
|
{plural: 'chapters'}
|
||||||
);
|
);
|
||||||
app.model(Chapter, { dataSource: 'db' });
|
app.model(Chapter, {dataSource: 'db'});
|
||||||
|
|
||||||
Book.hasMany(Page);
|
Book.hasMany(Page);
|
||||||
Book.hasMany(Chapter);
|
Book.hasMany(Chapter);
|
||||||
|
@ -1485,7 +1486,7 @@ describe('relations - integration', function() {
|
||||||
throw new Error('This should not crash the app');
|
throw new Error('This should not crash the app');
|
||||||
};
|
};
|
||||||
|
|
||||||
Page.remoteMethod('__throw__errors', { isStatic: false, http: { path: '/throws', verb: 'get' }});
|
Page.remoteMethod('__throw__errors', {isStatic: false, http: {path: '/throws', verb: 'get'}});
|
||||||
|
|
||||||
Book.nestRemoting('pages');
|
Book.nestRemoting('pages');
|
||||||
Book.nestRemoting('chapters');
|
Book.nestRemoting('chapters');
|
||||||
|
@ -1509,17 +1510,17 @@ describe('relations - integration', function() {
|
||||||
|
|
||||||
before(function createBook(done) {
|
before(function createBook(done) {
|
||||||
var test = this;
|
var 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);
|
||||||
|
|
||||||
test.book = book;
|
test.book = book;
|
||||||
book.pages.create({ name: 'Page 1' },
|
book.pages.create({name: 'Page 1'},
|
||||||
function(err, page) {
|
function(err, page) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
test.page = page;
|
test.page = page;
|
||||||
page.notes.create({ text: 'Page Note 1' },
|
page.notes.create({text: 'Page Note 1'},
|
||||||
function(err, note) {
|
function(err, note) {
|
||||||
test.note = note;
|
test.note = note;
|
||||||
|
|
||||||
|
@ -1531,12 +1532,12 @@ describe('relations - integration', function() {
|
||||||
|
|
||||||
before(function createChapters(done) {
|
before(function createChapters(done) {
|
||||||
var test = this;
|
var 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);
|
||||||
|
|
||||||
test.chapter = chapter;
|
test.chapter = chapter;
|
||||||
chapter.notes.create({ text: 'Chapter Note 1' }, function(err, note) {
|
chapter.notes.create({text: 'Chapter Note 1'}, function(err, note) {
|
||||||
test.cnote = note;
|
test.cnote = note;
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
@ -1546,7 +1547,7 @@ describe('relations - integration', function() {
|
||||||
|
|
||||||
before(function createCover(done) {
|
before(function createCover(done) {
|
||||||
var test = this;
|
var 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);
|
||||||
|
|
||||||
|
@ -1705,7 +1706,7 @@ describe('relations - integration', function() {
|
||||||
|
|
||||||
before(function createCustomer(done) {
|
before(function createCustomer(done) {
|
||||||
var test = this;
|
var 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);
|
||||||
|
|
||||||
cust = c;
|
cust = c;
|
||||||
|
@ -1727,7 +1728,7 @@ describe('relations - integration', function() {
|
||||||
var url = '/api/customers/' + cust.id + '/profile';
|
var url = '/api/customers/' + cust.id + '/profile';
|
||||||
|
|
||||||
this.post(url)
|
this.post(url)
|
||||||
.send({ points: 10 })
|
.send({points: 10})
|
||||||
.expect(200, function(err, res) {
|
.expect(200, function(err, res) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
|
@ -1754,7 +1755,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';
|
var 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) {
|
||||||
done(err);
|
done(err);
|
||||||
});
|
});
|
||||||
|
@ -1763,7 +1764,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';
|
var 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) {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue