I have “users”, “company” and “contract” controllers, with the following
relations:
class User < ActiveRecord::Base
has_many :companies
class Company < ActiveRecord::Base
belongs_to :user
has_many :contracts
class Contract < ActiveRecord::Base
belongs_to :company
I had no problem using ruby to create management interface for it (and i
started programming in ruby two weeks ago!!). What concerns me is
security of records. Here’s what needs to be done:
actions like for example /company/edit/1 should raise error when
Company with id=1 doesn’t belong to logged User (i’m using login
generator gem), same for Contracts (ownership needs to be checked
through Companies table).
system should be immune to hidden field abuse (like: download html
for /company/edit/30, edit html and replace user_id, visit from
localhost, submit to overtake record)
How to do that?? Here’s what i found so far:
Use subselect/joins to check permission at the beginning of every
chosen action in controller
@contract=Contract.find_by_sql(‘select contract.* from “contracts” r
left join “companies” p on p.“id”=r.“company_id” left join “users” …
where user.“id”=’+@session[‘user’].id)
if not found then raise error…
working, but ugly as hell and i’m repeating myslef often in different
actions.
Use :through property instead joins above (don’t know how to use it
properly yet)
Use validates_associated in model (doesnt protect from hidden field
abuse, cannot work through many tables like
Contract>o----Company>o----User - or can it??)
Write validation of ownership in model, not controller, similiar to
validates_associated but smarter
thanks for answer. that’s just how i’m doing it now.
question is - can such ownership check be moved to models?? so when we
get :id or @params[‘contract’].id for example in Contract class
subselect/join is performed to check if it really belongs to logged
user, and if not error is raised.
why??
because then scaffolded actions can be used for stuff like
contract/update safely
no code copy/paste in every action in controller
one central ownership validation for controller is less error prone
and easier to modify
Off the top of my head, I can’t see a way to do this. It seems to be
out of
the scope w/ the MVC here, and that the controller really needs to be
handling this rather than the model.
Now, you could override the methods of your class so that they require
an id
to be passed to them for each action… but that sounds like a lot of
extra
work.
This is best practice in Rails anyway, but you should protect certain
attributes of your Model from being mass assigned - for example in the
way you’ve defined below by editing a form source and resubmitting.
The way to do that is to use the attr_protected command in your model
to declare attributes that can only be set manually in your code. They
cannot be set using bulk assignments from outside such as
Model.create(params[:model]).
e.g.
class Company < ActiveRecord::Base
attr_protected :user_id
end
Alternatively you can use attr_accessible to explicitly declare which
fields can be mass assigned from form query parameters. It’s up to you
as to which of the opt-in or opt-out models you go for.
There’s more information on this in section 21.4 (“Creating Records
Directly from Form Parameters”) in chapter 21 (“Securing Your Rails
Application”) of the Agile Web D. with Rails book. It’s really
worth reading as it covers this and many other factors in securing code
if so, go for the 2nd Edition beta book available at Pragmatic
Programmers as it is covering the more recent changes to the Rails
codebase.
I’m not sure if this fits well to your problem, but did you have a look
at http://perens.com/FreeSoftware/ModelSecurity/ ? It’s not really
maintained actively, but it seems quite stable anyway
…which essentially lets you apply a with_scope clause as a filter at
the controller level.
Bbkr I juz wrote:
I have “users”, “company” and “contract” controllers, with the following
relations:
class User < ActiveRecord::Base
has_many :companies
class Company < ActiveRecord::Base
belongs_to :user
has_many :contracts
class Contract < ActiveRecord::Base
belongs_to :company
I had no problem using ruby to create management interface for it (and i
started programming in ruby two weeks ago!!). What concerns me is
security of records. Here’s what needs to be done:
actions like for example /company/edit/1 should raise error when
Company with id=1 doesn’t belong to logged User (i’m using login
generator gem), same for Contracts (ownership needs to be checked
through Companies table).
system should be immune to hidden field abuse (like: download html
for /company/edit/30, edit html and replace user_id, visit from
localhost, submit to overtake record)
… [snip]
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.