Access Control in Rails

December 10th, 2006

You need to install the acl2 plugin from

http://opensvn.csie.org/ezra/rails/plugins/dev/acl_system2/

 

Here is an example of its use.  the access_control is thanks to this plugin

 

class PostController < ApplicationController
  before_filter :login_required, :except => [:list, :index]
  access_control [:new, :create, :update, :edit] => ‘(admin | user | moderator)’,
                 :delete => ‘admin & (!moderator & !blacklist)’ 
There are two callback methods you can use to define your own success and failure behaviors. If you define permission_granted and/or permission_denied as protected methods in your controller you can redirect or render and error page or whatever else you might want to do if access is allowed or denied. 

 

  # the rest of your controller here

  protected

  def permission_denied
    flash[:notice] = “You don’t have privileges to access this action”
    return redirect_to :action => ‘denied’
  end

  def permission_granted
    flash[:notice] = “Welcome to the secure area of foo.com!”
  end
There is also a helper method that can be used in the view or controller. In the view its handy for conditional menus or stuff like that.

   
So here is the schema of this application including the Post model and the User and Role model plus the habtm join table:
ActiveRecord::Schema.define(:version => 3) do
create_table "roles", :force => true do |t|
t.column "title", :string
end
create_table "roles_users", :id => false, :force => true do |t|
t.column "role_id", :integer
t.column "user_id", :integer
end
create_table "users", :force => true do |t|
t.column "login", :string, :limit => 40
t.column "email", :string, :limit => 100
t.column "crypted_password", :string, :limit => 40
t.column "salt", :string, :limit => 40
t.column "created_at", :datetime
t.column "updated_at", :datetime
end
end  

 

installing acts_as_authenticated

December 9th, 2006

In a rails app

 

./script/plugin source http://svn.techno-weenie.net/projects/plugins
./script/plugin install acts_as_authenticated
#or if that doesn’t work:
script/plugin install http://svn.techno-weenie.net/projects/plugins/acts_as_authenticated

 NEXT
script/generate authenticated user account
 

Put include AuthenticatedSystem in your application controller (make sure you put it in the class, not before it), and put

before_filter :login_required

in every controller you want protected. More details in account_controller.rb.

Setting up local gem repository

December 8th, 2006

After struggling for a while with some problems getting gems working properly I finally got it set up. Here were the steps I took to successfully get it working.

First I created a directory off of my home directory called gems/

Then I specified the following in my .bash_profile

export GEM_PATH=$HOME/gems:/usr/lib/ruby/gems/1.8
export GEM_HOME=$HOME/gems
Specify both the installation directory and your local directory in the GEM_PATH variable.

 

I also created a .gemrc file which did not exist by default and put the following as the contents of that file

 

gemhome: /home/rsseltze/gems
gempath:
- /home/rsseltze/gems
- /usr/lib/ruby/gems/1.8
 

you can then check your gem environment by typing

gem environment

which will give you something like this

Rubygems Environment:
- VERSION: 0.9.0 (0.9.0)
- INSTALLATION DIRECTORY: /home/rsseltze/gems
- GEM PATH:
- /home/rsseltze/gems
- /usr/lib/ruby/gems/1.8
- REMOTE SOURCES:
- http://gems.rubyforge.org
Additionally, you can specify the GEM_PATH in your environment.rb file as well, in my case
ENV[’GEM_PATH’] = ‘/home/rsseltze/gems:/usr/lib/ruby/gems/1.8′

Then you can verify further by checking both

gem query –local

gem query –remote

Finally test by installing a gem with

gem install

after that if you query your local gem repository again it should show the newly installed gem.

Using has_many with STI

December 7th, 2006

I was having a problem where basically I had a has_many relationship in a class that was inheriting from a user table. Here was the issue.

class Artist < User

has_many :paintings

end
When I went to in irc and tried

>> a = Artist.find_first
=> #nil, “salt”=>”10d69fe2bc4d7223a09a33581f288288f0b71b29″, “postal_code”=>nil, “updated_at”=>”2006-12-07 16:01:18″, “street_addr”=>nil, “crypted_password”=>”71aae2a5503d582a3026cf604c1fa5862e684227″, “type”=>”Artist”, “country”=>nil, “remember_token_expires_at”=>nil, “id”=>”6″, “phone”=>nil, “remember_token”=>nil, “first_name”=>nil, “last_name”=>nil, “login”=>”test2″, “state”=>nil, “created_at”=>”2006-12-07 14:52:48″, “email”=>”test2@test.com“}>
>> a.paintingsActiveRecord::StatementInvalid: Mysql::Error: Unknown column ‘paintings.artist_id’ in ‘where clause’: SELECT * FROM paintings WHERE (paintings.artist_id = 6)

I did not want to add an artist_id to my paintings so I instead found that I could use a foreign_key attribute to fix the problem

class Artist < User
has_many :paintings, :foreign_key => ‘user_id’
end

Then in the processes of writing this up I realized I have been a retard and should have just created my paintings table with an artist_id rather then a user_id, since artists are the only users who will have a painting. Oh well, the foreign_key is a good thing to know and could be useful in other scenarios, such as if I had two different models, such as Artist1 and Artist2, and then I could have just left a single column in the artists table called user_id which would work for both the Artist1 and Artist2 models, using the foreign_key attribute.