Let's say there is a a system and you have three entities:
- User
- Team (group of users)
- Role
And you want to setup up some permission relationships, with the flexibility in the database anyway, to say:
- User X can change permissions of User Y
- User X can change permissions of Team Y
- User X can change permissions of Role Y
- Team X can change permissions of Role Y
- Team X can change permissions of Team Y
- Role X can change permissions of Team Y
- Role X can change permissions of Role Y
With a similar scenario, I currently have a table with the following schema:
- SubjectType (User | Team | Role)
- SubjectId (integer - not foreign key)
- TargetType (User | Team | Role)
- TargetId (integer - not foreign key)
This is allows all the relationships to be specified in one place, however, as there are no specified relationships, it has the problem:
- Role A is configured with access to teams with team IDs X,Y,Z
- Teams Y and Z are removed with no errors elsewhere
- When querying targets for Role A, the team IDs Y and Z are still returned.
As it stands, I can see two options, each with compromise involved (pros = +, cons = -):
1. Leave as is with data in one place but remove orphaned permission relationships when the entity is removed.
- (+) Keeps one table and single query simplicity and manually remove team permission entries when a team is removed
- (-) Will require 3 manual deletion operations (User | Team | Role). Whilst there would be a single deletion function where this could take place in a repeatable manner, there is no hard and fast guarantree
2. Specify each relationship in its own table.
- (+) ACID guarantee will prevent entries becoming orphaned
- (-) Much greater table verbosity, 7-9 tables for basically the same thing
- (-) More queries, more joins (specially if using class table inheritance)
I'm kind of leaning towards the second option with the thought of adding the extra complexity below and abstracting it into single access functions and am thinking that is worth the extra work (involves a bit of a rewrite).
However, I am wondering if there is a different option I have missed, or if there are some strong experienced based recommendations on this problem?
Using SQL Server 2012 with this setup but I imagine this to be a generic SQL / database issue.