Merge branch 'release/2.4.1' into production
This commit is contained in:
commit
6079792072
|
@ -1,65 +1,24 @@
|
|||
|
||||
### Contributing ###
|
||||
|
||||
Thank you for your interest in `loopback`, an open source project
|
||||
administered by StrongLoop.
|
||||
|
||||
Contributing to loopback is easy. In a few simple steps:
|
||||
Contributing to `loopback` is easy. In a few simple steps:
|
||||
|
||||
* Ensure that your effort is aligned with the project’s roadmap by
|
||||
* Ensure that your effort is aligned with the project's roadmap by
|
||||
talking to the maintainers, especially if you are going to spend a
|
||||
lot of time on it. This project is currently maintained by
|
||||
[@ritch](https://github.com/ritch), [@raymondfeng](https://github.com/raymondfeng),
|
||||
and [@bajtos](https://github.com/bajtos). The preferred channel of communication
|
||||
is [LoopBack Forum](https://groups.google.com/forum/#!forum/loopbackjs) or
|
||||
[Github Issues](https://github.com/strongloop/loopback/issues).
|
||||
lot of time on it.
|
||||
|
||||
* Make something better or fix a bug.
|
||||
|
||||
* Adhere to code style outlined in the
|
||||
* Adhere to code style outlined in the [Google C++ Style Guide][] and
|
||||
[Google Javascript Style Guide][].
|
||||
|
||||
* [Sign your patches](#signing-patches) to indicate that your are
|
||||
making your contribution available under the terms of the
|
||||
[Contributor License Agreement](#contributor-license-agreement).
|
||||
* Sign the [Contributor License Agreement](https://cla.strongloop.com/strongloop/loopback)
|
||||
|
||||
* Submit a pull request through Github.
|
||||
|
||||
|
||||
### Signing patches ###
|
||||
|
||||
Like many open source projects, we need a contributor license agreement
|
||||
from you before we can merge in your changes.
|
||||
|
||||
In summary, by submitting your code, you are granting us a right to use
|
||||
that code under the terms of this Agreement, including providing it to
|
||||
others. You are also certifying that you wrote it, and that you are
|
||||
allowed to license it to us. You are not giving up your copyright in
|
||||
your work. The license does not change your rights to use your own
|
||||
contributions for any other purpose.
|
||||
|
||||
Contributor License Agreements are important because they define the
|
||||
chain of ownership of a piece of software. Some companies won't allow
|
||||
the use of free software without clear agreements around code ownership.
|
||||
That's why many open source projects collect similar agreements from
|
||||
contributors. The CLA here is based on the Apache CLA.
|
||||
|
||||
To signify your agreement to these terms, add the following line to the
|
||||
bottom of your commit message. Use your real name and an actual e-mail
|
||||
address.
|
||||
|
||||
```
|
||||
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||
```
|
||||
|
||||
Alternatively you can use the git command line to automatically add this
|
||||
line, as follows:
|
||||
|
||||
```
|
||||
$ git commit -sm "Replace rainbows by unicorns"
|
||||
```
|
||||
|
||||
|
||||
### Contributor License Agreement ###
|
||||
|
||||
```
|
||||
|
@ -188,7 +147,5 @@ $ git commit -sm "Replace rainbows by unicorns"
|
|||
inaccurate in any respect. Email us at callback@strongloop.com.
|
||||
```
|
||||
|
||||
|
||||
[Google C++ Style Guide]: https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
|
||||
[Google Javascript Style Guide]: https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
|
||||
[license]: LICENSE
|
||||
|
||||
|
|
2
index.js
2
index.js
|
@ -12,7 +12,7 @@ var datasourceJuggler = require('loopback-datasource-juggler');
|
|||
loopback.Connector = require('./lib/connectors/base-connector');
|
||||
loopback.Memory = require('./lib/connectors/memory');
|
||||
loopback.Mail = require('./lib/connectors/mail');
|
||||
loopback.Remote = require('./lib/connectors/remote');
|
||||
loopback.Remote = require('loopback-connector-remote');
|
||||
|
||||
/**
|
||||
* Types
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
/**
|
||||
* Dependencies.
|
||||
*/
|
||||
|
||||
var assert = require('assert');
|
||||
var remoting = require('strong-remoting');
|
||||
var DataAccessObject = require('loopback-datasource-juggler/lib/dao');
|
||||
|
||||
/**
|
||||
* Export the RemoteConnector class.
|
||||
*/
|
||||
|
||||
module.exports = RemoteConnector;
|
||||
|
||||
/**
|
||||
* Create an instance of the connector with the given `settings`.
|
||||
*/
|
||||
|
||||
function RemoteConnector(settings) {
|
||||
assert(typeof settings === 'object', 'cannot initiaze RemoteConnector without a settings object');
|
||||
this.client = settings.client;
|
||||
this.adapter = settings.adapter || 'rest';
|
||||
this.protocol = settings.protocol || 'http'
|
||||
this.root = settings.root || '';
|
||||
this.host = settings.host || 'localhost';
|
||||
this.port = settings.port || 3000;
|
||||
this.remotes = remoting.create();
|
||||
|
||||
// TODO(ritch) make sure this name works with Model.getSourceId()
|
||||
this.name = 'remote-connector';
|
||||
|
||||
if(settings.url) {
|
||||
this.url = settings.url;
|
||||
} else {
|
||||
this.url = this.protocol + '://' + this.host + ':' + this.port + this.root;
|
||||
}
|
||||
|
||||
// handle mixins in the define() method
|
||||
var DAO = this.DataAccessObject = function() {};
|
||||
}
|
||||
|
||||
RemoteConnector.prototype.connect = function() {
|
||||
this.remotes.connect(this.url, this.adapter);
|
||||
}
|
||||
|
||||
RemoteConnector.initialize = function(dataSource, callback) {
|
||||
var connector = dataSource.connector = new RemoteConnector(dataSource.settings);
|
||||
connector.connect();
|
||||
callback();
|
||||
}
|
||||
|
||||
RemoteConnector.prototype.define = function(definition) {
|
||||
var Model = definition.model;
|
||||
var remotes = this.remotes;
|
||||
var SharedClass;
|
||||
|
||||
assert(Model.sharedClass, 'cannot attach ' + Model.modelName
|
||||
+ ' to a remote connector without a Model.sharedClass');
|
||||
|
||||
remotes.addClass(Model.sharedClass);
|
||||
|
||||
Model
|
||||
.sharedClass
|
||||
.methods()
|
||||
.forEach(function(remoteMethod) {
|
||||
// TODO(ritch) more elegant way of ignoring a nested shared class
|
||||
if(remoteMethod.name !== 'Change'
|
||||
&& remoteMethod.name !== 'Checkpoint') {
|
||||
createProxyMethod(Model, remotes, remoteMethod);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createProxyMethod(Model, remotes, remoteMethod) {
|
||||
var scope = remoteMethod.isStatic ? Model : Model.prototype;
|
||||
var original = scope[remoteMethod.name];
|
||||
|
||||
scope[remoteMethod.name] = function remoteMethodProxy() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var lastArgIsFunc = typeof args[args.length - 1] === 'function';
|
||||
var callback;
|
||||
if(lastArgIsFunc) {
|
||||
callback = args.pop();
|
||||
}
|
||||
|
||||
remotes.invoke(remoteMethod.stringName, args, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function noop() {}
|
|
@ -58,29 +58,9 @@ var Role = role.Role;
|
|||
var ACLSchema = {
|
||||
model: String, // The name of the model
|
||||
property: String, // The name of the property, method, scope, or relation
|
||||
|
||||
/**
|
||||
* Name of the access type - READ/WRITE/EXECUTE
|
||||
* @property accessType {String} Name of the access type - READ/WRITE/EXECUTE
|
||||
*/
|
||||
accessType: String,
|
||||
|
||||
/**
|
||||
* ALARM - Generate an alarm, in a system dependent way, the access specified
|
||||
* in the permissions component of the ACL entry.
|
||||
* ALLOW - Explicitly grants access to the resource.
|
||||
* AUDIT - Log, in a system dependent way, the access specified in the
|
||||
* permissions component of the ACL entry.
|
||||
* DENY - Explicitly denies access to the resource.
|
||||
*/
|
||||
permission: String,
|
||||
/**
|
||||
* Type of the principal - Application/User/Role
|
||||
*/
|
||||
principalType: String,
|
||||
/**
|
||||
* Id of the principal - such as appId, userId or roleId
|
||||
*/
|
||||
principalId: String
|
||||
};
|
||||
|
||||
|
@ -88,6 +68,16 @@ var ACLSchema = {
|
|||
* A Model for access control meta data.
|
||||
*
|
||||
* @header ACL
|
||||
* @property {String} model Name of the model.
|
||||
* @property {String} property Name of the property, method, scope, or relation.
|
||||
* @property {String} accessType Type of access being granted: one of READ, WRITE, or EXECUTE.
|
||||
* @property {String} permission Type of permission granted. One of:
|
||||
* - ALARM: Generate an alarm, in a system-dependent way, the access specified in the permissions component of the ACL entry.
|
||||
* - ALLOW: Explicitly grants access to the resource.
|
||||
* - AUDIT: Log, in a system-dependent way, the access specified in the permissions component of the ACL entry.
|
||||
* - DENY: Explicitly denies access to the resource.
|
||||
* @property {String} principalType Type of the principal; one of: Application, Use, Role.
|
||||
* @property {String} principalId ID of the principal - such as appId, userId or roleId
|
||||
* @class
|
||||
* @inherits Model
|
||||
*/
|
||||
|
|
|
@ -109,6 +109,33 @@ function generateKey(hmacKey, algorithm, encoding) {
|
|||
|
||||
/**
|
||||
* Manage client applications and organize their users.
|
||||
*
|
||||
* @property {String} id Generated ID.
|
||||
* @property {String} name Name; required.
|
||||
* @property {String} description Text description
|
||||
* @property {String} icon String Icon image URL.
|
||||
* @property {String} owner User ID of the developer who registers the application.
|
||||
* @property {String} email E-mail address
|
||||
* @property {Boolean} emailVerified Whether the e-mail is verified.
|
||||
* @property {String} url OAuth 2.0 application URL.
|
||||
* @property {String}[] callbackUrls The OAuth 2.0 code/token callback URL.
|
||||
* @property {String} status Status of the application; Either `production`, `sandbox` (default), or `disabled`.
|
||||
* @property {Date} created Date Application object was created. Default: current date.
|
||||
* @property {Date} modified Date Application object was modified. Default: current date.
|
||||
*
|
||||
* @property {Boolean} pushSettings.apns.production Whether to use production Apple Push Notification Service (APNS) servers to send push notifications.
|
||||
* If true, uses `gateway.push.apple.com:2195` and `feedback.push.apple.com:2196`.
|
||||
* If false, uses `gateway.sandbox.push.apple.com:2195` and `feedback.sandbox.push.apple.com:2196`
|
||||
* @property {String} pushSettings.apns.certData The certificate data loaded from the cert.pem file (APNS).
|
||||
* @property {String} pushSettings.apns.keyData The key data loaded from the key.pem file (APNS).
|
||||
* @property {String} pushSettings.apns.pushOptions.gateway (APNS).
|
||||
* @property {Number} pushSettings.apns.pushOptions.port (APNS).
|
||||
* @property {String} pushSettings.apns.feedbackOptions.gateway (APNS).
|
||||
* @property {Number} pushSettings.apns.feedbackOptions.port (APNS).
|
||||
* @property {Boolean} pushSettings.apns.feedbackOptions.batchFeedback (APNS).
|
||||
* @property {Number} pushSettings.apns.feedbackOptions.interval (APNS).
|
||||
* @property {String} pushSettings.gcm.serverApiKey: Google Cloud Messaging API key.
|
||||
*
|
||||
* @class
|
||||
* @inherits {Model}
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/*!
|
||||
* Module Dependencies.
|
||||
*/
|
||||
|
||||
|
@ -10,12 +10,12 @@ var PersistedModel = require('./persisted-model')
|
|||
, assert = require('assert')
|
||||
, debug = require('debug')('loopback:change');
|
||||
|
||||
/**
|
||||
/*!
|
||||
* Properties
|
||||
*/
|
||||
|
||||
var properties = {
|
||||
id: {type: String, generated: true, id: true},
|
||||
id: {type: String, id: true},
|
||||
rev: {type: String},
|
||||
prev: {type: String},
|
||||
checkpoint: {type: Number},
|
||||
|
@ -23,7 +23,7 @@ var properties = {
|
|||
modelId: {type: String}
|
||||
};
|
||||
|
||||
/**
|
||||
/*!
|
||||
* Options
|
||||
*/
|
||||
|
||||
|
@ -34,12 +34,12 @@ var options = {
|
|||
/**
|
||||
* Change list entry.
|
||||
*
|
||||
* @property id {String} Hash of the modelName and id
|
||||
* @property rev {String} the current model revision
|
||||
* @property prev {String} the previous model revision
|
||||
* @property checkpoint {Number} the current checkpoint at time of the change
|
||||
* @property modelName {String} the model name
|
||||
* @property modelId {String} the model id
|
||||
* @property {String} id Hash of the modelName and id
|
||||
* @property {String} rev The current model revision
|
||||
* @property {String} prev The previous model revision
|
||||
* @property {Number} checkpoint The current checkpoint at time of the change
|
||||
* @property {String} modelName Model name
|
||||
* @property {String} modelId Model ID
|
||||
*
|
||||
* @class
|
||||
* @inherits {Model}
|
||||
|
@ -515,7 +515,7 @@ function Conflict(modelId, SourceModel, TargetModel) {
|
|||
* Fetch the conflicting models.
|
||||
*
|
||||
* @callback {Function} callback
|
||||
* @param {Error}
|
||||
* @param {Error} err
|
||||
* @param {PersistedModel} source
|
||||
* @param {PersistedModel} target
|
||||
*/
|
||||
|
@ -618,12 +618,12 @@ Conflict.prototype.resolve = function(cb) {
|
|||
/**
|
||||
* Determine the conflict type.
|
||||
*
|
||||
* ```js
|
||||
* // possible results are
|
||||
* Change.UPDATE // => source and target models were updated
|
||||
* Change.DELETE // => the source and or target model was deleted
|
||||
* Change.UNKNOWN // => the conflict type is uknown or due to an error
|
||||
* ```
|
||||
* Possible results are
|
||||
*
|
||||
* - `Change.UPDATE`: Source and target models were updated.
|
||||
* - `Change.DELETE`: Source and or target model was deleted.
|
||||
* - `Change.UNKNOWN`: the conflict type is uknown or due to an error.
|
||||
*
|
||||
* @callback {Function} callback
|
||||
* @param {Error} err
|
||||
* @param {String} type The conflict type.
|
||||
|
|
|
@ -14,16 +14,12 @@ var properties = {
|
|||
};
|
||||
|
||||
/**
|
||||
* The Email 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.
|
||||
*
|
||||
* **Properties**
|
||||
*
|
||||
* - `to` - String (required)
|
||||
* - `from` - String (required)
|
||||
* - `subject` - String (required)
|
||||
* - `text` - String
|
||||
* - `html` - String
|
||||
*
|
||||
* @class
|
||||
* @inherits {Model}
|
||||
*/
|
||||
|
@ -58,4 +54,4 @@ var Email = module.exports = Model.extend('Email', properties);
|
|||
|
||||
Email.prototype.send = function() {
|
||||
throw new Error('You must connect the Email Model to a Mail connector');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -380,6 +380,19 @@ Model.remoteMethod = function(name, options) {
|
|||
this.sharedClass.defineMethod(name, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable remote invocation for the method with the given name.
|
||||
*
|
||||
* @param {String} name The name of the method.
|
||||
* @param {Boolean} isStatic Is the method static (eg. `MyModel.myMethod`)? Pass
|
||||
* `false` if the method defined on the prototype (eg.
|
||||
* `MyModel.prototype.myMethod`).
|
||||
*/
|
||||
|
||||
Model.disableRemoteMethod = function(name, isStatic) {
|
||||
this.sharedClass.disableMethod(name, isStatic || false);
|
||||
}
|
||||
|
||||
Model.belongsToRemoting = function(relationName, relation, define) {
|
||||
var modelName = relation.modelTo && relation.modelTo.modelName;
|
||||
modelName = modelName || 'PersistedModel';
|
||||
|
|
|
@ -30,6 +30,9 @@ var RoleMappingSchema = {
|
|||
* The `RoleMapping` model extends from the built in `loopback.Model` type.
|
||||
*
|
||||
* @class
|
||||
* @property {String} id Generated ID.
|
||||
* @property {String} name Name of the role.
|
||||
* @property {String} Description Text description.
|
||||
* @inherits {Model}
|
||||
*/
|
||||
|
||||
|
|
|
@ -116,6 +116,12 @@ var options = {
|
|||
* - ALLOW EVERYONE `findById`
|
||||
* - ALLOW OWNER `updateAttributes`
|
||||
*
|
||||
* @property {String} username Must be unique
|
||||
* @property {String} password Hidden from remote clients
|
||||
* @property {String} email Must be valid email
|
||||
* @property {Boolean} emailVerified Set when a user's email has been verified via `confirm()`
|
||||
* @property {String} verificationToken Set when `verify()` is called
|
||||
*
|
||||
* @class
|
||||
* @inherits {Model}
|
||||
*/
|
||||
|
@ -169,7 +175,7 @@ User.login = function (credentials, include, fn) {
|
|||
}else {
|
||||
include = include.toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var query = {};
|
||||
|
|
|
@ -27,22 +27,23 @@
|
|||
"mobile",
|
||||
"mBaaS"
|
||||
],
|
||||
"version": "2.2.0",
|
||||
"version": "2.4.1",
|
||||
"scripts": {
|
||||
"test": "grunt mocha-and-karma"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "~0.9.0",
|
||||
"bcryptjs": "~2.0.2",
|
||||
"body-parser": "~1.8.1",
|
||||
"canonical-json": "0.0.4",
|
||||
"debug": "~2.0.0",
|
||||
"ejs": "~1.0.0",
|
||||
"express": "4.x",
|
||||
"strong-remoting": "^2.1.0",
|
||||
"bcryptjs": "~2.0.2",
|
||||
"debug": "~2.0.0",
|
||||
"inflection": "~1.4.2",
|
||||
"loopback-connector-remote": "^1.0.1",
|
||||
"nodemailer": "~1.3.0",
|
||||
"nodemailer-stub-transport": "~0.1.4",
|
||||
"strong-remoting": "^2.4.0",
|
||||
"uid2": "0.0.3",
|
||||
"underscore": "~1.7.0",
|
||||
"underscore.string": "~2.3.3"
|
||||
|
|
|
@ -84,6 +84,7 @@ describe('Change', function(){
|
|||
it('should create an entry', function (done) {
|
||||
var test = this;
|
||||
Change.findById(this.result.id, function(err, change) {
|
||||
if (err) return done(err);
|
||||
assert.equal(change.id, test.result.id);
|
||||
done();
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue