Allow glob-style patterns for remote options
This commit is contained in:
parent
df87c17c08
commit
724a7d1928
|
@ -533,9 +533,9 @@ function configureModel(ModelCtor, config, app) {
|
||||||
config = extend({}, config);
|
config = extend({}, config);
|
||||||
config.dataSource = dataSource;
|
config.dataSource = dataSource;
|
||||||
|
|
||||||
setSharedMethodSharedProperties(ModelCtor, app, config);
|
|
||||||
|
|
||||||
app.registry.configureModel(ModelCtor, config);
|
app.registry.configureModel(ModelCtor, config);
|
||||||
|
|
||||||
|
setSharedMethodSharedProperties(ModelCtor, app, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSharedMethodSharedProperties(model, app, modelConfigs) {
|
function setSharedMethodSharedProperties(model, app, modelConfigs) {
|
||||||
|
@ -568,15 +568,38 @@ function setSharedMethodSharedProperties(model, app, modelConfigs) {
|
||||||
|
|
||||||
// set sharedMethod.shared using the merged settings
|
// set sharedMethod.shared using the merged settings
|
||||||
var sharedMethods = model.sharedClass.methods({includeDisabled: true});
|
var sharedMethods = model.sharedClass.methods({includeDisabled: true});
|
||||||
|
|
||||||
|
// re-map glob style values to regular expressions
|
||||||
|
var tests = Object
|
||||||
|
.keys(settings)
|
||||||
|
.filter(function(setting) {
|
||||||
|
return settings.hasOwnProperty(setting) && setting.indexOf('*') >= 0;
|
||||||
|
})
|
||||||
|
.map(function(setting) {
|
||||||
|
// Turn * into an testable regexp string
|
||||||
|
var glob = escapeRegExp(setting).replace(/\*/g, '(.)*');
|
||||||
|
return {regex: new RegExp(glob), setting: settings[setting]};
|
||||||
|
}) || [];
|
||||||
sharedMethods.forEach(function(sharedMethod) {
|
sharedMethods.forEach(function(sharedMethod) {
|
||||||
// use the specific setting if it exists
|
// use the specific setting if it exists
|
||||||
var hasSpecificSetting = settings.hasOwnProperty(sharedMethod.name);
|
var methodName = sharedMethod.isStatic ? sharedMethod.name : 'prototype.' + sharedMethod.name;
|
||||||
|
var hasSpecificSetting = settings.hasOwnProperty(methodName);
|
||||||
if (hasSpecificSetting) {
|
if (hasSpecificSetting) {
|
||||||
sharedMethod.shared = settings[sharedMethod.name];
|
if (settings[methodName] === false) {
|
||||||
} else { // otherwise, use the default setting if it exists
|
sharedMethod.sharedClass.disableMethodByName(methodName);
|
||||||
var hasDefaultSetting = settings.hasOwnProperty('*');
|
} else {
|
||||||
if (hasDefaultSetting)
|
sharedMethod.shared = true;
|
||||||
sharedMethod.shared = settings['*'];
|
}
|
||||||
|
} else {
|
||||||
|
tests.forEach(function(glob) {
|
||||||
|
if (glob.regex.test(methodName)) {
|
||||||
|
if (glob.setting === false) {
|
||||||
|
sharedMethod.sharedClass.disableMethodByName(methodName);
|
||||||
|
} else {
|
||||||
|
sharedMethod.shared = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -585,6 +608,11 @@ function clearHandlerCache(app) {
|
||||||
app._handlers = undefined;
|
app._handlers = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanitize all RegExp reserved characters except * for pattern gobbing
|
||||||
|
function escapeRegExp(str) {
|
||||||
|
return str.replace(/[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g, '\\$&');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen for connections and update the configured port.
|
* Listen for connections and update the configured port.
|
||||||
*
|
*
|
||||||
|
|
|
@ -739,4 +739,141 @@ describe('loopback', function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Hiding shared methods', function() {
|
||||||
|
var app;
|
||||||
|
|
||||||
|
beforeEach(setupLoopback);
|
||||||
|
|
||||||
|
it('hides remote methods using fixed method names', function() {
|
||||||
|
var TestModel = app.registry.createModel(uniqueModelName);
|
||||||
|
app.model(TestModel, {
|
||||||
|
dataSource: null,
|
||||||
|
methods: {
|
||||||
|
staticMethod: {
|
||||||
|
isStatic: true,
|
||||||
|
http: {path: '/static'},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
remoting: {
|
||||||
|
sharedMethods: {
|
||||||
|
staticMethod: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
var publicMethods = getSharedMethods(TestModel);
|
||||||
|
|
||||||
|
expect(publicMethods).not.to.include.members([
|
||||||
|
'staticMethod',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hides remote methods using a glob pattern', function() {
|
||||||
|
var TestModel = app.registry.createModel(uniqueModelName);
|
||||||
|
app.model(TestModel, {
|
||||||
|
dataSource: null,
|
||||||
|
methods: {
|
||||||
|
staticMethod: {
|
||||||
|
isStatic: true,
|
||||||
|
http: {path: '/static'},
|
||||||
|
},
|
||||||
|
instanceMethod: {
|
||||||
|
isStatic: false,
|
||||||
|
http: {path: '/instance'},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
remoting: {
|
||||||
|
sharedMethods: {
|
||||||
|
'prototype.*': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
var publicMethods = getSharedMethods(TestModel);
|
||||||
|
|
||||||
|
expect(publicMethods).to.include.members([
|
||||||
|
'staticMethod',
|
||||||
|
]);
|
||||||
|
expect(publicMethods).not.to.include.members([
|
||||||
|
'instanceMethod',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hides all remote methods using *', function() {
|
||||||
|
var TestModel = app.registry.createModel(uniqueModelName);
|
||||||
|
app.model(TestModel, {
|
||||||
|
dataSource: null,
|
||||||
|
methods: {
|
||||||
|
staticMethod: {
|
||||||
|
isStatic: true,
|
||||||
|
http: {path: '/static'},
|
||||||
|
},
|
||||||
|
instanceMethod: {
|
||||||
|
isStatic: false,
|
||||||
|
http: {path: '/instance'},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
remoting: {
|
||||||
|
sharedMethods: {
|
||||||
|
'*': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
var publicMethods = getSharedMethods(TestModel);
|
||||||
|
|
||||||
|
expect(publicMethods).to.be.empty();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hides methods for related models using globs', function() {
|
||||||
|
var TestModel = app.registry.createModel(uniqueModelName);
|
||||||
|
var RelatedModel = app.registry.createModel(uniqueModelName);
|
||||||
|
app.dataSource('test', {connector: 'memory'});
|
||||||
|
app.model(RelatedModel, {dataSource: 'test'});
|
||||||
|
app.model(TestModel, {
|
||||||
|
dataSource: 'test',
|
||||||
|
relations: {
|
||||||
|
related: {
|
||||||
|
type: 'hasOne',
|
||||||
|
model: RelatedModel,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
remoting: {
|
||||||
|
sharedMethods: {
|
||||||
|
'*__related': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
var publicMethods = getSharedMethods(TestModel);
|
||||||
|
|
||||||
|
expect(publicMethods).to.not.include.members([
|
||||||
|
'prototype.__create__related',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupLoopback() {
|
||||||
|
app = loopback({localRegistry: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSharedMethods(Model) {
|
||||||
|
return Model.sharedClass
|
||||||
|
.methods()
|
||||||
|
.filter(function(m) {
|
||||||
|
return m.shared === true;
|
||||||
|
})
|
||||||
|
.map(function(m) {
|
||||||
|
return m.stringName.replace(/^[^.]+\./, ''); // drop the class name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue