Avoiding a mass assignment security flaw while assigning user roles

I have User, Account, and Role models. Role stores the relationship type between Account and User.

I know that attr_accessible should be blank in the Role model to prevent attackers from changing either the role type (owner, admin, moderator, subscriber), 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 modify a role type without a having a mass assignment security flaw?

Also, I would appreciate an answer to this: 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?

Models:

class User < ActiveRecord::Base

attr_accessible :name, :email

has_many :accounts, through: roles

end

class Account < ActiveRecord::Base

attr_accessible :title

belongs_to :user

end

class Role < ActiveRecord::Base

attr_accessible

end

After doing my own research, it looks like I can approach this two ways:

  1. Episode 237, Railscasts, Dynamic att_accessible, overriding mass_assignment_authorizer

  2. I can use attr_accessible role, as: :admin

I would appreciate it if anyone can elaborate on the merits of either approach.

I have User, Account, and Role models. Role stores the relationship type
between Account and User.

I know that *attr_accessible* should be blank in the Role model to prevent
attackers from changing either the role type (owner,
admin, moderator, subscriber), 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"

No it wouldn't. You can always to foo.bar = 'baz', whether or not the
bar attribute is accessible or not. What attr_accessible controls is
what would happen if you did

role.update_attributes(params[:role])

Fred