Database Design for Role-Based Access System

Architectureauthorizationdatabase-designruby-on-rails

I'm considering different designs for a generic role library gem.

The first is based off the Rolify gem but with a has_many through: relationship instead of HABTM. HABTM tables are "headless" in ActiveRecord and cannot be queried directly which is a huge con.

class User < ApplicationRecord
  has_many :user_roles
  has_many :roles, through: :user_roles
end 

class UserRole < ApplicationRecord
  belongs_to :user
  belongs_to :role
end 

class Role < ApplicationRecord
  has_many :user_roles
  has_many :users, through: :user_roles
  belongs_to :resource, polymorphic: true
end 

Database diagram based off Rolify
But looking at this I can't really see any distinct advantages to having a separate table vs joining users to roles directly.

class User < ApplicationRecord
  has_many :roles
end 


class Role < ApplicationRecord
  belongs_to :user
end 

Diagram - roles as a join

Having a separate Role table lets you perhaps create "global" roles and then attach users to the role.

But is it really worth the performance hit and added complication vs letting the roles be unique per user?

Best Answer

Having a separate Role table lets you perhaps create "global" roles and then attach users to the role.

But is it really worth the performance hit and added complication vs letting the roles be unique per user?

Absolutely. The advantage of having preset/saved roles that are available to be assigned to different users is:

  1. Each role can be tested, so there is confidence in assigning it to a users.
  2. Duplicated data is more difficult to change.
  3. Easier for the admin to assign the role if it is already built. The record gets also gets added without the need to duplicate the details of the role.
  4. It's important to structure your data for performance, but joining 3 tables shouldn't be that much of a problem to fine-tune.

If you're going to build a generic role library, you probably need the data management flexibility provided by a RDBMS. The many-to-many relationship you're creating is fairly common and shouldn't be that difficult to work with.

Related Topic