Merge latest from master
This commit is contained in:
commit
d237ae5ddb
|
@ -0,0 +1,194 @@
|
||||||
|
|
||||||
|
### 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:
|
||||||
|
|
||||||
|
* 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).
|
||||||
|
|
||||||
|
* Make something better or fix a bug.
|
||||||
|
|
||||||
|
* Adhere to code style outlined in the
|
||||||
|
[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).
|
||||||
|
|
||||||
|
* 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 ###
|
||||||
|
|
||||||
|
```
|
||||||
|
Individual Contributor License Agreement
|
||||||
|
|
||||||
|
By signing this Individual Contributor License Agreement
|
||||||
|
("Agreement"), and making a Contribution (as defined below) to
|
||||||
|
StrongLoop, Inc. ("StrongLoop"), You (as defined below) accept and
|
||||||
|
agree to the following terms and conditions for Your present and
|
||||||
|
future Contributions submitted to StrongLoop. Except for the license
|
||||||
|
granted in this Agreement to StrongLoop and recipients of software
|
||||||
|
distributed by StrongLoop, You reserve all right, title, and interest
|
||||||
|
in and to Your Contributions.
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
|
||||||
|
"You" or "Your" shall mean the copyright owner or the individual
|
||||||
|
authorized by the copyright owner that is entering into this
|
||||||
|
Agreement with StrongLoop.
|
||||||
|
|
||||||
|
"Contribution" shall mean any original work of authorship,
|
||||||
|
including any modifications or additions to an existing work, that
|
||||||
|
is intentionally submitted by You to StrongLoop for inclusion in,
|
||||||
|
or documentation of, any of the products owned or managed by
|
||||||
|
StrongLoop ("Work"). For purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication
|
||||||
|
sent to StrongLoop or its representatives, including but not
|
||||||
|
limited to communication or electronic mailing lists, source code
|
||||||
|
control systems, and issue tracking systems that are managed by,
|
||||||
|
or on behalf of, StrongLoop for the purpose of discussing and
|
||||||
|
improving the Work, but excluding communication that is
|
||||||
|
conspicuously marked or otherwise designated in writing by You as
|
||||||
|
"Not a Contribution."
|
||||||
|
|
||||||
|
2. You Grant a Copyright License to StrongLoop
|
||||||
|
|
||||||
|
Subject to the terms and conditions of this Agreement, You hereby
|
||||||
|
grant to StrongLoop and recipients of software distributed by
|
||||||
|
StrongLoop, a perpetual, worldwide, non-exclusive, no-charge,
|
||||||
|
royalty-free, irrevocable copyright license to reproduce, prepare
|
||||||
|
derivative works of, publicly display, publicly perform,
|
||||||
|
sublicense, and distribute Your Contributions and such derivative
|
||||||
|
works under any license and without any restrictions.
|
||||||
|
|
||||||
|
3. You Grant a Patent License to StrongLoop
|
||||||
|
|
||||||
|
Subject to the terms and conditions of this Agreement, You hereby
|
||||||
|
grant to StrongLoop and to recipients of software distributed by
|
||||||
|
StrongLoop a perpetual, worldwide, non-exclusive, no-charge,
|
||||||
|
royalty-free, irrevocable (except as stated in this Section)
|
||||||
|
patent license to make, have made, use, offer to sell, sell,
|
||||||
|
import, and otherwise transfer the Work under any license and
|
||||||
|
without any restrictions. The patent license You grant to
|
||||||
|
StrongLoop under this Section applies only to those patent claims
|
||||||
|
licensable by You that are necessarily infringed by Your
|
||||||
|
Contributions(s) alone or by combination of Your Contributions(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If any
|
||||||
|
entity institutes a patent litigation against You or any other
|
||||||
|
entity (including a cross-claim or counterclaim in a lawsuit)
|
||||||
|
alleging that Your Contribution, or the Work to which You have
|
||||||
|
contributed, constitutes direct or contributory patent
|
||||||
|
infringement, any patent licenses granted to that entity under
|
||||||
|
this Agreement for that Contribution or Work shall terminate as
|
||||||
|
of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. You Have the Right to Grant Licenses to StrongLoop
|
||||||
|
|
||||||
|
You represent that You are legally entitled to grant the licenses
|
||||||
|
in this Agreement.
|
||||||
|
|
||||||
|
If Your employer(s) has rights to intellectual property that You
|
||||||
|
create, You represent that You have received permission to make
|
||||||
|
the Contributions on behalf of that employer, that Your employer
|
||||||
|
has waived such rights for Your Contributions, or that Your
|
||||||
|
employer has executed a separate Corporate Contributor License
|
||||||
|
Agreement with StrongLoop.
|
||||||
|
|
||||||
|
5. The Contributions Are Your Original Work
|
||||||
|
|
||||||
|
You represent that each of Your Contributions are Your original
|
||||||
|
works of authorship (see Section 8 (Submissions on Behalf of
|
||||||
|
Others) for submission on behalf of others). You represent that to
|
||||||
|
Your knowledge, no other person claims, or has the right to claim,
|
||||||
|
any right in any intellectual property right related to Your
|
||||||
|
Contributions.
|
||||||
|
|
||||||
|
You also represent that You are not legally obligated, whether by
|
||||||
|
entering into an agreement or otherwise, in any way that conflicts
|
||||||
|
with the terms of this Agreement.
|
||||||
|
|
||||||
|
You represent that Your Contribution submissions include complete
|
||||||
|
details of any third-party license or other restriction (including,
|
||||||
|
but not limited to, related patents and trademarks) of which You
|
||||||
|
are personally aware and which are associated with any part of
|
||||||
|
Your Contributions.
|
||||||
|
|
||||||
|
6. You Don't Have an Obligation to Provide Support for Your Contributions
|
||||||
|
|
||||||
|
You are not expected to provide support for Your Contributions,
|
||||||
|
except to the extent You desire to provide support. You may provide
|
||||||
|
support for free, for a fee, or not at all.
|
||||||
|
|
||||||
|
6. No Warranties or Conditions
|
||||||
|
|
||||||
|
StrongLoop acknowledges that unless required by applicable law or
|
||||||
|
agreed to in writing, You provide Your Contributions on an "AS IS"
|
||||||
|
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES
|
||||||
|
OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
7. Submission on Behalf of Others
|
||||||
|
|
||||||
|
If You wish to submit work that is not Your original creation, You
|
||||||
|
may submit it to StrongLoop separately from any Contribution,
|
||||||
|
identifying the complete details of its source and of any license
|
||||||
|
or other restriction (including, but not limited to, related
|
||||||
|
patents, trademarks, and license agreements) of which You are
|
||||||
|
personally aware, and conspicuously marking the work as
|
||||||
|
"Submitted on Behalf of a Third-Party: [named here]".
|
||||||
|
|
||||||
|
8. Agree to Notify of Change of Circumstances
|
||||||
|
|
||||||
|
You agree to notify StrongLoop of any facts or circumstances of
|
||||||
|
which You become aware that would make these representations
|
||||||
|
inaccurate in any respect. Email us at callback@strongloop.com.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
[Google Javascript Style Guide]: https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
|
||||||
|
[license]: LICENSE
|
||||||
|
|
7
LICENSE
7
LICENSE
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2013-2014 StrongLoop, Inc.
|
Copyright (c) 2013-2014 StrongLoop, Inc and other contributors.
|
||||||
|
|
||||||
loopback uses a 'dual license' model. Users may use loopback under the terms of
|
loopback uses a 'dual license' model. Users may use loopback under the terms of
|
||||||
the MIT license, or under the StrongLoop License. The text of both is included
|
the MIT license, or under the StrongLoop License. The text of both is included
|
||||||
|
@ -26,7 +26,12 @@ THE SOFTWARE.
|
||||||
|
|
||||||
StrongLoop License
|
StrongLoop License
|
||||||
|
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.strongloop.com/license/
|
||||||
|
|
||||||
STRONGLOOP SUBSCRIPTION AGREEMENT
|
STRONGLOOP SUBSCRIPTION AGREEMENT
|
||||||
|
|
||||||
PLEASE READ THIS AGREEMENT CAREFULLY BEFORE YOU AGREE TO THESE TERMS. IF YOU
|
PLEASE READ THIS AGREEMENT CAREFULLY BEFORE YOU AGREE TO THESE TERMS. IF YOU
|
||||||
ARE ACTING ON BEHALF OF AN ENTITY, THEN YOU REPRESENT THAT YOU HAVE THE
|
ARE ACTING ON BEHALF OF AN ENTITY, THEN YOU REPRESENT THAT YOU HAVE THE
|
||||||
AUTHORITY TO ENTER INTO THIS AGREEMENT ON BEHALF OF THAT ENTITY. IF YOU DO NOT
|
AUTHORITY TO ENTER INTO THIS AGREEMENT ON BEHALF OF THAT ENTITY. IF YOU DO NOT
|
||||||
|
|
75
README.md
75
README.md
|
@ -1,29 +1,78 @@
|
||||||
# LoopBack
|
LoopBack is a highly extensible, open source Node.js framework that enables you to:
|
||||||
|
|
||||||
For a quick introduction and overview, see http://loopback.io/.
|
* Create dynamic end-to-end REST APIs with little or no coding
|
||||||
|
* Easily access data from Oracle, MySQL, PostgreSQL, MS SQL Server, MongoDB, SOAP and other REST APIs
|
||||||
|
* Incorporate model relationships and access controls for complex APIs
|
||||||
|
* Run your application on-premises or in the cloud
|
||||||
|
* Use built-in push, geolocation, and file services for mobile use cases
|
||||||
|
* Easily create client apps using Android, iOS, and JavaScript SDKs
|
||||||
|
|
||||||
## Documentation
|
LoopBack consists of:
|
||||||
|
* A library of Node.js modules.
|
||||||
|
* A command line tool, `slc`, for creating and working with LoopBack applications.
|
||||||
|
* Client SDKs for native and web-based mobile clients.
|
||||||
|
|
||||||
[See the full documentation](http://docs.strongloop.com/display/DOC/LoopBack).
|
For more details, see http://loopback.io/.
|
||||||
|
|
||||||
## API
|
## LoopBack modules
|
||||||
|
|
||||||
[Browse the API documentation](http://apidocs.strongloop.com/loopback).
|
In addition to the [main LoopBack module](https://github.com/strongloop/loopback), LoopBack consists of numerous other modules that implement specific functionality,
|
||||||
|
as illustrated below:
|
||||||
|
|
||||||
## Mailing List
|
![LoopBack modules](./docs/assets/lb-modules.png "LoopBack modules")
|
||||||
|
|
||||||
Discuss features and ask questions on [LoopBack Forum](https://groups.google.com/forum/#!forum/loopbackjs).
|
* Frameworks
|
||||||
|
* [loopback](https://github.com/strongloop/loopback)
|
||||||
|
* [loopback-datasource-juggler](https://github.com/strongloop/loopback-datasource-juggler)
|
||||||
|
* [strong-remoting](https://github.com/strongloop/strong-remoting)
|
||||||
|
|
||||||
## Issues
|
* Enterprise Connectors
|
||||||
|
* [loopback-connector-mongodb](https://github.com/strongloop/loopback-connector-mongodb)
|
||||||
|
* [loopback-connector-mysql](https://github.com/strongloop/loopback-connector-mysql)
|
||||||
|
* [loopback-connector-oracle](https://github.com/strongloop/loopback-connector-oracle)
|
||||||
|
* [loopback-connector-postgresql](https://github.com/strongloop/loopback-connector-postgresql)
|
||||||
|
* [loopback-connector-rest](https://github.com/strongloop/loopback-connector-rest)
|
||||||
|
* [loopback-connector-soap](https://github.com/strongloop/loopback-connector-soap)
|
||||||
|
|
||||||
File any issues [here on GitHub](https://github.com/strongloop/loopback/issues).
|
* Mobile services
|
||||||
|
* [loopback-push-notification](https://github.com/strongloop/loopback-push-notification)
|
||||||
|
* [loopback-storage-service](https://github.com/strongloop/loopback-storage-service)
|
||||||
|
|
||||||
## Features
|
* Clients
|
||||||
|
* [loopback-ios](https://github.com/strongloop/loopback-ios)
|
||||||
|
* [loopback-remoting-ios](https://github.com/strongloop/loopback-remoting-ios)
|
||||||
|
* [loopback-android](https://github.com/strongloop/loopback-android)
|
||||||
|
* [loopback-remoting-android](https://github.com/strongloop/loopback-remoting-android)
|
||||||
|
* [loopback-angular](https://github.com/strongloop/loopback-angular)
|
||||||
|
|
||||||
Read about the [features of LoopBack](https://github.com/strongloop/loopback/wiki/Features).
|
* Tools
|
||||||
|
* [loopback-explorer](https://github.com/strongloop/loopback-explorer)
|
||||||
|
* [loopback-workspace](https://github.com/strongloop/loopback-workspace)
|
||||||
|
* [strong-cli](https://github.com/strongloop/strong-cli)
|
||||||
|
|
||||||
|
* Examples
|
||||||
|
* [loopback-example-full-stack](https://github.com/strongloop/loopback-example-full-stack)
|
||||||
|
* [loopback-example-office-supplies](https://github.com/strongloop/loopback-example-office-supplies)
|
||||||
|
* [loopback-example-todo](https://github.com/strongloop/loopback-example-todo)
|
||||||
|
* [loopback-example-access-control](https://github.com/strongloop/loopback-example-access-control)
|
||||||
|
* [loopback-example-proxy](https://github.com/strongloop/loopback-example-proxy)
|
||||||
|
* [strongloop-community/loopback-example-datagraph](https://github.com/strongloop-community/loopback-example-datagraph)
|
||||||
|
* [strongloop-community/loopback-mysql-example](https://github.com/strongloop-community/loopback-mysql-example)
|
||||||
|
* [strongloop-community/loopback-examples-ios](https://github.com/strongloop-community/loopback-examples-ios)
|
||||||
|
* [strongloop-community/loopback-example-ssl](https://github.com/strongloop-community/loopback-example-ssl)
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
* [Documentation](http://docs.strongloop.com/display/DOC/LoopBack).
|
||||||
|
* [API documentation](http://apidocs.strongloop.com/loopback).
|
||||||
|
* [LoopBack Google Group](https://groups.google.com/forum/#!forum/loopbackjs).
|
||||||
|
* [GitHub issues](https://github.com/strongloop/loopback/issues).
|
||||||
|
* Read more about the [LoopBack's features](https://github.com/strongloop/loopback/wiki/Features).
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
Please read [CONTRIBUTING.md](CONTRIBUTING.md) on how to contribute.
|
||||||
|
|
||||||
A brief guide for [contributing to LoopBack projects](https://github.com/strongloop/loopback/wiki/How-To-Contribute).
|
A brief guide for [contributing to LoopBack projects](https://github.com/strongloop/loopback/wiki/How-To-Contribute).
|
||||||
|
|
||||||
[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/8caf6b5cce4be4d13c01ea9aafc9f407 "githalytics.com")](http://githalytics.com/strongloop/loopback)
|
[![Analytics](https://sl-beacon.appspot.com/UA-37775386-1/github/loopback/readme?pixel)](https://github.com/strongloop/loopback)
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
"title": "LoopBack Documentation",
|
"title": "LoopBack Documentation",
|
||||||
"content": [
|
"content": [
|
||||||
"lib/application.js",
|
"lib/application.js",
|
||||||
{"title": "LoopBack", "depth": 3},
|
|
||||||
"lib/loopback.js",
|
"lib/loopback.js",
|
||||||
{"title": "Middleware", "depth": 3},
|
|
||||||
"lib/middleware/token.js",
|
"lib/middleware/token.js",
|
||||||
"lib/models/access-token.js",
|
"lib/models/access-token.js",
|
||||||
"lib/models/access-context.js",
|
"lib/models/access-context.js",
|
||||||
|
|
|
@ -443,145 +443,6 @@ appearing in many groups, you could declare the models this way,
|
||||||
user.groups.remove(group, callback); // remove the user from the group
|
user.groups.remove(group, callback); // remove the user from the group
|
||||||
```
|
```
|
||||||
|
|
||||||
### Validations
|
|
||||||
|
|
||||||
#### Model.validatesFormatOf(property, options)
|
|
||||||
|
|
||||||
Require a model to include a property that matches the given format.
|
|
||||||
|
|
||||||
```js
|
|
||||||
User.validatesFormat('name', {with: /\w+/});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Model.validatesPresenceOf(properties...)
|
|
||||||
|
|
||||||
Require a model to include a property to be considered valid.
|
|
||||||
|
|
||||||
```js
|
|
||||||
User.validatesPresenceOf('first', 'last', 'age');
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Model.validatesLengthOf(property, options)
|
|
||||||
|
|
||||||
Require a property length to be within a specified range.
|
|
||||||
|
|
||||||
```js
|
|
||||||
User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Model.validatesInclusionOf(property, options)
|
|
||||||
|
|
||||||
Require a value for `property` to be in the specified array.
|
|
||||||
|
|
||||||
```js
|
|
||||||
User.validatesInclusionOf('gender', {in: ['male', 'female']});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Model.validatesExclusionOf(property, options)
|
|
||||||
|
|
||||||
Require a value for `property` to not exist in the specified array.
|
|
||||||
|
|
||||||
```js
|
|
||||||
User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Model.validatesNumericalityOf(property, options)
|
|
||||||
|
|
||||||
Require a value for `property` to be a specific type of `Number`.
|
|
||||||
|
|
||||||
```js
|
|
||||||
User.validatesNumericalityOf('age', {int: true});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Model.validatesUniquenessOf(property, options)
|
|
||||||
|
|
||||||
Ensure the value for `property` is unique in the collection of models.
|
|
||||||
|
|
||||||
```js
|
|
||||||
User.validatesUniquenessOf('email', {message: 'email is not unique'});
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** not available for all [connectors](#connectors).
|
|
||||||
|
|
||||||
Currently supported in these connectors:
|
|
||||||
|
|
||||||
- [In Memory](#memory-connector)
|
|
||||||
- [Oracle](http://github.com/strongloop/loopback-connector-oracle)
|
|
||||||
- [MongoDB](http://github.com/strongloop/loopback-connector-mongodb)
|
|
||||||
|
|
||||||
#### myModel.isValid()
|
|
||||||
|
|
||||||
Validate the model instance.
|
|
||||||
|
|
||||||
```js
|
|
||||||
user.isValid(function (valid) {
|
|
||||||
if (!valid) {
|
|
||||||
console.log(user.errors);
|
|
||||||
// => hash of errors
|
|
||||||
// => {
|
|
||||||
// => username: [errmessage, errmessage, ...],
|
|
||||||
// => email: ...
|
|
||||||
// => }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### loopback.ValidationError
|
|
||||||
|
|
||||||
`ValidationError` is raised when the application attempts to save an invalid
|
|
||||||
model instance.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
"name": "ValidationError",
|
|
||||||
"status": 422,
|
|
||||||
"message": "The Model instance is not valid. \
|
|
||||||
See `details` property of the error object for more info.",
|
|
||||||
"statusCode": 422,
|
|
||||||
"details": {
|
|
||||||
"context": "user",
|
|
||||||
"codes": {
|
|
||||||
"password": [
|
|
||||||
"presence"
|
|
||||||
],
|
|
||||||
"email": [
|
|
||||||
"uniqueness"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"messages": {
|
|
||||||
"password": [
|
|
||||||
"can't be blank"
|
|
||||||
],
|
|
||||||
"email": [
|
|
||||||
"Email already exists"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You might run into situations where you need to raise a validation error
|
|
||||||
yourself, for example in a "before" hook or a custom model method.
|
|
||||||
|
|
||||||
```js
|
|
||||||
MyModel.prototype.preflight = function(changes, callback) {
|
|
||||||
// Update properties, do not save to db
|
|
||||||
for (var key in changes) {
|
|
||||||
model[key] = changes[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (model.isValid()) {
|
|
||||||
return callback(null, { success: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
// This line shows how to create a ValidationError
|
|
||||||
err = new ValidationError(model);
|
|
||||||
callback(err);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Shared methods
|
### Shared methods
|
||||||
|
|
||||||
Any static or instance method can be decorated as `shared`. These methods are exposed over the provided transport (eg. [loopback.rest](#rest)).
|
Any static or instance method can be decorated as `shared`. These methods are exposed over the provided transport (eg. [loopback.rest](#rest)).
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 215 KiB |
|
@ -3,7 +3,7 @@ var client = loopback();
|
||||||
var CartItem = require('./models').CartItem;
|
var CartItem = require('./models').CartItem;
|
||||||
var remote = loopback.createDataSource({
|
var remote = loopback.createDataSource({
|
||||||
connector: loopback.Remote,
|
connector: loopback.Remote,
|
||||||
root: 'http://localhost:3000'
|
url: 'http://localhost:3000'
|
||||||
});
|
});
|
||||||
|
|
||||||
client.model(CartItem);
|
client.model(CartItem);
|
||||||
|
|
|
@ -7,6 +7,7 @@ var debug = require('debug')('loopback:security:access-context');
|
||||||
* resources
|
* resources
|
||||||
*
|
*
|
||||||
* @class
|
* @class
|
||||||
|
* @options {Object} context The context object
|
||||||
* @property {Principal[]} principals An array of principals
|
* @property {Principal[]} principals An array of principals
|
||||||
* @property {Function} model The model class
|
* @property {Function} model The model class
|
||||||
* @property {String} modelName The model name
|
* @property {String} modelName The model name
|
||||||
|
@ -16,7 +17,6 @@ var debug = require('debug')('loopback:security:access-context');
|
||||||
* @property {String} accessType The access type
|
* @property {String} accessType The access type
|
||||||
* @property {AccessToken} accessToken The access token
|
* @property {AccessToken} accessToken The access token
|
||||||
*
|
*
|
||||||
* @param {Object} context The context object
|
|
||||||
* @returns {AccessContext}
|
* @returns {AccessContext}
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -296,6 +296,9 @@ ACL.getStaticACLs = function getStaticACLs(model, property) {
|
||||||
ACL.checkPermission = function checkPermission(principalType, principalId,
|
ACL.checkPermission = function checkPermission(principalType, principalId,
|
||||||
model, property, accessType,
|
model, property, accessType,
|
||||||
callback) {
|
callback) {
|
||||||
|
if(principalId !== null && principalId !== undefined && (typeof principalId !== 'string') ) {
|
||||||
|
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;
|
||||||
|
@ -356,7 +359,7 @@ ACL.prototype.debug = function() {
|
||||||
* @property {String} accessType The access type
|
* @property {String} accessType The access type
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
ACL.checkAccess = function (context, callback) {
|
ACL.checkAccessForContext = function (context, callback) {
|
||||||
if(!(context instanceof AccessContext)) {
|
if(!(context instanceof AccessContext)) {
|
||||||
context = new AccessContext(context);
|
context = new AccessContext(context);
|
||||||
}
|
}
|
||||||
|
@ -422,7 +425,7 @@ ACL.checkAccess = function (context, callback) {
|
||||||
if(resolved && resolved.permission === ACL.DEFAULT) {
|
if(resolved && resolved.permission === ACL.DEFAULT) {
|
||||||
resolved.permission = (model && model.settings.defaultPermission) || ACL.ALLOW;
|
resolved.permission = (model && model.settings.defaultPermission) || ACL.ALLOW;
|
||||||
}
|
}
|
||||||
debug('checkAccess() returns: %j', resolved);
|
debug('checkAccessForContext() returns: %j', resolved);
|
||||||
callback && callback(null, resolved);
|
callback && callback(null, resolved);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -455,7 +458,7 @@ ACL.checkAccessForToken = function (token, model, modelId, method, callback) {
|
||||||
|
|
||||||
context.debug();
|
context.debug();
|
||||||
|
|
||||||
this.checkAccess(context, function (err, access) {
|
this.checkAccessForContext(context, function (err, access) {
|
||||||
if (err) {
|
if (err) {
|
||||||
callback && callback(err);
|
callback && callback(err);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -78,7 +78,7 @@ function convertNullToNotFoundError(ctx, cb) {
|
||||||
|
|
||||||
var modelName = ctx.method.sharedClass.name;
|
var modelName = ctx.method.sharedClass.name;
|
||||||
var id = ctx.getArgByName('id');
|
var id = ctx.getArgByName('id');
|
||||||
var msg = 'Unkown "' + modelName + '" id "' + id + '".';
|
var msg = 'Unknown "' + modelName + '" id "' + id + '".';
|
||||||
var error = new Error(msg);
|
var error = new Error(msg);
|
||||||
error.statusCode = error.status = 404;
|
error.statusCode = error.status = 404;
|
||||||
cb(error);
|
cb(error);
|
||||||
|
|
|
@ -373,8 +373,14 @@ Role.isInRole = function (role, context, callback) {
|
||||||
async.some(context.principals, function (p, done) {
|
async.some(context.principals, function (p, done) {
|
||||||
var principalType = p.type || undefined;
|
var principalType = p.type || undefined;
|
||||||
var principalId = p.id || undefined;
|
var principalId = p.id || undefined;
|
||||||
|
var roleId = result.id.toString();
|
||||||
|
|
||||||
|
if(principalId !== null && principalId !== undefined && (typeof principalId !== 'string') ) {
|
||||||
|
principalId = principalId.toString();
|
||||||
|
}
|
||||||
|
|
||||||
if (principalType && principalId) {
|
if (principalType && principalId) {
|
||||||
roleMappingModel.findOne({where: {roleId: result.id,
|
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);
|
||||||
|
|
|
@ -379,7 +379,7 @@ User.resetPassword = function(options, cb) {
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
if(typeof options.email === 'string') {
|
if(typeof options.email === 'string') {
|
||||||
UserModel.findOne({email: options.email}, function(err, user) {
|
UserModel.findOne({ where: {email: options.email} }, function(err, user) {
|
||||||
if(err) {
|
if(err) {
|
||||||
cb(err);
|
cb(err);
|
||||||
} else if(user) {
|
} else if(user) {
|
||||||
|
@ -392,7 +392,8 @@ User.resetPassword = function(options, cb) {
|
||||||
cb();
|
cb();
|
||||||
UserModel.emit('resetPasswordRequest', {
|
UserModel.emit('resetPasswordRequest', {
|
||||||
email: options.email,
|
email: options.email,
|
||||||
accessToken: accessToken
|
accessToken: accessToken,
|
||||||
|
user: user
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "loopback",
|
"name": "loopback",
|
||||||
"description": "LoopBack: Open Mobile Platform for Node.js",
|
"description": "LoopBack: Open Mobile Platform for Node.js",
|
||||||
|
"homepage": "http://loopback.io",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"StrongLoop",
|
"StrongLoop",
|
||||||
"LoopBack",
|
"LoopBack",
|
||||||
|
@ -9,7 +10,7 @@
|
||||||
"Platform",
|
"Platform",
|
||||||
"mBaaS"
|
"mBaaS"
|
||||||
],
|
],
|
||||||
"version": "1.8.0",
|
"version": "1.8.2",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha -R spec"
|
"test": "mocha -R spec"
|
||||||
},
|
},
|
||||||
|
|
|
@ -268,7 +268,7 @@ describe('security ACLs', function () {
|
||||||
|
|
||||||
log('ACL 2: ', acl.toObject());
|
log('ACL 2: ', acl.toObject());
|
||||||
|
|
||||||
ACL.checkAccess({
|
ACL.checkAccessForContext({
|
||||||
principals: [
|
principals: [
|
||||||
{type: ACL.USER, id: userId}
|
{type: ACL.USER, id: userId}
|
||||||
],
|
],
|
||||||
|
@ -279,7 +279,7 @@ describe('security ACLs', function () {
|
||||||
assert(!err && access.permission === ACL.ALLOW);
|
assert(!err && access.permission === ACL.ALLOW);
|
||||||
});
|
});
|
||||||
|
|
||||||
ACL.checkAccess({
|
ACL.checkAccessForContext({
|
||||||
principals: [
|
principals: [
|
||||||
{type: ACL.ROLE, id: Role.EVERYONE}
|
{type: ACL.ROLE, id: Role.EVERYONE}
|
||||||
],
|
],
|
||||||
|
|
|
@ -3,8 +3,9 @@ describe('GeoPoint', 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'});
|
||||||
|
|
||||||
assert.equal(here.distanceTo(there, {type: 'meters'}), 782777.923052584);
|
assert.equal(Math.floor(distance), 782777);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -12,8 +13,9 @@ describe('GeoPoint', 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'});
|
||||||
|
|
||||||
assert.equal(GeoPoint.distanceBetween(here, there, {type: 'feet'}), 2568169.038886431);
|
assert.equal(Math.floor(distance), 2568169);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue