Skip to content

Commit

Permalink
Add options to hide exposed fields and avoid http post rewriting
Browse files Browse the repository at this point in the history
  • Loading branch information
Unitech committed Nov 27, 2012
1 parent 445c0b7 commit 832a520
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 27 deletions.
1 change: 1 addition & 0 deletions .npmignore
@@ -0,0 +1 @@
node_modules/*
7 changes: 7 additions & 0 deletions README.md
Expand Up @@ -24,6 +24,9 @@ var PizzaSchema = new Schema({
}, },
size : { size : {
type : Number type : Number
},
password : { // You can hide it from read and write ! (check after)
type : String
} }
}); });
Expand All @@ -40,6 +43,10 @@ var angularBridge = new (require('angular-bridge'))(app, {
}); });
angularBridge.addRessource('pizzas', db.Pizza); angularBridge.addRessource('pizzas', db.Pizza);
//
// You can also hide fields
// angularBridge.addRessource('pizzas', db.Pizza, { hide : ['_id', 'password']});
//
``` ```


That's all for the backend, now in Angular : That's all for the backend, now in Angular :
Expand Down
95 changes: 73 additions & 22 deletions lib/index.js
Expand Up @@ -11,7 +11,7 @@ var util = require('util');
var AngularBridge = function(app, options, dontRegisterRoutes) { var AngularBridge = function(app, options, dontRegisterRoutes) {
this.app = app; this.app = app;
this.options = _.extend({ this.options = _.extend({
urlPath: '/' urlPrefix: '/',
}, options || {}); }, options || {});
this.resources = [ ]; this.resources = [ ];
this.registerRoutes(); this.registerRoutes();
Expand All @@ -28,32 +28,35 @@ module.exports = exports = AngularBridge;
*/ */
AngularBridge.prototype.registerRoutes = function() { AngularBridge.prototype.registerRoutes = function() {


this.app.all(this.options.urlPath + ':resourceName', this.collection()); this.app.all(this.options.urlPrefix + ':resourceName', this.collection());
this.app.get(this.options.urlPath + ':resourceName', this.collectionGet()); this.app.get(this.options.urlPrefix + ':resourceName', this.collectionGet());




this.app.post(this.options.urlPath + ':resourceName', this.collectionPost()); this.app.post(this.options.urlPrefix + ':resourceName', this.collectionPost());


this.app.all(this.options.urlPath + ':resourceName/:id', this.entity()); this.app.all(this.options.urlPrefix + ':resourceName/:id', this.entity());
this.app.get(this.options.urlPath + ':resourceName/:id', this.entityGet()); this.app.get(this.options.urlPrefix + ':resourceName/:id', this.entityGet());


// You can POST or PUT to update data // You can POST or PUT to update data
this.app.post(this.options.urlPath + ':resourceName/:id', this.entityPut()); this.app.post(this.options.urlPrefix + ':resourceName/:id', this.entityPut());
this.app.put(this.options.urlPath + ':resourceName/:id', this.entityPut()); this.app.put(this.options.urlPrefix + ':resourceName/:id', this.entityPut());


this.app.delete(this.options.urlPath + ':resourceName/:id', this.entityDelete()); this.app.delete(this.options.urlPrefix + ':resourceName/:id', this.entityDelete());
}; };


AngularBridge.prototype.addResource = function(singularName, model, pluralName, defaultSort) { AngularBridge.prototype.addResource = function(resource_name, model, options) {
pluralName = singularName; var resource = {
resource_name: resource_name,
model: model,
options : options || null
};


var resource = { singularName: singularName, pluralName: pluralName, model: model };
this.resources.push(resource); this.resources.push(resource);
}; };


AngularBridge.prototype.getResource = function(name) { AngularBridge.prototype.getResource = function(name) {
return _.find(this.resources, function(resource) { return _.find(this.resources, function(resource) {
return resource.pluralName === name; return resource.resource_name === name;
}); });
}; };


Expand All @@ -73,7 +76,7 @@ AngularBridge.prototype.redirect = function (address, req, res, next) {
res.send(address); res.send(address);
}; };


/** /**
* All entities rest functions have to go through this first. * All entities rest functions have to go through this first.
*/ */
AngularBridge.prototype.collection = function() { AngularBridge.prototype.collection = function() {
Expand All @@ -95,7 +98,8 @@ AngularBridge.prototype.collectionGet = function() {
} }


var self = this; var self = this;
var query = req.resource.model.find(); var hidden_fields = this.generateHiddenFields(req.resource);
var query = req.resource.model.find().select(hidden_fields);


query.exec(function(err, docs) { query.exec(function(err, docs) {
if (err) { if (err) {
Expand All @@ -114,7 +118,8 @@ AngularBridge.prototype.collectionPost = function() {
var self = this; var self = this;
if (!req.body) throw new Error('Nothing submitted.'); if (!req.body) throw new Error('Nothing submitted.');


var doc = new req.resource.model(req.body); var epured_body = this.epureRequest(req.body, req.resource);
var doc = new req.resource.model(epured_body);


doc.save(function(err) { doc.save(function(err) {
if (err) { error(err); return; } if (err) { error(err); return; }
Expand All @@ -123,6 +128,44 @@ AngularBridge.prototype.collectionPost = function() {
}, this); }, this);
}; };


/**
* Generate an object of fields to not expose
*/
AngularBridge.prototype.generateHiddenFields = function(resource) {
var hidden_fields = {};

if (resource.options == null || typeof resource.options['hide'] == 'undefined')
return {};

resource.options.hide.forEach(function(dt) {
hidden_fields[dt] = false;
});
return hidden_fields;
}


/** Sec issue
* Epure incoming data to avoid overwritte and POST request forgery
*/
AngularBridge.prototype.epureRequest = function(req_data, resource) {


if (resource.options == null || typeof resource.options['hide'] == 'undefined')
return req_data;

var hidden_fields = resource.options.hide;

_.each(req_data, function(num, key) {
_.each(hidden_fields, function(fi) {
if (fi == key)
delete req_data[key];
});
});

return req_data;
}


/* /*
* Entity request goes there first * Entity request goes there first
* It retrieves the resource * It retrieves the resource
Expand All @@ -131,9 +174,15 @@ AngularBridge.prototype.entity = function() {
return _.bind(function(req, res, next) { return _.bind(function(req, res, next) {
var self = this; var self = this;
if (!(req.resource = this.getResource(req.params.resourceName))) { next(); return; } if (!(req.resource = this.getResource(req.params.resourceName))) { next(); return; }


req.resource.model.findOne({ _id: req.params.id }, function(err, doc) { var hidden_fields = this.generateHiddenFields(req.resource);
console.log(err);
//
// select({_id : false}) invert the select process (hidde the _id field)
//
var query = req.resource.model.findOne({ _id: req.params.id }).select(hidden_fields);

query.exec(function(err, doc) {
if (err) { if (err) {
return res.send({ return res.send({
success : false, success : false,
Expand Down Expand Up @@ -175,19 +224,21 @@ AngularBridge.prototype.entityPut = function() {
var self = this; var self = this;


if (!req.body) throw new Error('Nothing submitted.'); if (!req.body) throw new Error('Nothing submitted.');

var epured_body = this.epureRequest(req.body, req.resource);


// Merge // Merge
_.each(req.body, function(value, name) { _.each(epured_body, function(value, name) {
req.doc[name] = value; req.doc[name] = value;
}); });





req.doc.save(function(err) { req.doc.save(function(err) {
console.log(req.doc);
if (err) { if (err) {
return res.send({success:false}); return res.send({success:false});
} }
return res.send({success:true}); return res.send(req.doc);
}); });


}, this); }, this);
Expand Down
28 changes: 23 additions & 5 deletions package.json
@@ -1,16 +1,34 @@
{ {
"name": "angular-bridge", "name": "angular-bridge",
"description": "Mongoose Express Angular ressources bridge", "author": {
"version": "1.0.0", "name": "as"
},
"description": "Mongoose Express Angular resources bridge",
"version": "0.1.1",
"main": "./index.js", "main": "./index.js",
"private": false, "private": false,
"dependencies": { "dependencies": {
"underscore": "1.x" "underscore": "1.x"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/" "url": "git://github.com/Alexandre-Strzelewicz/angular-bridge.git"
},
"homepage": "https://github.com/Alexandre-Strzelewicz/angular-bridge",
"readmeFilename": "README.md",
"_npmUser": {
"name": "tknew",
"email": "strzelewicz.alexandre@gmail.com"
},
"_id": "angular-bridge@0.1.1",
"devDependencies": {},
"optionalDependencies": {},
"engines": {
"node": "*"
}, },
"homepage": "", "_engineSupported": true,
"readmeFilename": "Readme.md" "_npmVersion": "1.1.24",
"_nodeVersion": "v0.6.19",
"_defaultsLoaded": true,
"_from": "angular-bridge@*"
} }

0 comments on commit 832a520

Please sign in to comment.