JSFiddle - React, Tailwind, and code Playground
by Jon Jaques
HTML
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.10/backbone-min.js"></script>
<a href="#list">Pages List</a>
<a href="#list/1">Page 1 Detail</a>
<a href="#create">Create Page</a>
<br>
<br>
<div id="log"><strong>LOG</strong></div>
CSS
#log {
font-family: Menlo, monospaced;
}
#log strong {
font-weight: bold;
border-bottom: 1px solid black;
}
JavaScript
var userPermissions = {
'api/pages': {
create: true, read: true, update: false, destroy: false
},
'api/links': {
create: true, read: true, update: true, destroy: false
}
};
var PermRouter = Backbone.Router.extend({
authorize: function(namedRoute) {
if (this.permissions && this.collections) {
var perms = this.permissions[namedRoute];
if (!perms) {
perms = {};
// if nothing is specified for a particular route, we
// assume read access required for all registered controllers.
_.each(_.keys(this.collections), function(key) {
return perms[key] = [];
});
}
var authorized = _.chain(perms)
.map(function(reqPerms, collKey) {
var collection = this.collections[collKey],
permKey = _.result(collection, 'url');
// We implicitly check for 'read'
if (!_.contains('read')) {
reqPerms.push('read');
}
return _.every(reqPerms, function(ability) {
return userPermissions[permKey][ability];
});
}, this)
.every(function(auth){ return auth; })
.value();
return authorized;
}
return true;
},
route: function(route, name, callback) {
if (!callback) { callback = this[name]; }
var action = function() {
// allow anonymous routes through auth check.
if (!name || this.authorize(name)) {
callback.apply(this, arguments);
} else {
this.trigger('denied');
}
}
Backbone.Router.prototype.route.call(this, route, name, action);
return this;
}
});
var PagesCollection = Backbone.Collection.extend({
url: 'api/pages'
});
var LinksCollection = Backbone.Collection.extend({
url: 'api/links'
});
var PagesController = PermRouter.extend({
// Setup
routes: {
'list' : 'list',
'list/:id' : 'detail',
'create' : 'create'
},
// Collection are registered so we can
// keep...