Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I store site configuration in MongoDB for a NodeJS Express App?

I have an Expressjs app running on NodeJS 0.8.8 using MongoDB and the Jade template language, and I'd like to allow the user to configure many of the site-wide presentation options such as the page titles, logo image, etc.

How can I store these configuration options in a mongoDB database so that I can read them upon application startup, manipulate them while the app is running, and display them in the jade templates?

Here's my general app setup:

var app = module.exports = express();
global.app = app;
var DB = require('./accessDB');
var conn = 'mongodb://localhost/dbname';
var db;

// App Config
app.configure(function(){
   ...
});

db = new DB.startup(conn);

//env specific config
app.configure('development', function(){
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
}); // etc

// use date manipulation tool moment
app.locals.moment = moment;

// Load the router
require('./routes')(app);

So Far I have created a model called "Site" for the "siteConfig" collection and I have a function called getSiteConfig in accessDB.js that runs Site.find()... to retrieve the fields in the one document in the collection.

So this is the crux of the question: how should I inject those fields into the express app so that they can be used throughout the site? Should I follow the same pattern I used with the moment.js tool? Like this:

db.getSiteConfig(function(err, siteConfig){
  if (err) {throw err;}
  app.locals.siteConfig = siteConfig;
});

If not, what would be the correct way to do this?

Thanks!

like image 631
tutley Avatar asked Sep 14 '12 18:09

tutley


People also ask

How do I create a schema in MongoDB using node JS?

import mongoose from 'mongoose'; const Schema = mongoose. Schema; const postSchema = new Schema({ title: { type: 'String', required: true }, content: { type: 'String', required: true }, slug: { type: 'String', required: true } }); let Post = mongoose. model('Post', postSchema);


1 Answers

Consider using express middleware for loading site config.

app.configure(function() {
  app.use(function(req, res, next) {
    // feel free to use req to store any user-specific data
    return db.getSiteConfig(req.user, function(err, siteConfig) {
      if (err) return next(err);
      res.local('siteConfig', siteConfig);
      return next();
    });
  });
  ...
});

Throwing an err is a realy bad idea because it will crash your application. So use next(err); instead. It will pass your error to express errorHandler.

If you already authenticated your user (in previous middleware, for example) and stored its data into req.user, you can use it to get the right config from db.

But be careful with using your getSiteConfig function inside of express middleware because it will pause express from further processing of the request until the data is received.

You shall consider caching siteConfig in express session to speedup you application. Storing session-specific data in express session is absolutely safe because there is no way for user to get access to it.

The following code demonstrates the idea of caching siteConfig in express sessionn:

app.configure(function() {
  app.use(express.session({
    secret: "your sercret"
  }));
  app.use(/* Some middleware that handles authentication */);
  app.use(function(req, res, next) {
    if (req.session.siteConfig) {
      res.local('siteConfig', req.session.siteConfig);
      return next();
    }
    return db.getSiteConfig(req.user, function(err, siteConfig) {
      if (err) return next(err);
      req.session.siteConfig = siteConfig;
      res.local('siteConfig', siteConfig);
      return next();
    });
  });
  ...
});
like image 148
Leonid Beschastny Avatar answered Oct 11 '22 00:10

Leonid Beschastny