Create collection object dynamically

There are multiple collections in my project. Each collection is named after the username. For ex: “Jackdb” where Jack is the username. So I’m trying to load collection after the user login as shown below.

Accounts.onLogin(function(user){
CurrentDB = new Mongo.Collection(user+“db”);
}

But the above function runs perfect for the first time. But every time on every new page visit, I get an exception such as - Exception from Tracker afterFlush function: debug.js:41 Error: There is already a collection named “jackdb”. Because the collections are getting loaded everytime new page is visited for the same user. Is this a correct way to proceed or any other good way to load collections dynamically. Please help me on this one. I’ got stuck in it for a while

You’re storing the user based Collection in a global variable, so one really quick way to fix this is to first make sure the global isn’t set. So:

Accounts.onLogin(function (user) {
  if (!CurrentDB) {
    CurrentDB = new Mongo.Collection(user+"db");
  }
}

Then register an onLogout callback to remove your global Collection reference:

Account.onLogout(function () {
  CurrentDB = null;
});

Thank you @hwillson. But do you think is this the best way to do it dynamically. For Ex: Using Accounts.OnLogin (or) is there any other good way to solve this problem.

Why would you want to create an collections for every user? Just use Meteor.users Collection

I have a case where each user needs their own separate database (collection)

Could you explain why? I’m curious why

@henribeck. For example: Consider, I am providing service to various clients in the same field who compete each other. Therefore I need separate database for different clients for security purposes.

Mr.Hwillson, When I do CurrentDB = null (OR) delete CurrentDB; It’s only deleting the object and not the reference i guess. So if i fist login as jack - then it will create reference jackdb. After that if i login as sam - then also it works. But when i intially login as jack and logout and then again if login as jack it was throwing the same error - Error: There is already a collection named “jackdb” … Because it’s only deleting the object and not the reference. Any thoughts on this? Thanks in advance

(Note: This code runs on both server and client. so cannot use sessions)

Relying on different databases for security, especially when the naming convention is so obvious, is no more or less secure than using a single database with a key to “partition” collections for multi-tenancy. In both cases you will need to apply rigorous security checks. The only real difference is that a single database is much easier to work with.

2 Likes

Right - the Collection name is registered with the live data connection store, so this makes sense. There are ways you can remove it, but an easier approach would be to just swallow the error like:

Accounts.onLogin(function (user) {
  if (!CurrentDB) {
    try {
      CurrentDB = new Mongo.Collection(user+"db");
    } catch (error) {
      // This is okay!
    }
  }
}

That being said, I’m just following up on the how to get it working part. As @robfallows mentioned, there are better approaches for handling this from a security standpoint.

@hwillson & @robfallows - Thanks for your valuable comments.

@robfallows - I will trying looking that way. Thanks for the heads up

@hwillson - Out of curiosity I would like to know the approach to do so. Because I searched in lot of places. But couldn’t able to find one solution for it. If you can share your approach, that would be great! Thank you very much

1 Like

@hwillson - I again fall into similar problem

CurrentDB = new Mongo.Collection(‘jackdb’);

I want to to delete both the CurrentDB and jackdb reference. As you have already mentioned there is a way to do it, can you please help me in deleting the jackdb reference. This time I couldn’t able to perform insert operation on the db. Therefore I want to delete it

**//Code which runs after new user is created, If the user is in admin role I'm inserting his/her ID into collection**
var postSignUp = function(userId, info){
  if (info.profile.roles == "admin"){
    CurrentDB.insert({user_id: userId});
  }
}
AccountsTemplates.configure({
  postSignUpHook: postSignUp
});

**//Getting Error on creating a new user**
Exception while invoking method 'ATCreateUserServer' TypeError: CurrentDB.insert is not a function
     at postSignUp (server/Accounts.js:9:13)
     at [object Object].Meteor.methods.ATCreateUserServer (packages/useraccounts_core/lib/server_methods.js:113:1)
     at maybeAuditArgumentChecks (packages/ddp-server/livedata_server.js:1711:12)
     at packages/ddp-server/livedata_server.js:711:19
     at [object Object]._.extend.withValue (packages/meteor/dynamics_nodejs.js:56:1)
     at packages/ddp-server/livedata_server.js:709:40
     at [object Object]._.extend.withValue (packages/meteor/dynamics_nodejs.js:56:1)
     at packages/ddp-server/livedata_server.js:707:46
     at Session.method (packages/ddp-server/livedata_server.js:681:23)
     at packages/ddp-server/livedata_server.js:551:43