
Security News
OWASP 2025 Top 10 Adds Software Supply Chain Failures, Ranked Top Community Concern
OWASP’s 2025 Top 10 introduces Software Supply Chain Failures as a new category, reflecting rising concern over dependency and build system risks.
bookshelf-shield
Advanced tools

Form a protective shield around your bookshelf models. This module adds ACL-based authorization, and a CRUD API to bookshelf models.
As of right now, bookshelf-shield only can interact with the ACL module called relations Provides an intuitive interface for storing and querying Access Conrtol Lists. Relations is used to determine whether a user has been granted access to perform an action on the model.
This module utilizes ES6 features, including classes, arrow functions and Promises. As a result node 4.0.0+ is required.
relations.define('study', {
PI: ['read_Study'],
siteAdmin: [
'read_Study',
'update_Study',
'create_Study',
'delete_Study'
]
});
const models = {
Study: bookshelf.Model.extend({tableName: 'mrs_studies'}),
//...
};
const config = [
{
defaults: {
modelName: 'Study',
authKey: 'id',
aclContextName: 'study'
},
//optional action-specific configs here
},
//...
const shield = require('bookshelf-shield');
shield({
config: config,
acl: relations,
models: models
});
Once a model has been shielded, you can interact with it using a standard CRUD API, rather than the traditional fetch, save, destroy bookshelf API. This was implemented to more easily map to user's permissions.
const user = { username: 'dylan' };
const widget = new Widget({ color: 'blue' });
widget.create(user).then((newWidget) => {
//new Widget successfully created
}).catch((error) => {
//handle Error
});
const user = { username: 'dylan' };
const widget = new Widget({ id: '101' });
widget.read(user).then((newWidget) => {
//newWidget successfully read
}).catch((error) => {
//handle Error
});
const user = { username: 'dylan' };
const widget = new Widget();
widget.query({color: 'blue'});
widget.readAll(user).then((newWidgets) => {
//widgets successfully read into newWidgets collection
}).catch((error) => {
//handle Error
});
const user = { username: 'dylan' };
widget.set('color', 'red');
widget.update(user).then((newWidget) => {
//widget successfully updated
}).catch((error) => {
//handle Error
});
const user = { username: 'dylan' };
const widget = new Widget({ id: '101' });
widget.delete(user).then((newWidget) => {
//widgets successfully deleted (newWidget should now be empty)
}).catch((error) => {
//handle Error
});
const widget = new Widget({ id: '101' });
widget.bypass('fetch').then((newWidget) => {
//new Widget successfully created
}).catch((error) => {
//handle Error
});
Each model to be shielded requires a config object. During initialization, these config objects should be provided as an array. Here is an example config object:
module.exports = {
defaults: { // These defaults will be applied to all CRUD access methods, unless overridden below.
modelName: 'Study', // The name of the model: must match the key associated with the model in the models object passed to shield init.
authKey: 'id', // The property that should be used for authorization.
aclContextName: 'study' // The name of the ACL (relations) context to be used
},
create: { //specifying any CRUD method allows you to override the defaults secified above
authKey: 'siteId', //alternative auth key to be used when evaluating create access
aclContextName: 'site',
method: function validateSiteAdmin(user) {
// this is a cusom authentication method that will be invoked instead of the generic method.
// `this` refers to the current instance of the bookshelf model
const siteId = this.get('siteId');
// data stored on the shield can be accessed through the current object's constructor (the bookshelf Model).
const Model = this.constructor;
const aclContext = Model.shield.acl.site;
const aclQuestion = 'can ' +
user.username +
' create_Study from ' +
siteId;
if (!siteId) {
return Promise.reject(
new Error('Study has no valide siteId')
);
}
return aclContext(aclQuestion).then(function checkAuth(allow) {
let errorMsg;
if (allow) {
return allow;
}
errorMsg =
user.username +
' cannot create studies in Site ' +
siteId;
throw new Error(errorMsg);
});
}
}
};
Because there are no configuration objects specified for read, update and delete operations, those operations will be protected using the generic method (see below).
Unless a custom method is specified in the Model's config, the following generic method will be applied:
// Note options is the config for the current Model and action
function genericAuthMethod(user) {
const authVal = this.get(options.authKey);
const aclQuestion = 'can ' +
user.username +
' ' +
permissionName +
' from ' +
authVal;
const aclContext = options.acl[aclContextName];
//TODO: optimize to cache perms instead of loading from redis
return aclContext(aclQuestion).then(function checkAuth(allow) {
let errorMsg;
if (allow) {
return allow;
}
errorMsg = [
user.username,
'cannot',
permissionName.replace('_', ' '),
'in',
options.authKey,
'`' + authVal + '`'
].join(' ');
throw new AuthError(errorMsg);
});
See test/integration/main.js for a full example
Fully unit and integration tested
Please follow the MRN Javascript Style Guide (forked from AirBnB). Use grunt lint to check yo-self
FAQs
Access control list based authorization for bookshelf models
We found that bookshelf-shield demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OWASP’s 2025 Top 10 introduces Software Supply Chain Failures as a new category, reflecting rising concern over dependency and build system risks.

Research
/Security News
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.