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. -- Posted via http://www.ruby-forum.com/.
On 7/16/06, Josh Kieschnick <jjkiesch@gmail.com> wrote:> 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.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 Ludlow wrote:> On 7/16/06, Josh Kieschnick <jjkiesch@gmail.com> 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-- Posted via http://www.ruby-forum.com/.
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. -- Posted via http://www.ruby-forum.com/.
On Jul 16, 2006, at 9:46 PM, Josh Kieschnick wrote:> 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. > > --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
Ezra Zygmuntowicz wrote on 17.07.2006 06:52:> On Jul 16, 2006, at 9:46 PM, Josh Kieschnick 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 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. > > > -Ezrathanks 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? -- Posted via http://www.ruby-forum.com/.
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 -- Posted via http://www.ruby-forum.com/.
On Jul 17, 2006, at 5:49 AM, Josh Kieschnick wrote:>> >> 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'' >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.> 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?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. -- Posted via http://www.ruby-forum.com/.