Incorporating Agenda-UI into your sails project

Agenda is a powerful tool for task scheduling. Agenda-UI is a nice front-end to see what work Agenda has scheduled, and the status of previous jobs. Here is how to set up Agenda-UI in a sails.js project:

Initially I tried setting it up via custom middleware, like this:

// config/http.js
module.exports.http = {

  middleware: {
    // ...
  },

  // ...

  customMiddleware: function(app) {
    var Agenda = require('agenda');
    var agendaUI = require('agenda-ui');

    var mongoConnection = sails.config.connections.mongodb
    var agendaDbName = '/hrvst-agenda-jobs';
    // this split assumes mongoConnection.url looks like: 'mongodb://localhost:27017'
    var mongoURL = mongoConnection.url.split('mongodb://')[1] + agendaDbName;

    var agenda = new Agenda({
      db: {
        address: mongoURL
      }
    });

    app.use('/agenda-ui', agendaUI(agenda, {
      poll: 20000
    }));
  }
};

The problem I ran into was that I couldn't control access to this endpoint with this configuration. This runs regardless of policies. To allow access control, I ended up removing the code from config/http.js and doing this instead:

// config/routes.js
module.exports.routes = {  
  //...
  'GET /agenda-ui': 'AdminController.handleAgendaRequest',
  'GET /agenda-ui/*': 'AdminController.handleAgendaRequest'
};
// api/services/AdminController.js
var agendaUI = require('agenda-ui');  
var Agenda = require('agenda')  
var agendaServer;

module.exports = {  
  // ...
  handleAgendaRequest: function(req, res) {
    if (!agendaServer) {
      var mongoConnection = sails.config.connections.mongodb
      var agendaDbName = '/hrvst-agenda-jobs';

      // this code assumes mongoConnection.url looks like: 
      // 'mongodb://someurl:someportnumber'
      var mongoURL = mongoConnection.url.split('mongodb://')[1] +
        agendaDbName;

      var agenda = new Agenda({
        db: {
          address: mongoURL
        }
      });

      agendaServer = agendaUI(agenda, {
        poll: 20000
      });
    }

    // TODO find a way around this hackery
    if (_.contains(req.url, 'agenda-ui/')) {
      // get rid of agenda ui bit of request
      req.url = req.url.replace('/agenda-ui', '');
    }

    agendaServer.handle(req, res);
  }
};