Add more functions and tests for Application model

This commit is contained in:
Raymond Feng 2013-07-18 11:44:25 -07:00
parent 87e033f4d8
commit 836df227c6
5 changed files with 153 additions and 18 deletions

View File

@ -36,7 +36,7 @@ Application.create(data, function(err, data) {
}); });
Application.register('MyApp', 'My first mobile application', 'rfeng', function (err, result) { Application.register('rfeng', 'MyApp', {description: 'My first mobile application'}, function (err, result) {
console.log(result.toObject()); console.log(result.toObject());
result.resetKeys(function (err, result) { result.resetKeys(function (err, result) {

View File

@ -20,19 +20,32 @@ Factors to be authorized against:
Class level permissions, for example, Album Class level permissions, for example, Album
* model name: Album * model name: Album
* methods * 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
// comments
allow '*' to: ['find', 'read'] // read aka findById
allow 'user' to: ['create']
allow ['owner', 'admin'] to: '*'
// users only section URL/Route level permissions
allow: '*' to: ['find', 'read', 'create'] * url pattern
allow: 'owner' to: ['*.destroy', '*.save'] * application id
* ip addresses
* http headers
// scopes Map to oAuth 2.0 scopes
// URL level permissions
*/ */
var ACLSchema = {
model: String, // The model name
properties: [String], // A list of property names
methods: [String], // A list of methods
roles: [String], // A list of roles
permission: {type: String, enum: ['Allow', 'Deny']}, // Allow/Deny
status: String, // Enabled/disabled
created: Date,
modified: Date
}
// readAccess, writeAccess --> public, userId, role
module.exports = function(dataSource) {
dataSource = dataSource || new require('loopback-data').ModelBuilder();
var ACL = dataSource.define('ACL', ACLSchema);
return ACL;
}

View File

@ -1,3 +1,5 @@
var assert = require('assert');
// Authentication schemes // Authentication schemes
var AuthenticationSchemeSchema = { var AuthenticationSchemeSchema = {
scheme: String, // local, facebook, google, twitter, linkedin, github scheme: String, // local, facebook, google, twitter, linkedin, github
@ -33,7 +35,7 @@ var PushNotificationSettingSchema = {
var ApplicationSchema = { var ApplicationSchema = {
// Basic information // Basic information
id: {type: String, required: true}, // The id id: {type: String, required: true, generated: true, id: true}, // The id
name: {type: String, required: true}, // The name name: {type: String, required: true}, // The name
description: String, // The description description: String, // The description
icon: String, // The icon image url icon: String, // The icon image url
@ -79,9 +81,10 @@ var ApplicationSchema = {
var crypto = require('crypto'); var crypto = require('crypto');
function generateKey(hmacKey, algorithm) { function generateKey(hmacKey, algorithm, encoding) {
hmacKey = hmacKey || 'loopback'; hmacKey = hmacKey || 'loopback';
algorithm = algorithm || 'sha256'; algorithm = algorithm || 'sha256';
encoding = encoding || 'base64';
var hmac = crypto.createHmac(algorithm, hmacKey); var hmac = crypto.createHmac(algorithm, hmacKey);
var buf = crypto.randomBytes(64); var buf = crypto.randomBytes(64);
hmac.update(buf); hmac.update(buf);
@ -114,20 +117,59 @@ module.exports = function (dataSource) {
app.masterKey = generateKey('master'); app.masterKey = generateKey('master');
}; };
// Register a new application /**
Application.register = function (name, description, owner, cb) { * Register a new application
Application.create({name: name, description: description, owner: owner}, cb); * @param owner Owner's user id
* @param name Name of the application
* @param options Other options
* @param cb Callback function
*/
Application.register = function (owner, name, options, cb) {
assert(owner, 'owner is required');
assert(name, 'name is required');
if(typeof options === 'function' && !cb) {
cb = options;
options = {};
}
var props = {owner: owner, name: name};
for(var p in options) {
if(!(p in props)) {
props[p] = options[p];
}
}
Application.create(props, cb);
} }
/**
* Reset keys for the application instance
* @param cb
*/
Application.prototype.resetKeys = function(cb) { Application.prototype.resetKeys = function(cb) {
this.clientKey = generateKey('client'); this.clientKey = generateKey('client');
this.javaScriptKey = generateKey('javaScript'); this.javaScriptKey = generateKey('javaScript');
this.restApiKey = generateKey('restApi'); this.restApiKey = generateKey('restApi');
this.windowsKey = generateKey('windows'); this.windowsKey = generateKey('windows');
this.masterKey = generateKey('master'); this.masterKey = generateKey('master');
this.modified = new Date();
this.save(cb); this.save(cb);
} }
/**
* Reset keys for a given application by the appId
* @param appId
* @param cb
*/
Application.resetKeys = function(appId, cb) {
Application.findById(appId, function(err, app) {
if(err) {
cb && cb(err, app);
return;
}
app.resetKeys(cb);
});
}
return Application; return Application;
} }

View File

@ -1,6 +1,13 @@
exports.Model = require('./model');
exports.Email = require('./email');
exports.User = require('./user');
exports.Session = require('./session');
exports.Application = require('./application'); exports.Application = require('./application');
exports.ACL = require('./acl'); exports.ACL = require('./acl');
exports.Role = require('./role'); exports.Role = require('./role');
exports.Installation = require('./installation'); exports.Installation = require('./installation');

View File

@ -0,0 +1,73 @@
var models = require('../lib/models');
var loopback = require(('../'));
var assert = require('assert');
var dataSource = loopback.createDataSource('db', {connector: loopback.Memory});
var Application = models.Application(dataSource);
describe('Application', function () {
var registeredApp = null;
it('Create a new application', function (done) {
Application.create({owner: 'rfeng', name: 'MyApp1', description: 'My first mobile application'}, function (err, result) {
var app = result;
assert.equal(app.owner, 'rfeng');
assert.equal(app.name, 'MyApp1');
assert.equal(app.description, 'My first mobile application');
assert(app.clientKey);
assert(app.javaScriptKey);
assert(app.restApiKey);
assert(app.windowsKey);
assert(app.masterKey);
assert(app.created);
assert(app.modified);
done(err, result);
});
});
it('Register a new application', function (done) {
Application.register('rfeng', 'MyApp2', {description: 'My second mobile application'}, function (err, result) {
var app = result;
assert.equal(app.owner, 'rfeng');
assert.equal(app.name, 'MyApp2');
assert.equal(app.description, 'My second mobile application');
assert(app.clientKey);
assert(app.javaScriptKey);
assert(app.restApiKey);
assert(app.windowsKey);
assert(app.masterKey);
assert(app.created);
assert(app.modified);
registeredApp = app;
done(err, result);
});
});
it('Reset keys', function (done) {
Application.resetKeys(registeredApp.id, function (err, result) {
var app = result;
assert.equal(app.owner, 'rfeng');
assert.equal(app.name, 'MyApp2');
assert.equal(app.description, 'My second mobile application');
assert(app.clientKey);
assert(app.javaScriptKey);
assert(app.restApiKey);
assert(app.windowsKey);
assert(app.masterKey);
assert(app.clientKey !== registeredApp.clientKey);
assert(app.javaScriptKey !== registeredApp.javaScriptKey);
assert(app.restApiKey !== registeredApp.restApiKey);
assert(app.windowsKey !== registeredApp.windowsKey);
assert(app.masterKey !== registeredApp.masterKey);
assert(app.created);
assert(app.modified);
done(err, result);
});
});
});