accepts nest attributes & attr_accessible

Hey, Just going over some of the accepts of accepts_nested_attributes_for & attr_accessible.

I found with the form and models I've been working on it would be great if I could use accepts_nested_attribtues but I want to propose my case where I just can't make it work. And for secretory reasons wonder where it would ever work for that matter.

So below. We have a household setup. We would have a Family object with an id. Now if we were to create one person for the family we could do it easily with:

@family = Family.new @family.persons.new(params[person])

But what if we wanted to add a person and a child at the same time via nested parameters? We won't be able to. As the childs family_id field is protected we won't be able to mass assign with the nested parameters. I can't think of a time I would ever be creating a completely "open" object that wouldn't have a single protected parameter. So when do the nested_attributes come in handy besides when your model is un-secure?

(This is just me learning there very well might be perfect places for this, I am just wondering where)

class Person < ActiveRecord::Base   validates_presence_of :name, :family_id

  has_many :children   belongs_to :family

  accepts_nested_attributes_for :children

  attr_accessible :name end

class Child < ActiveRecord::Base   belongs_to :person   belongs_to :family

  validates_presence_of :name, :family_id

  attr_accessible :name end

class Family < ActiveRecord::Base   has_many :persons   has_many :children (childs?)

  attr_protected :id end

cheers, brianp

Why does Child even have the family_id attribute? Can't you get the child's family through it's person (parent)? Unless the child can belong to a different family than the person, this is an unnecessary association.

Anyway, that doesn't really answer the question. accepts_nested_atrributes_for and attr_protected on the foreign keys doesn't work together. My question is: Why are you putting attr_protected on the foreign_keys? To prevent users from being able to move a child to a different parent when editing its attributes? If so, I recommend you use attr_readonly instead.

Yeah the objective protecting the foreign keys are not letting the Users make the changes. Maybe an admin of the app could say a person or child has changed families (parents do split up). But we don't want some smart child using curl and changing his family to any family id he wants on his own. And thereby getting access to another families options/pages or capabilities.

In my particular applications case as you've seen example code. I have dealers and users. Users belong to a dealer. Users would have foreign keys attr_protected. Becuase at no point is a user ever changing what dealer it belongs to. But if the keys can be mass assigned. Then isn't the app then vulnerable to someone creating a user that could belong to ANY dealership. Then gaining access to another dealerships admin panel ?

But if the id can't be mass assigned then it cannot be created through the dealer via nested attributes. Which makes me think the only models that can be assigned via nested attributes are un-secure and vulnerable to mass-assignment attacks.

attr_readonly does not look like it would solver the problem. As again on the initial create any use could assign any foreign key to themselves on the initial create.

Maybe i'm wrong here and maybe this just isn't a concern at all somehow. But after reading the security issues on mass-assignment I don't understand how there not vulnerabilities. If a user can change a foreign key which is used for authorization purposes. Then there changing privileges for them self.

Thanks for all the replies Sharagoz your really cleaning up my posts =) ie helping me understand rails better everyday!

This is not a problem if you are always creating users in context of dealers and validating that the one doing the creation is allowed to manage the data for the dealer in question. @dealer.users.create(params[:user]) This ensures that the users dealer_id is set to @dealer.id, even if somebody tries to be clever and add dealer_id to the post request.

Ahhhh yeah i guess that does make sense.

Now what about...I think well trying to come up with my counter-piece I answered my own question so let me see if I have it correct:

If the user was created in context of the dealer like you said. Then in the dealers control panel the user can update there profile. If the profole was updated by finding the user and updating directly then this could be a secuirty issue as they could change the dealer id at that point by sneaking in :dealer_id. BUT If the user updates the profile and it's processed via the dealer then this would not be an issue because it would still be in context. how would this look in the controller? @dealer.users.find(3).update_attributes(params[:update_user_form]) ?

Thanks, brianp

That is correct, however if you set the dealer_id to readonly, then it is not possible for the user to change it anyway, so User.find(3).update_attributes(params[:user]) is fine

Hi all,

I want to invite you to check out ResourceAwareness, a small gem that makes available information about a Rails application's resources (as defined by the 'resource/s' routing DSL methods) at Rails.application.resources.

http://github.com/ingoweiss/resource_awareness

You can find a brief introductory post about it here:

http://blog.ingoweiss.com/2010/05/10/resource-awareness.html

There is also another post with a small example (dynamic ActiveResource client creation) for the kind of things that become possible once this resource information is available:

http://blog.ingoweiss.com/2010/05/12/resource-awareness-and-active-resource.html

Best Regards, Ingo Weiss

http://github.com/ingoweiss