I have User, Account, and Role models. Role stores the relationship type between Account and User.
I left attr_accessible
in Role
blank to prevent a mass assignment vulnerability (otherwise attackers could change the role type--owner, admin, etc...--, account or user ids).
But what if an admin wants to change a subscriber to a moderator? This would raise a mass assignment security exception:
user = User.find(params[:id])
role = user.roles.find_by_account_id(params[:account_id])
role.type = "admin"
How do I solve this? One way is to create a separate model to represent each role (owner, admin, moderator, subscriber) and use an STI type pattern. This lets me do:
user = User.find(params[:id])
user.moderatorship.build(account_id: params([:account_id])
Tedious! I would have to create Onwership, Moderatorship, Subscribership, etc..., and have them inherit from Role. If I want to stick to a single Role model, how can I have dynamic roles without exposing myself to mass assignment vulnerability?
Bonus question: Should I use a User has_many roles (user can have a single record for each role type) or has_one role (user can only have one role record, which must be toggled if their role changes) pattern?
class User < ActiveRecord::Base
attr_accessible :name, :email
has_many :accounts, through: roles
end
class Account < ActiveRecord::Base
attr_accessible :title
has_many :users, through: roles
end
class Role < ActiveRecord::Base
attr_accessible
belongs_to: :user
belongs_to: :account
end
You can use "as" with attr_accessible to have different assignment abilities. For instance,
attr_accessible :type, as: :admin
Then, when you do mass assignment, you can do something like
@role.update_attributes {type: :moderator}, as: :admin # Will update type
@role.update_attributes {type: :moderator} # Will not update type