Merge branch 'release/2.4.1' into production

This commit is contained in:
Miroslav Bajtoš 2014-10-10 19:52:18 +02:00
commit 6079792072
12 changed files with 96 additions and 192 deletions

View File

@ -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 projects 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

View File

@ -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

View File

@ -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() {}

View File

@ -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
*/

View File

@ -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}
*/

View File

@ -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.

View File

@ -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');
}
}

View File

@ -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';

View File

@ -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}
*/

View File

@ -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 = {};

View File

@ -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"

View File

@ -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();
});