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:
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?)
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.
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])
?
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
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.
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: