Skip to content

Commit

Permalink
fix(distinct): filter private/protected keys (2.x)
Browse files Browse the repository at this point in the history
Backported from PR#253
  • Loading branch information
Pier-Luc Gendreau committed Feb 26, 2016
1 parent 62295c9 commit 746defc
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 3 deletions.
2 changes: 1 addition & 1 deletion lib/express-restify-mongoose.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ var restify = function (app, model, opts) {
options.name = options.name.toLowerCase()
}

var ops = require('./operations')(model, options)
var ops = require('./operations')(model, options, excludedMap)

var uri_item = util.format('%s%s/%s', options.prefix, options.version, options.name)
if (uri_item.indexOf('/:id') === -1) {
Expand Down
21 changes: 20 additions & 1 deletion lib/operations.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
var _ = require('lodash')
var http = require('http')

module.exports = function (model, options) {
module.exports = function (model, options, excludedMap) {
var buildQuery = require('./buildQuery')(options)

function findById (filteredContext, id) {
Expand All @@ -10,7 +10,20 @@ module.exports = function (model, options) {
return filteredContext.findOne().and(byId)
}

function isDistinctExcluded (req) {
return options.filter.isExcluded(req._ermQueryOptions['distinct'], {
access: req.access,
excludedMap: excludedMap
})
}

function getItems (req, res, next) {
if (isDistinctExcluded(req)) {
req.erm.result = []
req.erm.statusCode = 200
return next()
}

options.contextFilter(model, req, function (filteredContext) {
var query = buildQuery(filteredContext.find(), req._ermQueryOptions).read(options.readPreference)

Expand Down Expand Up @@ -88,6 +101,12 @@ module.exports = function (model, options) {
}

function getItem (req, res, next) {
if (isDistinctExcluded(req)) {
req.erm.result = []
req.erm.statusCode = 200
return next()
}

options.contextFilter(model, req, function (filteredContext) {
buildQuery(findById(filteredContext, req.params.id), req._ermQueryOptions).lean(options.lean).read(options.readPreference).exec().then(function (item) {
if (!item) {
Expand Down
17 changes: 16 additions & 1 deletion lib/resource_filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var weedout = require('weedout')
/**
* Represents a filter.
* @constructor
* @param {Object} - Options
* @param {Object} opts - Options
* @param {Object} opts.model - Mongoose model
* @param {Object} opts.excludedMap {} - Filtered keys for related models
* @param {Object} opts.filteredKeys {} - Keys to filter for the current model
Expand Down Expand Up @@ -60,6 +60,21 @@ Filter.prototype.getExcluded = function (opts) {
return opts.access === 'protected' ? entry.private : entry.private.concat(entry.protected)
}

Filter.prototype.isExcluded = function (field, opts) {
if (!field) {
return false
}

opts = _.defaults(opts, {
access: 'public',
excludedMap: {},
filteredKeys: this.filteredKeys,
modelName: this.model.modelName
})

return this.getExcluded(opts).indexOf(field) >= 0
}

/**
* Removes excluded keys from a document.
* @memberof Filter
Expand Down
186 changes: 186 additions & 0 deletions test/integration/access.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,38 @@ module.exports = function (createFn, setup, dismantle) {
})
})

it('GET /Customers?distinct=age 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers', testUrl),
qs: {
distinct: 'age'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 1)
assert.equal(body[0], 12)
done()
})
})

it('GET /Customers?distinct=comment 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers', testUrl),
qs: {
distinct: 'comment'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 1)
assert.equal(body[0], 'Boo')
done()
})
})

it('GET /Customers/:id 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers/%s', testUrl, customer._id),
Expand All @@ -191,6 +223,38 @@ module.exports = function (createFn, setup, dismantle) {
})
})

it('GET /Customers/:id?distinct=age 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers/%s', testUrl, customer._id),
qs: {
distinct: 'age'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 1)
assert.equal(body[0], 12)
done()
})
})

it('GET /Customers/:id?distinct=comment 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers/%s', testUrl, customer._id),
qs: {
distinct: 'comment'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 1)
assert.equal(body[0], 'Boo')
done()
})
})

it('GET /Customers?populate=favorites.purchase.item,purchases.item,returns 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers', testUrl),
Expand Down Expand Up @@ -630,6 +694,37 @@ module.exports = function (createFn, setup, dismantle) {
})
})

it('GET /Customers?distinct=age 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers', testUrl),
qs: {
distinct: 'age'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 0)
done()
})
})

it('GET /Customers?distinct=comment 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers', testUrl),
qs: {
distinct: 'comment'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 1)
assert.equal(body[0], 'Boo')
done()
})
})

it('GET /Customers/:id 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers/%s', testUrl, customer._id),
Expand All @@ -650,6 +745,37 @@ module.exports = function (createFn, setup, dismantle) {
})
})

it('GET /Customers/:id?distinct=age 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers/%s', testUrl, customer._id),
qs: {
distinct: 'age'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 0)
done()
})
})

it('GET /Customers/:id?distinct=comment 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers/%s', testUrl, customer._id),
qs: {
distinct: 'comment'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 1)
assert.equal(body[0], 'Boo')
done()
})
})

it('GET /Customers?populate=favorites.purchase.item,purchases.item,returns 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers', testUrl),
Expand Down Expand Up @@ -1070,6 +1196,36 @@ module.exports = function (createFn, setup, dismantle) {
})
})

it('GET /Customers?distinct=age 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers', testUrl),
qs: {
distinct: 'age'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 0)
done()
})
})

it('GET /Customers?distinct=comment 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers', testUrl),
qs: {
distinct: 'comment'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 0)
done()
})
})

it('GET /Customers/:id 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers/%s', testUrl, customer._id),
Expand All @@ -1090,6 +1246,36 @@ module.exports = function (createFn, setup, dismantle) {
})
})

it('GET /Customers/:id?distinct=age 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers/%s', testUrl, customer._id),
qs: {
distinct: 'age'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 0)
done()
})
})

it('GET /Customers/:id?distinct=comment 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers/%s', testUrl, customer._id),
qs: {
distinct: 'comment'
},
json: true
}, function (err, res, body) {
assert.ok(!err)
assert.equal(res.statusCode, 200)
assert.equal(body.length, 0)
done()
})
})

it('GET /Customers?populate=favorites.purchase.item,purchases.item,returns 200', function (done) {
request.get({
url: util.format('%s/api/v1/Customers', testUrl),
Expand Down

0 comments on commit 746defc

Please sign in to comment.