Merge 0.9 into master
This commit is contained in:
commit
a2308cbc1c
|
@ -13,7 +13,7 @@ v0.9.0
|
|||
- [DataSource](#data-source)
|
||||
- [Connectors](#connectors)
|
||||
- [Loopback Types](#loopback-types)
|
||||
- [GeoPoint](#geo-point)
|
||||
- [GeoPoint](#geo-point)
|
||||
- [REST Router](#rest-router)
|
||||
- [Bundled Models](#bundled-models)
|
||||
- [User](#user-model)
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
var models = require('../../lib/models');
|
||||
|
||||
var loopback = require('../../');
|
||||
var app = loopback();
|
||||
|
||||
app.use(loopback.rest());
|
||||
|
||||
var dataSource = loopback.createDataSource('db', {connector: loopback.Memory});
|
||||
|
||||
var Application = models.Application(dataSource);
|
||||
|
||||
app.model(Application);
|
||||
|
||||
|
||||
var data = {pushSettings: [
|
||||
{ "platform": "apns",
|
||||
"apns": {
|
||||
"pushOptions": {
|
||||
"gateway": "gateway.sandbox.push.apple.com",
|
||||
"cert": "credentials/apns_cert_dev.pem",
|
||||
"key": "credentials/apns_key_dev.pem"
|
||||
},
|
||||
|
||||
"feedbackOptions": {
|
||||
"gateway": "feedback.sandbox.push.apple.com",
|
||||
"cert": "credentials/apns_cert_dev.pem",
|
||||
"key": "credentials/apns_key_dev.pem",
|
||||
"batchFeedback": true,
|
||||
"interval": 300
|
||||
}
|
||||
}}
|
||||
]}
|
||||
|
||||
Application.create(data, function(err, data) {
|
||||
console.log('Created: ', data.toObject());
|
||||
});
|
||||
|
||||
|
||||
Application.register('MyApp', 'My first mobile application', 'rfeng', function (err, result) {
|
||||
console.log(result.toObject());
|
||||
|
||||
result.resetKeys(function (err, result) {
|
||||
console.log(result.toObject());
|
||||
});
|
||||
});
|
|
@ -25,6 +25,21 @@ app.remotes = function () {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose an object or Class remotely.
|
||||
*
|
||||
* @param {String} name The remote namespace (eg. url base)
|
||||
* @param {Object|Function} obj The object to remote
|
||||
*/
|
||||
|
||||
app.remote = function (name, obj) {
|
||||
// add the object to the remote exports
|
||||
this.remotes().exports[name] = obj;
|
||||
|
||||
// clear the handlers cache
|
||||
this._handlers = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a route by reference.
|
||||
*/
|
||||
|
@ -44,6 +59,7 @@ app.disuse = function (route) {
|
|||
*/
|
||||
|
||||
app._models = [];
|
||||
app._services = [];
|
||||
|
||||
/**
|
||||
* Expose a model.
|
||||
|
@ -52,6 +68,8 @@ app._models = [];
|
|||
*/
|
||||
|
||||
app.model = function (Model) {
|
||||
var remotes = this.remotes();
|
||||
|
||||
this._models.push(Model);
|
||||
Model.shared = true;
|
||||
Model.app = this;
|
||||
|
@ -67,22 +85,28 @@ app.models = function () {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all remote objects.
|
||||
* Expose a service.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {Service} service
|
||||
*/
|
||||
|
||||
app.remoteObjects = function () {
|
||||
var result = {};
|
||||
var models = this.models();
|
||||
app.service = function (name, service) {
|
||||
this._services.push(service);
|
||||
service.shared = true;
|
||||
|
||||
// add in models
|
||||
models.forEach(function (ModelCtor) {
|
||||
// only add shared models
|
||||
if(ModelCtor.shared && typeof ModelCtor.sharedCtor === 'function') {
|
||||
result[ModelCtor.pluralModelName] = ModelCtor;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
service.app = this;
|
||||
|
||||
// add to the remote exports
|
||||
this.remote(name, service);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all exposed services.
|
||||
*/
|
||||
|
||||
app.services = function () {
|
||||
return this._services;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,4 +115,29 @@ app.remoteObjects = function () {
|
|||
|
||||
app.remotes = function () {
|
||||
return this._remotes || (this._remotes = RemoteObjects.create());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a remotes handler.
|
||||
*/
|
||||
|
||||
app.handler = function (type) {
|
||||
var handler = this._handlers[type];
|
||||
|
||||
if(!handler) {
|
||||
// get the sl remoting object
|
||||
var remotes = this.remotes();
|
||||
|
||||
// create and save the handler
|
||||
handler = this._handlers[type] = remotes.handler(type);
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Handlers
|
||||
*/
|
||||
|
||||
app._handlers = {};
|
||||
|
||||
|
|
|
@ -17,21 +17,12 @@ module.exports = rest;
|
|||
|
||||
function rest() {
|
||||
return function (req, res, next) {
|
||||
var app = req.app;
|
||||
var remotes = app.remotes();
|
||||
|
||||
// get all remote objects
|
||||
var objs = app.remoteObjects();
|
||||
|
||||
// export remote objects
|
||||
remotes.exports = objs;
|
||||
|
||||
var handler = remotes.handler('rest');
|
||||
var handler = req.app.handler('rest');
|
||||
|
||||
if(req.url === '/routes') {
|
||||
res.send(handler.adapter.allRoutes());
|
||||
} else if(req.url === '/models') {
|
||||
return res.send(remotes.toJSON());
|
||||
return res.send(req.app.remotes().toJSON());
|
||||
} else {
|
||||
handler(req, res, next);
|
||||
}
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
// Schema ACL options
|
||||
/**
|
||||
Schema ACL options
|
||||
|
||||
Object level permissions, for example, an album owned by a user
|
||||
|
||||
// Object level permissions
|
||||
Factors to be authorized against:
|
||||
|
||||
// open: no protection
|
||||
// none: always rejected
|
||||
// owner: only the owner
|
||||
// loggedIn: any logged in user
|
||||
// roles: logged in users with the roles
|
||||
// related: owner of the related objects
|
||||
|
||||
// Class level permissions
|
||||
* model name: Album
|
||||
* model instance properties: userId of the album, friends, shared
|
||||
* methods
|
||||
* app and/or user ids/roles
|
||||
** loggedIn
|
||||
** roles
|
||||
** userId
|
||||
** appId
|
||||
** none
|
||||
** everyone
|
||||
** relations: owner/friend/granted
|
||||
|
||||
Class level permissions, for example, Album
|
||||
* model name: Album
|
||||
* methods
|
||||
// blog posts
|
||||
allow: ['owner', 'admin'] to: '*' // allow owner's of posts and admins to do anything
|
||||
allow: '*' to: ['find', 'read'] // allow everyone to read and find
|
||||
|
@ -27,5 +35,4 @@ allow: 'owner' to: ['*.destroy', '*.save']
|
|||
// scopes
|
||||
|
||||
// URL level permissions
|
||||
|
||||
|
||||
*/
|
||||
|
|
|
@ -1,17 +1,54 @@
|
|||
// Application model
|
||||
// Authentication schemes
|
||||
var AuthenticationSchemeSchema = {
|
||||
scheme: String, // local, facebook, google, twitter, linkedin, github
|
||||
credential: Object // Scheme-specific credentials
|
||||
}
|
||||
|
||||
var APNSSettingSchema = {
|
||||
pushOptions: {type: {
|
||||
gateway: String,
|
||||
cert: String,
|
||||
key: String
|
||||
}},
|
||||
|
||||
feedbackOptions: {type: {
|
||||
gateway: String,
|
||||
cert: String,
|
||||
key: String,
|
||||
batchFeedback: Boolean,
|
||||
interval: Number
|
||||
}}
|
||||
};
|
||||
|
||||
// Push notification settings
|
||||
var PushNotificationSettingSchema = {
|
||||
platform: {type: String, required: true}, // apns, gcm, mpns
|
||||
// configuration: {type: Object} // platform-specific configurations
|
||||
apns: APNSSettingSchema
|
||||
}
|
||||
|
||||
/**
|
||||
* Data model for Application
|
||||
*/
|
||||
var ApplicationSchema = {
|
||||
|
||||
// Basic information
|
||||
id: {type: String, required: true},
|
||||
name: {type: String, required: true},
|
||||
description: String, // description
|
||||
icon: String, // The icon url
|
||||
public: Boolean,
|
||||
permissions: [String],
|
||||
id: {type: String, required: true}, // The id
|
||||
name: {type: String, required: true}, // The name
|
||||
description: String, // The description
|
||||
icon: String, // The icon image url
|
||||
|
||||
userId: String,
|
||||
owner: String, // The user id of the developer who registers the application
|
||||
collaborators: [String], // A list of users ids who have permissions to work on this app
|
||||
|
||||
status: String,
|
||||
// EMail
|
||||
email: String, // e-mail address
|
||||
emailVerified: Boolean, // Is the e-mail verified
|
||||
|
||||
// oAuth 2.0 settings
|
||||
url: String, // The application url
|
||||
callbackUrls: [String], // oAuth 2.0 code/token callback url
|
||||
permissions: [String], // A list of permissions required by the application
|
||||
|
||||
// Keys
|
||||
clientKey: String,
|
||||
|
@ -21,21 +58,80 @@ var ApplicationSchema = {
|
|||
masterKey: String,
|
||||
|
||||
// Push notification
|
||||
pushPlatforms: [String],
|
||||
pushCredentials: [],
|
||||
pushSettings: [PushNotificationSettingSchema],
|
||||
|
||||
// Authentication
|
||||
authenticationEnabled: Boolean,
|
||||
anonymousAllowed: Boolean,
|
||||
schemes: [String], // Basic, facebook, github, google
|
||||
attachedCredentials: [],
|
||||
// User Authentication
|
||||
authenticationEnabled: {type: Boolean, default: true},
|
||||
anonymousAllowed: {type: Boolean, default: true},
|
||||
authenticationSchemes: [AuthenticationSchemeSchema],
|
||||
|
||||
// email
|
||||
email: String, // e-mail address
|
||||
emailVerified: Boolean, // Is the e-mail verified
|
||||
status: {type: String, default: 'sandbox'}, // Status of the application, production/sandbox/disabled
|
||||
|
||||
collaborators: [String], // A list of users ids who have permissions to work on this app
|
||||
|
||||
created: Date,
|
||||
lastUpdated: Date
|
||||
// Timestamps
|
||||
created: {type: Date, default: Date},
|
||||
modified: {type: Date, default: Date}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Application management functions
|
||||
*/
|
||||
|
||||
var crypto = require('crypto');
|
||||
|
||||
function generateKey(hmacKey, algorithm) {
|
||||
hmacKey = hmacKey || 'loopback';
|
||||
algorithm = algorithm || 'sha256';
|
||||
var hmac = crypto.createHmac(algorithm, hmacKey);
|
||||
var buf = crypto.randomBytes(64);
|
||||
hmac.update(buf);
|
||||
return hmac.digest('base64');
|
||||
}
|
||||
|
||||
module.exports = function (dataSource) {
|
||||
dataSource = dataSource || new require('loopback-data').ModelBuilder();
|
||||
|
||||
// var AuthenticationScheme = dataSource.define('AuthenticationScheme', AuthenticationSchemeSchema);
|
||||
// ApplicationSchema.authenticationSchemes = [AuthenticationScheme];
|
||||
|
||||
// var PushNotificationSetting = dataSource.define('PushNotificationSetting', PushNotificationSettingSchema);
|
||||
// ApplicationSchema.pushSettings = [PushNotificationSetting];
|
||||
|
||||
var Application = dataSource.define('Application', ApplicationSchema);
|
||||
|
||||
// Application.hasMany(AuthenticationScheme, {as: 'authenticationSchemes', foreignKey: 'appId'});
|
||||
// Application.hasMany(PushNotificationSetting, {as: 'pushNotificationSettings', foreignKey: 'appId'});
|
||||
|
||||
Application.afterInitialize = function () {
|
||||
var app = this;
|
||||
// use data argument to update object
|
||||
app.created = app.modified = new Date();
|
||||
app.id = generateKey('id', 'sha1');
|
||||
app.clientKey = generateKey('client');
|
||||
app.javaScriptKey = generateKey('javaScript');
|
||||
app.restApiKey = generateKey('restApi');
|
||||
app.windowsKey = generateKey('windows');
|
||||
app.masterKey = generateKey('master');
|
||||
};
|
||||
|
||||
// Register a new application
|
||||
Application.register = function (name, description, owner, cb) {
|
||||
Application.create({name: name, description: description, owner: owner}, cb);
|
||||
}
|
||||
|
||||
Application.prototype.resetKeys = function(cb) {
|
||||
this.clientKey = generateKey('client');
|
||||
this.javaScriptKey = generateKey('javaScript');
|
||||
this.restApiKey = generateKey('restApi');
|
||||
this.windowsKey = generateKey('windows');
|
||||
this.masterKey = generateKey('master');
|
||||
this.save(cb);
|
||||
}
|
||||
|
||||
return Application;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
exports.Application = require('./application');
|
||||
exports.ACL = require('./acl');
|
||||
exports.Role = require('./role');
|
||||
exports.Installation = require('./installation');
|
||||
|
||||
|
|
@ -1,4 +1,26 @@
|
|||
// Device registration
|
||||
// See Device registration
|
||||
var InstallationSchema = {
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
id: 1
|
||||
},
|
||||
appId: String, // Application id
|
||||
appVersion: String, // Application version
|
||||
userId: String, // User id
|
||||
deviceToken: String,
|
||||
deviceType: String,
|
||||
subscriptions: [String],
|
||||
|
||||
status: {type: String, default: 'active'}, // Status of the application, production/sandbox/disabled
|
||||
|
||||
// Timestamps
|
||||
created: {type: Date, default: Date},
|
||||
modified: {type: Date, default: Date}
|
||||
};
|
||||
|
||||
module.exports = function(dataSource) {
|
||||
dataSource = dataSource || new require('loopback-data').ModelBuilder();
|
||||
var Installation = dataSource.define('Installation', InstallationSchema);
|
||||
return Installation;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
// Role model
|
||||
var RoleSchema = {
|
||||
id: {type: String, required: true},
|
||||
name: {type: String, required: true},
|
||||
roles: [String],
|
||||
users: [String],
|
||||
acl: [],
|
||||
id: {type: String, required: true}, // Id
|
||||
name: {type: String, required: true}, // The name of a role
|
||||
description: String, // Description
|
||||
roles: [String], // A role can be an aggregate of other roles
|
||||
users: [String], // A role contains a list of user ids
|
||||
|
||||
created: Date,
|
||||
lastUpdated: Date
|
||||
// Timestamps
|
||||
created: {type: Date, default: Date},
|
||||
modified: {type: Date, default: Date}
|
||||
}
|
||||
|
||||
module.exports = function(dataSource) {
|
||||
dataSource = dataSource || new require('loopback-data').ModelBuilder();
|
||||
var Role = dataSource.define('Role', RoleSchema);
|
||||
return Role;
|
||||
}
|
|
@ -22,6 +22,7 @@ var properties = {
|
|||
email: String,
|
||||
emailVerified: Boolean,
|
||||
verificationToken: String,
|
||||
|
||||
credentials: [
|
||||
'UserCredential' // User credentials, private or public, such as private/public keys, Kerberos tickets, oAuth tokens, facebook, google, github ids
|
||||
],
|
||||
|
@ -328,4 +329,4 @@ User.prototype.logout = function (fn) {
|
|||
* Setup the base user.
|
||||
*/
|
||||
|
||||
User.setup();
|
||||
User.setup();
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
- [app](#app)
|
||||
- [app.model(Model)](#app-appmodelmodel)
|
||||
- [app.models()](#app-appmodels)
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
- [loopback](#loopback)
|
||||
- [loopback.createDataSource(options)](#loopback-loopbackcreatedatasourceoptions)
|
||||
- [loopback.remoteMethod(Model, fn, [options]);](#loopback-loopbackremotemethodmodel-fn-options)
|
||||
>>>>>>> master
|
||||
- [DataSource](#datasource)
|
||||
- [dataSource.createModel(name, properties, settings)](#datasource-datasourcecreatemodelname-properties-settings)
|
||||
- [dataSource.operations()](#datasource-datasourceoperations)
|
||||
|
@ -76,6 +82,48 @@ assert.equal(models.length, 1);
|
|||
assert.equal(models[0].modelName, 'color');
|
||||
```
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
<a name="loopback"></a>
|
||||
# loopback
|
||||
<a name="loopback-loopbackcreatedatasourceoptions"></a>
|
||||
## loopback.createDataSource(options)
|
||||
Create a data source with a connector..
|
||||
|
||||
```js
|
||||
var dataSource = loopback.createDataSource({
|
||||
connector: loopback.Memory
|
||||
});
|
||||
assert(dataSource.connector());
|
||||
```
|
||||
|
||||
<a name="loopback-loopbackremotemethodmodel-fn-options"></a>
|
||||
## loopback.remoteMethod(Model, fn, [options]);
|
||||
Setup a remote method..
|
||||
|
||||
```js
|
||||
var Product = loopback.createModel('product', {price: Number});
|
||||
|
||||
Product.stats = function(fn) {
|
||||
// ...
|
||||
}
|
||||
|
||||
loopback.remoteMethod(
|
||||
Product.stats,
|
||||
{
|
||||
returns: {arg: 'stats', type: 'array'},
|
||||
http: {path: '/info', verb: 'get'}
|
||||
}
|
||||
);
|
||||
|
||||
assert.equal(Product.stats.returns.arg, 'stats');
|
||||
assert.equal(Product.stats.returns.type, 'array');
|
||||
assert.equal(Product.stats.http.path, '/info');
|
||||
assert.equal(Product.stats.http.verb, 'get');
|
||||
assert.equal(Product.stats.shared, true);
|
||||
```
|
||||
|
||||
>>>>>>> master
|
||||
<a name="datasource"></a>
|
||||
# DataSource
|
||||
<a name="datasource-datasourcecreatemodelname-properties-settings"></a>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
describe('loopback', function() {
|
||||
describe('loopback.createDataSource(options)', function(){
|
||||
it('Create a data source with a connector', function() {
|
||||
it('Create a data source with a connector.', function() {
|
||||
var dataSource = loopback.createDataSource({
|
||||
connector: loopback.Memory
|
||||
});
|
||||
|
@ -9,7 +9,7 @@ describe('loopback', 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});
|
||||
|
||||
Product.stats = function(fn) {
|
||||
|
@ -31,18 +31,4 @@ describe('loopback', function() {
|
|||
assert.equal(Product.stats.shared, true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loopback.memory([name])', function(){
|
||||
it('Get an in-memory data source. Use one if it already exists', function() {
|
||||
var memory = loopback.memory();
|
||||
assertValidDataSource(memory);
|
||||
var m1 = loopback.memory();
|
||||
var m2 = loopback.memory('m2');
|
||||
var alsoM2 = loopback.memory('m2');
|
||||
|
||||
assert(m1 === memory);
|
||||
assert(m1 !== m2);
|
||||
assert(alsoM2 === m2);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue