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
users
collection and thedashboards
collection to create ausers.dashboards
collection 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 $unwind
ing 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 $group
ing 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 $unwind
ing and re$group
ing -- 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?