diff --git a/docs.json b/docs.json index 36765298..eb68a22b 100644 --- a/docs.json +++ b/docs.json @@ -1,8 +1,9 @@ { "title": "LoopBack Documentation", "content": [ - "docs/api.md", - "docs/api-app.md", + "lib/application.js", + {"title": "Middleware", "depth": 3}, + "lib/middleware/token.js", "lib/models/access-token.js", "lib/models/access-context.js", "lib/models/acl.js", diff --git a/docs/api-app.md b/docs/api-app.md index 0b3c7bb8..28dbf87b 100644 --- a/docs/api-app.md +++ b/docs/api-app.md @@ -218,8 +218,6 @@ View generated REST documentation at [http://localhost:3000/_docs](http://localh LoopBack includes middleware similar to [Express / Connect middleware](http://expressjs.com/api.html#middleware). - - #### loopback.token(options) **Options** diff --git a/lib/application.js b/lib/application.js index c7a19365..6497441f 100644 --- a/lib/application.js +++ b/lib/application.js @@ -1,4 +1,4 @@ -/** +/*! * Module dependencies. */ @@ -12,13 +12,43 @@ var DataSource = require('loopback-datasource-juggler').DataSource , path = require('path'); /** + * The `App` object represents a Loopback application. + * + * The App object extends [Express](http://expressjs.com/api.html#express) and + * supports + * [Express / Connect middleware](http://expressjs.com/api.html#middleware). See + * [Express documentation](http://expressjs.com/api.html) for details. + * + * ```js + * var loopback = require('loopback'); + * var app = loopback(); + * + * app.get('/', function(req, res){ + * res.send('hello world'); + * }); + * + * app.listen(3000); + * ``` + * + * @class LoopBackApplication + * @header app = loopback() + */ +function App() { + // no op +} + +/*! * Export the app prototype. */ var app = exports = module.exports = {}; /** - * Create a set of remote objects. + * Lazily load a set of [remote objects](http://apidocs.strongloop.com/strong-remoting/#remoteobjectsoptions). + * + * **NOTE:** Calling `app.remotes()` multiple times will only ever return a + * single set of remote objects. + * @returns {RemoteObjects} */ app.remotes = function () { @@ -29,7 +59,7 @@ app.remotes = function () { } } -/** +/*! * Remove a route by reference. */ @@ -44,9 +74,24 @@ app.disuse = function (route) { } /** - * Expose a model. + * Define and attach a model to the app. The `Model` will be available on the + * `app.models` object. * - * @param Model {Model} + * ```js + * var Widget = app.model('Widget', {dataSource: 'db'}); + * Widget.create({name: 'pencil'}); + * app.models.Widget.find(function(err, widgets) { + * console.log(widgets[0]); // => {name: 'pencil'} + * }); + * ``` + * + * @param {String} modelName The name of the model to define + * @options {Object} config The model's configuration + * @property {String} dataSource The `DataSource` to attach the model to + * @property {Object} [options] an object containing `Model` options + * @property {Object} [properties] object defining the `Model` properties in [LoopBack Definition Language](http://docs.strongloop.com/loopback-datasource-juggler/#loopback-definition-language) + * @end + * @returns {ModelConstructor} the model class */ app.model = function (Model, config) { @@ -78,6 +123,9 @@ app.model = function (Model, config) { /** * Get all exposed models. + * + * @header app.models() or app.models.ModelName + * @returns {Array} a list of model classes */ app.models = function () { @@ -86,6 +134,9 @@ app.models = function () { /** * Define a DataSource. + * + * @param {String} name The data source name + * @param {Object} config The data source config */ app.dataSource = function (name, config) { @@ -121,7 +172,7 @@ app.remotes = function () { return this._remotes || (this._remotes = RemoteObjects.create()); } -/** +/*! * Enable documentation */ @@ -189,8 +240,81 @@ app.enableAuth = function() { } /** - * Initialize the app using JSON and JavaScript files. - * + * Initialize an application from an options object or a set of JSON and JavaScript files. + * + * **What happens during an app _boot_?** + * + * 1. **DataSources** are created from an `options.dataSources` object or `datasources.json` in the current directory + * 2. **Models** are created from an `options.models` object or `models.json` in the current directory + * 3. Any JavaScript files in the `./models` directory are loaded with `require()`. + * 4. Any JavaScript files in the `./boot` directory are loaded with `require()`. + * + * **Options** + * + * - `cwd` - _optional_ - the directory to use when loading JSON and JavaScript files + * - `models` - _optional_ - an object containing `Model` definitions + * - `dataSources` - _optional_ - an object containing `DataSource` definitions + * + * + * **Model Definitions** + * + * The following is an example of an object containing two `Model` definitions: "location" and "inventory". + * + * ```js + * { + * "dealership": { + * // a reference, by name, to a dataSource definition + * "dataSource": "my-db", + * // the options passed to Model.extend(name, properties, options) + * "options": { + * "relations": { + * "cars": { + * "type": "hasMany", + * "model": "Car", + * "foreignKey": "dealerId" + * } + * } + * }, + * // the properties passed to Model.extend(name, properties, options) + * "properties": { + * "id": {"id": true}, + * "name": "String", + * "zip": "Number", + * "address": "String" + * } + * }, + * "car": { + * "dataSource": "my-db" + * "properties": { + * "id": { + * "type": "String", + * "required": true, + * "id": true + * }, + * "make": { + * "type": "String", + * "required": true + * }, + * "model": { + * "type": "String", + * "required": true + * } + * } + * } + * } + * ``` + * + * **Model definition properties** + * + * - `dataSource` - **required** - a string containing the name of the data source definition to attach the `Model` to + * - `options` - _optional_ - an object containing `Model` options + * - `properties` _optional_ - an object defining the `Model` properties in [LoopBack Definition Language](http://docs.strongloop.com/loopback-datasource-juggler/#loopback-definition-language) + * + * **DataSource definition properties** + * + * - `connector` - **required** - the name of the [connector](#working-with-data-sources-and-connectors) + * + * * @throws {Error} If config is not valid * @throws {Error} If boot fails */ diff --git a/lib/middleware/token.js b/lib/middleware/token.js index 26088855..327989c1 100644 --- a/lib/middleware/token.js +++ b/lib/middleware/token.js @@ -1,4 +1,4 @@ -/** +/*! * Module dependencies. */ @@ -6,12 +6,48 @@ var loopback = require('../loopback'); var RemoteObjects = require('strong-remoting'); var assert = require('assert'); -/** +/*! * Export the middleware. */ module.exports = token; +/** + * **Options** + * + * - `cookies` - An `Array` of cookie names + * - `headers` - An `Array` of header names + * - `params` - An `Array` of param names + * - `model` - Specify an AccessToken class to use + * + * Each array is used to add additional keys to find an `accessToken` for a `request`. + * + * The following example illustrates how to check for an `accessToken` in a custom cookie, query string parameter + * and header called `foo-auth`. + * + * ```js + * app.use(loopback.token({ + * cookies: ['foo-auth'], + * headers: ['foo-auth', 'X-Foo-Auth'], + * cookies: ['foo-auth', 'foo_auth'] + * })); + * ``` + * + * **Defaults** + * + * By default the following names will be checked. These names are appended to any optional names. They will always + * be checked, but any names specified will be checked first. + * + * - **access_token** + * - **X-Access-Token** + * - **authorization** + * - **access_token** + * + * **NOTE:** The `loopback.token()` middleware will only check for [signed cookies](http://expressjs.com/api.html#req.signedCookies). + * + * @header loopback.token(options) + */ + function token(options) { options = options || {}; var TokenModel = options.model || loopback.AccessToken; diff --git a/lib/models/access-token.js b/lib/models/access-token.js index fba53357..acf8484e 100644 --- a/lib/models/access-token.js +++ b/lib/models/access-token.js @@ -12,12 +12,8 @@ var Model = require('../loopback').Model , Role = require('./role').Role , ACL = require('./acl').ACL; -/** +/*! * Default AccessToken properties. - * - * @property id {String} - Generated token ID - * @property ttl {Number} - Time to live - * @property created {Date} - When the token was created */ var properties = { @@ -30,6 +26,10 @@ var properties = { /** * Token based authentication and access control. + * + * @property id {String} Generated token ID + * @property ttl {Number} Time to live + * @property created {Date} When the token was created * * **Default ACLs** *