Skip to content

Instantly share code, notes, and snippets.

@ebarault
Forked from drmikecrowe/DisableAllMethods.js
Last active January 24, 2018 09:43
Show Gist options
  • Save ebarault/d162892cd1873faad45faa0d08ddcdfd to your computer and use it in GitHub Desktop.
Save ebarault/d162892cd1873faad45faa0d08ddcdfd to your computer and use it in GitHub Desktop.
Loopback mixin to disable or expose methods
// based on https://github.com/strongloop/loopback/issues/651#issuecomment-259540469
'use strict';
module.exports = function (Model, options) {
if(Model && Model.sharedClass) {
var methodsToExpose = options.expose || [];
var methodsToHide = options.hide || [];
if (methodsToExpose.length) {
disableAllExcept(Model, methodsToExpose);
}
else if (methodsToHide.length) {
disableOnlyTheseMethods(Model, methodsToHide);
}
else {
disableAllExcept(Model);
}
}
/**
* Options for disableAllExcept
* @param Model -- The model to operate on
* @param methodsToExpose -- An array of method names
*/
function disableAllExcept (Model, methodsToExpose ) {
var hiddenMethods = [];
let explicitMethods, excludedMethods;
// wait for all models to be attached so sharedClass.methods() returns all methods
Model.on('attached', function (server) {
server.on('started', function () {
explicitMethods = getAclMethods(Model);
excludedMethods = methodsToExpose ? methodsToExpose.concat(explicitMethods) : explicitMethods;
Model.sharedClass.methods().forEach(disableMethod);
if ( hiddenMethods.length ) {
console.log( 'Hidding remote methods for model', Model.modelName, ':', hiddenMethods.join( ', ' ));
}
});
});
function disableMethod (method) {
var methodName = method.name;
if ( excludedMethods.indexOf(methodName) === -1 ) {
// append prefix 'prototype.' to method name if not static
methodName = method.isStatic? methodName: 'prototype.'+methodName;
hiddenMethods.push(methodName);
// disable method
Model.disableRemoteMethodByName(methodName);
}
}
}
/**
* Options for methodsToDisable:
* create, upsert, replaceOrCreate, upsertWithWhere, exists, findById, replaceById,
* find, findOne, updateAll, deleteById, count, updateAttributes, createChangeStream
* -- can also specify related method using prefixes listed above
* and the related model name ex for Account: (prototype.__updateById__followers, prototype.__create__tags)
* @param Model
* @param methodsToDisable array
*/
function disableOnlyTheseMethods (Model, methodsToDisable ) {
methodsToDisable.forEach( function (method) {
Model.disableRemoteMethodByName(method);
});
if ( methodsToDisable.length ) {
console.log( 'Hidding explicitly remote methods for model', Model.modelName, ':', methodsToDisable.join( ', ' ));
}
}
function getAclMethods (Model) {
let authorizedMethods = [];
const acls = Model.definition.settings.acls || [];
acls.forEach((acl) => {
if (acl.permission === 'ALLOW' && acl.property) {
if (Array.isArray(acl.property)) {
authorizedMethods = authorizedMethods.concat(acl.property);
}
else {
authorizedMethods.push(acl.property);
}
}
});
if (authorizedMethods.length) {
console.log('Exposing explicitly methods for model', Model.modelName, ':', authorizedMethods.join(', '));
}
return authorizedMethods;
}
};
{
"name": "Example",
"base": "PersistentModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {},
"mixins":{
"DisableAllMethods":{
"expose":[
"find",
"findById"
]
}
}
}
{
"name": "Example",
"base": "PersistentModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {},
"mixins":{
"DisableAllMethods":{
"hide":[
"create"
]
}
}
}
{
"name": "Example",
"base": "PersistentModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"name": {
"type": "string",
"required": true
}
},
"validations": [],
"relations": {},
"acls": [],
"methods": {},
"mixins":{
"DisableAllMethods":{}
}
}
'use strict';
var util = require('util');
var disableRemoteMethods = require('./disable-remote-methods');
module.exports = (0, util.deprecate) (
function (app) { return app.loopback.modelBuilder.mixins.define('disableRemoteMethods', disableRemoteMethods);},
'DEPRECATED: Use mixinSources, see https://github.com/.../loopback-import-mixin#mixinsources'
);
@tqtran7
Copy link

tqtran7 commented Jan 24, 2018

DisableAllMethods should actually be DisableRemoteMethods

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment