diff --git a/example/hidden.js b/example/hidden.js new file mode 100644 index 0000000..b152d93 --- /dev/null +++ b/example/hidden.js @@ -0,0 +1,20 @@ +var loopback = require('loopback'); +var app = loopback(); +var explorer = require('../'); +var port = 3000; + +var User = loopback.Model.extend('user', { + username: 'string', + email: 'string', + sensitiveInternalProperty: 'string', +}, {hidden: ['sensitiveInternalProperty']}); + +User.attachTo(loopback.memory()); +app.model(User); + +var apiPath = '/api'; +app.use('/explorer', explorer(app, {basePath: apiPath})); +app.use(apiPath, loopback.rest()); +console.log('Explorer mounted at localhost:' + port + '/explorer'); + +app.listen(port); diff --git a/lib/model-helper.js b/lib/model-helper.js index b5c5724..d612489 100644 --- a/lib/model-helper.js +++ b/lib/model-helper.js @@ -37,6 +37,12 @@ var modelHelper = module.exports = { Object.keys(properties).forEach(function(key) { var prop = properties[key]; + // Hide hidden properties. + if (modelHelper.isHiddenProperty(def, key)) { + delete properties[key]; + return; + } + // Eke a type out of the constructors we were passed. prop = modelHelper.LDLPropToSwaggerDataType(prop); @@ -84,6 +90,12 @@ var modelHelper = module.exports = { return propType; }, + isHiddenProperty: function(definition, propName) { + return definition.settings && + Array.isArray(definition.settings.hidden) && + definition.settings.hidden.indexOf(propName) !== -1; + }, + // Converts a prop defined with the LDL spec to one conforming to the // Swagger spec. // https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#431-primitives diff --git a/lib/swagger.js b/lib/swagger.js index c886ac3..2bea1a1 100644 --- a/lib/swagger.js +++ b/lib/swagger.js @@ -102,7 +102,7 @@ function addRoute(app, uri, doc) { var host = headers.Host || headers.host; doc.basePath = req.protocol + '://' + host + initialPath; } - res.send(200, doc); + res.status(200).send(doc); }); } diff --git a/package.json b/package.json index cc05678..05eb9fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "loopback-explorer", - "version": "1.2.5", + "version": "1.2.6", "description": "Browse and test your LoopBack app's APIs", "main": "index.js", "scripts": { diff --git a/test/model-helper.test.js b/test/model-helper.test.js index 1a88b29..d196a26 100644 --- a/test/model-helper.test.js +++ b/test/model-helper.test.js @@ -117,10 +117,29 @@ describe('model-helper', function() { expect(defs).has.property('relatedModel'); }); }); + describe('hidden properties', function() { + it('should hide properties marked as "hidden"', function() { + var aClass = createModelCtor({ + visibleProperty: 'string', + hiddenProperty: 'string' + }); + aClass.ctor.definition.settings = { + hidden: ['hiddenProperty'] + }; + var def = modelHelper.generateModelDefinition(aClass.ctor, {}).testModel; + expect(def.properties).to.not.have.property('hiddenProperty'); + expect(def.properties).to.have.property('visibleProperty'); + }); + }); }); // Simulates the format of a remoting class. function buildSwaggerModels(model) { + var aClass = createModelCtor(model); + return modelHelper.generateModelDefinition(aClass.ctor, {}).testModel; +} + +function createModelCtor(model) { Object.keys(model).forEach(function(name) { model[name] = {type: model[name]}; }); @@ -132,7 +151,7 @@ function buildSwaggerModels(model) { } } }; - return modelHelper.generateModelDefinition(aClass.ctor, {}).testModel; + return aClass; } function buildSwaggerModelsWithRelations(model) {