I'm working on a data dashboards application that needs a user permissions system for admins that allows them to easily show or hide different parts of the sitemap depending on who the user is.
The following is what I've come up with so far for what to do, but I'd like to hear what alternatives are out there, whether it's using a relational or non-relational database (or both).
I currently plan to have a users collection in my MongoDB database that would look like the following (auth is handled by Auth0 and that stuff doesn't need to be stored here):
[
{
_id: "e5jg",
username: "demo",
permissions: [ // ids in this array correspond to content ids in collection below
"lk4n",
"d30j",
"hjyut",
]
}
]
There would also be a dashboards collection that resembles the sitemap of the website. It'd look like the following (assume a given parent's children are never shared with another parent -- that happens to be the case in the application):
[
{
"_id": "9gtl",
"dashboard": "Restaurants",
"tools": [
{
"tool": "Management",
"pages": [
{
"page": "Market Strategy",
"cards": [
{
"card": "Top Priority Areas",
"contents": [
{
"_id": "lk4n",
"content": "Regional Map",
"dataSource": "topPriorityMapData"
},
{
"_id": "78ty",
"content": "Stakeholders",
"dataSource": "stakeholdersData"
}
]
}
]
}
]
}
]
}
]
I only associated users with permissions at the content level because I figure if someone has access to a given leaf node of the site map, they automatically have access to all of that node's ancestors. Ex: Because demo user with _id e5jg can see the Regional Map, he has access to the Top Priority Areas card, the Market Strategy page, and the Restaurants dashboard.
Whenever the permissions are changed (controllable through a not-yet-built UI interface), I plan to:
- update the users collection and
- programatically trigger a MongoDB aggregation pipeline to join the
userscollection and thedashboardscollection to create ausers.dashboardscollection that basically comprises sitemaps on a user-by-user basis. That would look like the following:
[
{
"username": "demo",
"dashboards": [
{
"dashboard": "Restaurants",
"tools": [
"tool": "Management",
"pages": [
{
"page": "Market Strategy",
"cards": [
{
"card": "Top Priority Areas",
"contents": [
{
"content": "Regional Map",
"dataSource": "topPriorityMapData"
},
]
}
]
}
]
]
}
]
}
]
The purpose of the users.dashboards collection would be so that when a user logs into the app, their specific sitemap can be fetched. The frontend would then programatically use that sitemap to generate the views that the user can see.
This approach feels off to me, especially with the crazy amount of $unwinding that would have to be done to flatten the dashboards collection before it can be joined to the users collection with $lookup. And then the crazy $grouping that would then have to happen to nest everything back together on a user-by-user basis.
The other problem is I need the data to be sorted despite all that $unwinding and re$grouping -- that is, the order in which children (dashboards, tools, pages, cards, contents) are returned to the frontend would ideally stay in the same order originally laid out in the dashboards collection. Ex: If there's a user that only has access to one page in a tool that has five pages, that one page should be removed from her sitemap but the other pages shouldn't get shuffled.
What would be a better way to approach building a user permissions system for this application?