2

So I have a node express app using nano with couchdb as the backend, this is running fine. I'm now looking to learn how I would expand it to multiple organisations.

So for instance, a wildcard DNS record allowing https://customername.myapp.com for each customer. I will then check the req.headers.host in the main database, along with checking session cookies etc in each request.

What I'm struggling to get my head around though, is how the backend will work. I think I understand that the correct method is to use a database for each organisation, and copy the design from a template database.

But if this is correct, I don't understand how this translates to my code using nano. I currently use this:

var dbname = 'customer1';
var nano = require('nano')(config.dbhost);
var couch = nano.db.use(dbname);

and then in my functions:

couch.get(somevalue, function(err, body) { 
   // do stuff
});

But that won't work when the database itself is a variable. Should I be looking at moving the query to a lower level, eg nano.get('dbname', query... or something else?

EDIT

Hoping someone can give me an example of how to use middleware to change the database name dependent on the host header. I have this so far:

app.use(function(req,res,next) {
    var couch = nano.db.use(req.header.host);
    next();
});

But I don't understand how to pass the couch object through ('couch' is unknown in the rest of my routing). I have tried passing it back through in the 'next(couch)' but this breaks it...

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
user4893295
  • 533
  • 6
  • 25
  • Even if you use a wildcard DNS, in the end, you will always query the CouchDB database at myapp.com ? – Alexis Côté Aug 09 '17 at 13:24
  • Yes, the wildcard DNS was just to give an idea of how the app will work, but the question is really about multiple databases on a single couch server – user4893295 Aug 09 '17 at 13:30

1 Answers1

1

First of all, I'd recommend to have the application working with a single organization. If you want to have 1 database per organization, it should be fairly easy to add more organizations later.

I would have a master database and a template database. The master database would be a database listing the existing organization in the service with some metadata. This is what NodeJS would query first to know from which database you need to fetch data.

The template database would be used to sync design objects to existing or new organizations. You can technically have old organization with old design and they will still work as the data will be consistent.

In your case, the line you're looking for is this one:

var couch = nano.db.use(dbname);

When you know which database to query, you'll have to create a new nano object for each dbname you need.

You can know which database to use directly if the databases are named after domain name or project name as long as the information is present in the request headers/session.

Anyhow, it's a really wide question that can be answered in many ways and there is no particularly best way of doing things.

You could technically have all of your organization in one database if that works for you. Splitting database allow you to isolate a bit things and make use of ACL but you could technically make database not only for organization but for more specific things.

For example, I made a painting program that stores projects per database and allow people to cooperatively draw on a canvas. Database ACL allowed me to restrict access to people invited in a project. My NodeJS server was techically used only for WebSockets and the webapp was able to communicate with the couchDB directly without NodeJS.

Loïc Faure-Lacroix
  • 13,220
  • 6
  • 67
  • 99
  • The model I'm looking at is a typical sign up, like slack etc, where you join as an organisation, and then manage your own users. If I were to create an object for each organisation that would get very messy, and I couldn't reuse code. But equally, if I store it all in one database, suddenly my views etc won't work, as they only query on one key, such as the username, so then all my design wouldn't work. I don't get what's missing here to be honest, I always assumed that my model would be quite a common scenario.. – user4893295 Aug 09 '17 at 18:30
  • I'm pretty sure you can always reuse code no matter what design you choose. If you store all in one database, you'll have to store to which organization each object belong and emit the key for the organization in your views or something similar. – Loïc Faure-Lacroix Aug 10 '17 at 10:08
  • I don't see what is your concerns. On your backend, you require nano with the host information (it's the same for each user). Then, what you could do is add a middleware before your access in order to get the information from the request headers. From there, you can create the database object and pass it with the orignal request to the next handler (your target API). If you don't want to recreate multiples variables of the nano database, you can always keep these instance in a an object (as a singleton). – Alexis Côté Aug 10 '17 at 13:24
  • 1
    @AlexisCôté there shouldn't be any concern about nano variables either, those aren't even active sockets or anything. As far as I know they only hold url and credentials. – Loïc Faure-Lacroix Aug 10 '17 at 15:30
  • @AlexisCôté I think that sounds like a solution to me... I guess the problem is that I'm still trying to get my head around creating middleware. If you could give me an example as you describe, I will select it as the answer? – user4893295 Aug 10 '17 at 17:52
  • @user4893295 Are you using express as your backend? – Alexis Côté Aug 10 '17 at 22:27
  • Yes, express, express-session & nano – user4893295 Aug 11 '17 at 10:59
  • Sorry, should probably have tagged @AlexisCôté in that last comment – user4893295 Aug 14 '17 at 09:01