Acl_system help is needed

i found Ezra’s acl_system plugin yesterday and i am trying to figure it
out.

based on the simple instructions on the site, it does exactly what i
need but i’m getting some errors when i try to use it:

NoMethodError in UsersController#index

You have a nil object when you didn’t expect it!
The error occured while evaluating nil.roles

i am pretty new to rails and still have trouble figuring out where
things go, so i’m pretty sure that my problem is that i don’t have the
current_user method in the right place. or i might have just done
something else wrong too. i’m not sure, but if anyone can help that
would be great.

On 7/16/06, Josh K. [email protected] wrote:

i am pretty new to rails and still have trouble figuring out where
things go, so i’m pretty sure that my problem is that i don’t have the
current_user method in the right place. or i might have just done
something else wrong too. i’m not sure, but if anyone can help that
would be great.

What is UsersController#index supposed to be doing? Since acl_system
doesn’t handle authentication, you need to give us some more info on
how you’re handling login/logout of users.

– James

the users controller is just a scaffold i threw up to test the acl
plugin.

i added the following code to the controller:

before_filter :authorize

access_control [ :index, :list, :show, :new, :create, :edit, :update,
:destroy ] => ‘CSR’

and here is the authorize method in my applicatin.rb file:

private
def authorize
unless User.find_by_id(session[:user_id])
session[:original_uri] = request.request_uri
flash[:notice] = ‘Please log in’
redirect_to :controller => ‘login’
end
end

James L. wrote:

On 7/16/06, Josh K. [email protected] wrote:

i am pretty new to rails and still have trouble figuring out where
things go, so i’m pretty sure that my problem is that i don’t have the
current_user method in the right place. or i might have just done
something else wrong too. i’m not sure, but if anyone can help that
would be great.

What is UsersController#index supposed to be doing? Since acl_system
doesn’t handle authentication, you need to give us some more info on
how you’re handling login/logout of users.

– James

ok, after spending a whole day fighting with this, i think i know what
was wrong.

when i was testing my program, there wasn’t a user logged in. everything
in the acl_system plugin was being executed before the methods in
“before_filter”. i don’t know if this is a bug or if something i did was
wrong, but the only way it is working for me right now is if the login
controller is the first thing the user sees. if the user isn’t logged in
before going to a controller with “access_control” the “current_user”
method returns nil and causes the whole thing to shut down.

there is some terminology i am still not quite familiar with so i might
not be explaining this right, so i will give more info if anyone can
help me out and give me any pointers on using this.

On Jul 16, 2006, at 9:46 PM, Josh K. wrote:

logged in
before going to a controller with “access_control” the “current_user”
method returns nil and causes the whole thing to shut down.

there is some terminology i am still not quite familiar with so i
might
not be explaining this right, so i will give more info if anyone can
help me out and give me any pointers on using this.

I think you have the right idea. You need to make sure that a user
has authenticated before you let the access_control filter run. So
only use access_control on actions in your controller that require
user login. If one of your controller actions doesn’t need a user to
log in to see , then it doesn’t need to perform access_control either.

-Ezra

I think you have the right idea. You need to make sure that a user
has authenticated before you let the access_control filter run. So
only use access_control on actions in your controller that require
user login. If one of your controller actions doesn’t need a user to
log in to see , then it doesn’t need to perform access_control either.

-Ezra

thanks for the reply Ezra. for this particular controller, i need all of
the pages to perform access control. all i have in it now is the code
that is generated when you create a scaffold, plus this:

before_filter :authorize

access_control :DEFAULT => ‘customer | csr’,
:authorize => ‘!guest’

the authorize method is in my application.rb file and all it does is
check to see if there is someone logged in and then sends the user to
the login controller that i have set up.

i had this in my controller:

def current_user
User.find_by_id(session[:user_id])
end

but this was being executed before my authorize method so when the
acl_system checks my current user, it returns nil. to at least keep the
code from from giving errors i had to change my current_user method to:

def current_user
User.find_by_id(session[:user_id]) || User.new
end

but even by doing that, my authorize method is not getting called and
the user is not ever being sent to the login screen. if i go straight to
the login screen and login, everything else works great.

also, on a side note, i wanted to add the current user method to the
base controller file but it’s not pulling up that way. is it required to
have current_user in every single controller?

Ezra Z. wrote on 17.07.2006 06:52:

On Jul 16, 2006, at 9:46 PM, Josh K. wrote:

[…]

controller is the first thing the user sees. if the user isn’t logged in
before going to a controller with “access_control” the “current_user”
method returns nil and causes the whole thing to shut down.
[…]

I think you have the right idea. You need to make sure that a user has
authenticated before you let the access_control filter run. So only use
access_control on actions in your controller that require user login.
If one of your controller actions doesn’t need a user to log in to see ,
then it doesn’t need to perform access_control either.

The restrict_to and permit? helpers can be used without a login in the
views.

i was finally able to get this plugin to work the way i wanted it to
work.

i ended up having to take out the before_filter line because
access_control was being processed before it.

to make sure that i don’t get nil errors from current_user, i used
something like this:

def current_user
User.find_by_id(session[:user_id]) || User.new
end

i made the default role !guest, so my access_control call looks
something like this:

access_control :DEFAULT => ‘!guest’,
:test_csr => ‘csr’

i still want to check every page to see if the user is logged in though,
so i wrote that in my permission_denied method:

protected
def permission_denied
unless User.find_by_id(session[:user_id])
session[:original_uri] = request.request_uri
flash[:notice] = ‘Please log in’
return redirect_to :controller => ‘login’
end

return redirect_to :controller => 'login', :action => 'denied'

end

so everything works the way i need it to but i was never able to get
everything working the way it shows in the example. the only way it
works is if the user is already logged in and tries to go to one pages
he or she does not have access to.

i would like to get any input from anyone who has had the same problems
or maybe could point out what i got wrong in the first place.

thanks

On Jul 17, 2006, at 5:49 AM, Josh K. wrote:

thanks for the reply Ezra. for this particular controller, i need
all of
the pages to perform access control. all i have in it now is the code
that is generated when you create a scaffold, plus this:

before_filter :authorize

access_control :DEFAULT => ‘customer | csr’,
:authorize => ‘!guest’

This looks like a problem. the :authorize => ‘!guest’ is not needed.
I think your authorize method might be a slight misnomer as well. I
think you mean authenticate there instead. Authentication is the
process of making sure someone is who they say they are, ie user logs
in with password and is authenticated. Then the access_control
performs authorization, which is what user roles are allowed to
access certain actions. So maybe change your authorize method to be
authenticate instead.

But all that aside, I don’t think you want to put access_control on
your authorize method. Since it is already a private method it cannot
be called from the web so it doesn’t need to be protected with
access_control.

but this was being executed before my authorize method so when the
but even by doing that, my authorize method is not getting called and
the user is not ever being sent to the login screen. if i go
straight to
the login screen and login, everything else works great.

also, on a side note, i wanted to add the current user method to the
base controller file but it’s not pulling up that way. is it
required to
have current_user in every single controller?

Ok I think I see what your issue is. You need to realize that to have
a before_filter halt the chain of before filters it needs to return
false. So we need to rewrite your before_filter method that checks if
a user is logged in. Also I think you need a slight change to your
current_user method to make it work a tad better. Lets try something
like this in the bottom of your application controller class:

protected

I would change this to authenticate instead of authorize to avoid

confusion.
def authorize
unless @current_user = User.find_by_id(session[:user_id])
session[:original_uri] = request.request_uri
flash[:notice] = ‘Please log in’
redirect_to :controller => ‘login’
return false # !! this is what was missing!
end
end

def current_user
@current_user ||= session[:user] ? User.find_by_id(session
[:user]) : nil
end

Try setting these methods like I have shown and then use a before
filter to protect all actions that require a login. This will make
sure that if an action needs a logged in user that it will try to
authenticate, if it fails then it will redirect to the login action
and access_control will never be called. If the user is successful at
login in the current_user will be set and then access_control gets
called next to see if the user has permission to access the action in
question.

so in the controllers that require login:

before_filter :authorize # or authenticate if you change the name.

access_control :DEFAULT => ‘!guest’,
:test_csr => ‘csr’

One thing to realize that might help make this all a bit more clear
for you is to realize that access_control sets up a before_filter
itself, thats how it works. So it must happen after the before
filter has run that logs the user in and sets current_user. If the
user login fails then the access_control is never run because the
user is redirected to the login screen.

Cheers-
-Ezra

thanks so much Ezra. i wish i had known a lot of that before i started
trying to use your plugin.

this has def been a good learning experience for me though. thanks for
the help.