What's the best way to model one person with multiple emails linked to multiple organizations with Meteor Accounts?

I’m making an app where a person can be part of multiple organizations. I’d like the person to be able to sign in with an email address and see all the organizations they have access to.

The person might have a different email address for each organization they have access to. They might also have one email address that is associated with multiple organizations.

What’s the best way to model this with Meteor’s Accounts?

Is it possible to have one Meteor.user and use the emails field to store the emails they can log in with? Then I suppose I’d need a way to associate one of their email addresses with their organization(s). Maybe something like this:

_id: ABC123,
emails: [
	 {address: jdoe@gmail.com, verified: true}, 
	{address: john.doe@acme.com, verified: true} 
],
organizations: [
	{_id: orgA._id, email: jdoe@gmail.com, displayName: jdoe, profilePicture: url}, 
	{_id: orgB._id, email: jdoe@gmail.com, displayName: jdoe, profilePicture: url},
	{_id: orgC._id, email: john.doe@acme.com, displayName: john, profilePicture: url}
]

Or is it better to have a Meteor.user for each email address they have and somehow allow them to link the user accounts? If so, how could you present a page where they can see all organizations for Meteor.user ABC123 and Meteor.user XYZ456 below:

_id: ABC123
emails: [
	 {address: jdoe@gmail.com, verified: true},
],
organizations: [_id: orgA._id, _id: orgB._id],
profile: {
	displayName: jdoe,
	profilePicture: url
}

_id: XYZ456
emails: [
	 {address: john.doe@acme.com, verified: true},
],
organizations: [_id: orgC._id],
profile: {
	displayName: john,
	profilePicture: url
}

Or maybe there’s another way that’s better than both ideas above…

2 Likes

Better to have only one user account per user. Then do not use the default email-based account handling by Meteor and create your own: https://docs.meteor.com/api/accounts-multi.html

On top of my head, I will create a new email collection and the relationship between the user collection and email collection is 1:many

Unless I’m mistaken, a user can already have multiple emails, the schema is something like this:

emails: [
  { address: "blah@blah.com", verified: true }
]

Multiple organisations is more complicated. A collection called organisations and an organisationIds: [...] property stored on each user will work at the basic level. But if you have documents that “belong” to an organisation, which should only be accessible to users who are also members of that organisation, then each document in these collections will also have to reference the organisationId. If you then need to have multiple roles, things get EXTRA complicated. The alanning:roles package helps here (each group is one organisation).

You are correct and I have a set up similar to what you’re referring to with the Organizations collection and hanging an organizationIds array off the user. I updated the original question with some more details about the models I’m currently debating between. Or maybe there’s another model that I’m not aware of that would be even better.

Appreciate any other insights you might have.

Why do you need to associate a specific email with an organisation? I’d definately say the top option is your better bet - using this schema you implicitly support the second option as well, e.g., while a user could have multiple emails and multiple organisations, a “person” could create multiple users, one per email. As such its less restrictive.

Why do you need to associate a specific email with an organisation?

I need to be able to send emails that are specific to an organization. For example, I need to send the person an email when someone in one of their organizations @mentions them. Right now, I have a Notifications collection that looks at the userId being mentioned and the organizationId so I’d need a way to determine which email address to use.

Maybe there’s another way?

hmm, thats a good question. I don’t think this is really a schema question though, more “how you want it to work”.

Personnally, I’d either have the user specify a primary email (which they can change) and send all emails to that address only. Or, I’d send all emails to all addresses.

However, if you really need to only send emails from the organisation to the correct address, then your schema seems fine. I would say though, if you have no need to “link” accounts, one user per email might be the way to go. e.g., if you have an exact one:one mapping between a user in an organisation and an email address. But if you need to handle the case that blah@blah.com is part of organisation1 and organisation2, then your first schema is for sure the way to go.

I think that a similar scene. I created a array field users in Organizations.

organizations collection com userId references =>

{_id: 1, name:"A", users: ["iwafsljdional23kl2"]}, 
{_id: 2, name:"B", users: ["ajdkf2o3ijsldosdfi"]},
{_id: 3, name:"C", users: ["iwafsljdional23kl2", "ajdkf2o3ijsldosdfi"]}

Then, you can permit access to users that are in organization user list.

Or maybe you could just extend the emails object in the Meteor.users collection to include an orgId (or an array if multiple are required). Something like:

...
emails: [
	{address: "jdoe@gmail.com", verified: true, orgId:["org1","org2"]}, 
	{address: "john.doe@acme.com", verified: true, orgId:["org3"]} 
],
...
1 Like