Data Structure & Privacy Rules: Users as Members of Multiple Teams/Accounts

Hi all! I’m looking for thoughts on setting up data structure and privacy rules for a B2B app that’s similar to Asana or Slack in that a User might be a “member” of several different accounts (in this case, organizations) which all have discrete sets of data.

Essentially, I’m looking for this type of setup:

  • An individual user can log in with her email address and then click on her profile picture in the header bar to switch between her own “account” and her various clients’ “accounts” to see/work on their data.
  • An organization (or the admin on that org account) can invite people to their “account” via email, and those individuals can join that “account,” even if they have own “accounts” or are members of other org “accounts.”

Note: I’m using the word “account” here but I’ve seen people use “teams” here on the forums, so I hope it’s clear that I mean the same thing.

Specifically, I’m trying to understand these things:

  • Do I need a separate data type for “Team” or “Account” that people are members/admins of?
  • How do I then make sure all members can see anything related to stuff connected to Teams they’re members of? Privacy Rules don’t seem to allow for this level of complexity. Do I need to set up a back-end workflow situation that automatically adds all members to a “members” list field on all the pertinent data types? Seems like this could get messy when new people are added or removed from a team (then again, I’m new to back-end workflows, so maybe this is easy?).

Would be grateful for any specific suggestions, reference articles, other posts, etc., to help me figure this out.

p.s. I’ve outlined my specific use case is in the first comment below, for reference. :smiley:

1 Like

App Overview (for reference)

The app is meant for grant writers to manage proposal language they’re writing or have written in the past. If you’re really bored, here’s a quick-ish walkthrough: https://youtu.be/e1CaVRYlbaE?t=1674

There are three types of users:

  1. Freelance grant writer (single-member “team”) with lots of clients & client projects
  2. Grant writing agency (multi-member “team” + occasional contractors) with lots of non-profit clients & client projects
  3. Non-profit organization (multi-member “team” + occasional contractors) with a single client (themselves) & lots of projects.

Consequential data types are:

Organizations

  • Could be a “nonprofit” or a “funder” (set via a “type” option set)
  • Users can create these
  • In a freelance or grant writing agency account, there will be several nonprofit Orgs (these are their clients), but in a non-profit account the only nonprofit Org in the system will be itself. Both types of accounts would have multiple funders.
  • Privacy: Users should only see the Orgs tied to the team they’re a member of and are logged into at that moment.
  • The Organization data type is sort of the main one. Everything else falls under this data type in one way or another.

Grants

  • This is a funding opportunity published by a “funder” Org, which a “nonprofit” Org can write a proposal for.
  • Tied to a single “funder” Org
  • Tied to any “nonprofit” Orgs that is applying for the grant (could be > 1)
  • Users can create these
  • Privacy: Users should only see the Opportunities tied to Organizations tied to the team they’re a member of and are logged into at that moment.

Proposals

  • This is a “project” that includes a list of many Language Items
  • Tied to the corresponding Opportunity (there might be several Proposals for a single Grant)
  • Tied to the “nonprofit” Org that it’s being written for
  • Users can create these
  • Privacy: Users should only see the Proposals tied to Organizations tied to the team they’re a member of and are logged into at that moment.

Language Items

  • These are the chunks of language that make up a Proposal
  • Tied to the corresponding Proposal
  • Users can create these
  • Privacy: Users should only see the Proposals tied to Organizations tied to the team they’re a member of and are logged into at that moment.

Language Topics

  • These are essentially tags for Language Items (i.e. Mission, Program Description, Evaluation Methods, etc.)
  • This data type is pre-populated, but users should be allowed to add their own as well (that’s why I’ve made it a data type instead of an option set)
  • Privacy: Users should only see the pre-populated Topics and any that have been created by members of the account they’re logged into.

I read through this quickly but couldn’t you try this:

  1. Create a list ‘team members’ (user accounts) on each organization

  2. Then create a privacy rule on organization: when this ‘organization’ ‘team members’ contains current user

And you should be able to create a similar rule for each topic, item, proposal and so on. This proposal’s organisation team members contains current user

With Bubble, there are usually a few ways to tackle something. The way I’d approach this is…

  • If you need groups of users to be members of distinct “teams” then yes I would set up a datatype for that. I imagine that users may have different levels of rights (admin, editor, view only). You can control for that either by having a user list for each level of rights within the team, or build in field(s) to mark a user’s rights.

  • Regarding privacy rules, if the User’s rights within the “team” control their rights on every other datatype, and it’s an exact match in every instance, then this presents a slight but manageable speedbump. In privacy rules I believe Bubble has trouble traversing more than 1 level deep (I don’t do it on my app but vaguely recall it being discussed in the forum). What I would do is to set up parallel fields on all the other datatypes that mirror the user fields in Team, then you can set up those privacy rules for each datatype. Then when your workflow adds/deletes Users to the team, have it do the same for the other relevant datatypes. This does not need to be a backend workflow (though if you find the workflow is slow on your page, move it to a backend workflow that executes when the user hits the “submit” button. It’s very simple to set up).

The advantage to the above is that if for whatever reason you need to get more granular in a user’s rights such that their rights on the team diverge from specific projects or content, you can do that since you are setting rights up and down the chain.

It’s possible someone else has posted a better solution in the entries on traversing multiple levels in privacy rules.

Hey @natvancleve :wave:! This was indeed what I was initially thinking…

… the problem I see is that anytime a user adds a new thing that requires privacy settings based on the team, they’d have to add all their team members manually to that thing. Can’t set up a workflow, because Bubble doesn’t know who the members of the team are, so there’s no single source of truth in terms of teams to reference.

@ed727 Your solution was my next thought, so really glad to know I was on the right track (or one that makes sense, at least). And if you say the workflows are simple, I’ll trust you. :slight_smile: Will let you know how I fare!

Also, for what it’s worth (for anyone else reading this), a fellow Bubbler sent me this, which goes into the data structure for a Slack clone. Haven’t watched it yet, but apparently has a solution that could work for this type of thing.

Hi, the workflow should be simple. Whatever step you’re using to add/delete the user to a team, just duplicate the step and change the datatype. So the user hits “submit” and executes the workflow which contains the string of steps.

A complication I thought of is what if a user is a member of two separate teams, and those teams happen to share the same organization. If that user gets deleted out of one team, the workflow would then delete them from the organization, yet they should remain in that organization because they still belong to a team that contains that organization. If this is a possibility, then in the workflow to delete someone from a team and the connected datatypes, you would need an “only when” in the workflow step which searches for this scenario, to ensure it doesn’t happen.

But hopefully that slack clone video (or I’m sure Bubble has a slack clone or similar tutorial) has a simpler / more elegant solution!