The Decider said over 5 years ago permalink Comment? (0)
Tagged: model relationships rails

finding relationships

I haven’t found a better way to discover all relationships between models other than loading in all models from the app/models directory and trying to instantiate them and then looking to see if they are a kind of ActiveRecord:Base. If they are then we can run reflect_on_all_associations.

In doing this I modified some code I found on the web to draw a .svg image of the relationships. Code looks like:

#!/usr/bin/env ruby
require "config/environment"
Dir.glob("app/models/*rb") { |f|
    require f
}

puts %{digraph x \{ 
  has_many1 [shape=point]
  has_many2 [shape=point]
  has_many1 -> has_many2 [label="Has many", color=red]
  belongs_to1 [shape=point]
  belongs_to2 [shape=point]
  belongs_to1 -> belongs_to2 [label="Belongs to", color=blue]
  has_and_belongs_to_many1 [shape=point]
  has_and_belongs_to_many2 [shape=point]
  has_and_belongs_to_many1 -> has_and_belongs_to_many2 [label="HaBtM", color=green]
  has_one1  [shape=point]
  has_one2  [shape=point]
  has_one1 -> has_one2 [label="Has one", color=gray]
  node [shape=box, style=filled, fillcolor=lightgray, width=2.5] 
}
Dir.glob("app/models/*rb") { |f|
    f.match(/\/([a-z_]+).rb/)
    classname = $1.camelize
    classname = $1 + 'QR' if classname =~ /(\w+)Qr$/ # total hack for question response models
    klass = Kernel.const_get classname
    obj = klass.new rescue next
    if obj.kind_of? ActiveRecord::Base
        puts classname
        klass.reflect_on_all_associations.each { |a|
          att = case a.macro
                  when :has_many : 'color=red, '# label="#{a.macro.to_s.humanize}"
                  when :belongs_to : 'color=blue, '
                  when :has_and_belongs_to_many : 'color=green, '
                  when :has_one : 'color=gray, '
                  else 'color=black, '
                  end
          puts %{ #{classname} -> #{a.name.to_s.camelize.singularize} [ #{att} fontsize="8"]}
        }
    end
}
puts "}"
  1. Install Graphviz
  2. Save that code in your lib or bin directory of your rails root. I called it rails_visual.rb then try:

PNG output
ruby bin/rails_visual.rb > surveil.dot; dot -Tpng -osurveil.png surveil.dot

SVG output
@ruby bin/rails_visual.rb > surveil.dot; dot -Tsvg -osurveil.svg surveil.dot @

Follow the image link to flickr to see the original (7959 × 1364) image
surveil

The Hacker said over 5 years ago permalink Comment? (0)
Tagged: rails security relationships activerecord

ActiveRecord.update_attributes has_many :security_holes, :through => :unkown_features

Among you railites who have successfully learned rails, watched tutorials, and generally feel comfortable about your abilities: Probably didn’t know there is a little security hole in your app.

It has to deal with update_attributes, has_many relationships, and a method made available on the parent in the relation.

Example:

class User < ActiveRecord::Base
  has_many :groups
end

In your view you have your pretty form with user’s name and other demographics they can enter in their profile. and a ‘save’ button that leads to a call to ‘update_attributes’.

The problem lies in the fact that has_many creates a method off your object called

 user.group_ids= 

Which allows you to pass in an array of ids and create associations en-mass.
the problem is that I can come in with firebug and add my own fields.

<!-- im in your html source adding my inputs -->
<input type="text" name="user[group_ids][]"/>
<input type="text" name="user[group_ids][]"/>
<input type="text" name="user[group_ids][]"/>

After filling those fields and submiting, if you inspect the params hash you will notice:
- “parent” => {…. “association_ids” => [“1”,“2”,“4”]}

And if you check your script/console and check the associations, they will be there assuming you have groups with id’s of 1,2, and 4.

The implications? If you use these groups for any kind of role based access, a user could assume a group with root/super/power user access!

The lesson?

Protect your attributes!

 attr_protected :group_ids 

But! a better idea would be to use:

 attr_accessible :name, :bio, :etc 

I hope this has helped you as much as it did me!

-TheHacker