define([ 'underscore', 'marionette' ], function(_, Marionette) { 'use strict'; /** * SecureRouter * * This class is similar to the marionette Approuter except * that it verifies permissions before attempting to enter * into routes on the controller. * * This separates the security logic from the controller and provides * a syntax for us to configure SPA routes with security * * constructor options: * isAuthorized is for you to create your own validation logic, * return truthy for authorized, or falsy for unauthorized * isAuthorized: function(){return true;}; * * secureRoutes: { * '/secureRoute': { * authorized: 'securedControllerMethod', * unauthorized: 'unauthorizedHandlerOnController', * permissions: String || String[] || {} whatever you want, gets passed to isAuthorized * } * */ var SecureRouter = Marionette.AppRouter.extend({ constructor: function(options) { Marionette.AppRouter.prototype.constructor.apply(this, arguments); this.options = options || {}; this.isAuthorized = options.isAuthorized || function(){ return true; } var secureRoutes = Marionette.getOption(this, 'secureRoutes'); var controller = this._getController(); this.processSecureRoutes(controller, secureRoutes); }, // Internal method to process the `secureRoutes` for the // router, and turn them in to routes that trigger the // specified method on the specified `controller`. processSecureRoutes: function(controller, secureRoutes) { if (!secureRoutes) { return; } var routeNames = _.keys(secureRoutes).reverse(); // Backbone requires reverted order of routes _.each(routeNames, function(route) { this._addSecureRoute(controller, route, secureRoutes[route]); }, this); }, _addSecureRoute: function(controller, route, secureRoute) { var method = controller[secureRoute.authorized]; var unauthorizedRoute = controller[secureRoute.unauthorized]; if (!method) { throwError('Method "' + secureRoute.authorized + '" was not found on the controller'); } this.route(route, secureRoute.authorized, _.bind(function() { if (this.isAuthorized(secureRoute.permissions)) { method.apply(controller, arguments); } else { if (unauthorizedRoute) unauthorizedRoute.apply(controller, arguments); console.log('unauthorized'); } }, this)); } }); return SecureRouter; });