[rspec-users] Getting past my login system

Daniel N has.sox at gmail.com
Tue Jul 17 02:40:50 EDT 2007


On 7/17/07, Ryan Tucker <rctucker at u.washington.edu> wrote:
>
> Daniel N wrote:
> >
> >
> > On 7/17/07, *Ryan Tucker* <rctucker at u.washington.edu
> > <mailto:rctucker at u.washington.edu>> wrote:
> >
> >     Daniel N wrote:
> >     >
> >     >
> >     > On 7/17/07, *Ryan Tucker* <rctucker at u.washington.edu
> >     <mailto:rctucker at u.washington.edu>
> >     > <mailto:rctucker at u.washington.edu
> >     <mailto:rctucker at u.washington.edu>>> wrote:
> >     >
> >     >     Daniel N wrote:
> >     >     >
> >     >     >
> >     >     > On 7/17/07, *Ryan Tucker* <rctucker at u.washington.edu
> >     <mailto:rctucker at u.washington.edu>
> >     >     <mailto: rctucker at u.washington.edu
> >     <mailto:rctucker at u.washington.edu>>
> >     >     > <mailto:rctucker at u.washington.edu
> >     <mailto:rctucker at u.washington.edu>
> >     >     <mailto: rctucker at u.washington.edu
> >     <mailto:rctucker at u.washington.edu>>>> wrote:
> >     >     >
> >     >     >     Ryan Tucker wrote:
> >     >     >     > Thank you in advance for your help.  I am relatively
> new
> >     >     to both
> >     >     >     Rails
> >     >     >     > and Rspec and I am hoping for some insight from some
> >     >     experienced
> >     >     >     veterans.
> >     >     >     >
> >     >     >     > Right now I am using Rspec for code that has already
> >     been
> >     >     >     written so
> >     >     >     > that additional functionality can be developed using
> >     the BDD
> >     >     >     method. My
> >     >     >     > problem shows up when I try to spec controllers that
> are
> >     >     behind the
> >     >     >     > login system.  Each page checks for the
> >     session[:user], and if
> >     >     >     they do
> >     >     >     > not exists, requires them to login.  Logging in is
> >     handled
> >     >     by one
> >     >     >     > controller (the Admin controller) and I want to access
> a
> >     >     page under
> >     >     >     > another controller (say a Students controller).
> >     >     >     >
> >     >     >     > In my students_controller_spec.rb, I want want to
> >     make sure
> >     >     >     > http://test.host/students is successfully displayed,
> >     so I
> >     >     wrote
> >     >     >     > something like:
> >     >     >     >
> >     >     >     >   it "should be successful" do
> >     >     >     >     get :index
> >     >     >     >     response.should be_success
> >     >     >     >   end
> >     >     >     >
> >     >     >     > The problem is that is keeps redirecting to my login
> >     page at
> >     >     >     > http://test.host/login.  I tried then setting
> >     >     session[:user] and
> >     >     >     doing a
> >     >     >     > post to my login page to simulate a login so that I
> >     could
> >     >     access the
> >     >     >     > correct page, but that does not seem to work.  I tried
> a
> >     >     number of
> >     >     >     > things, including the following:
> >     >     >     >
> >     >     >     > def do_login
> >     >     >     >   @user = User.find(:first, :conditions =>
> >     ['username = ?' ,
> >     >     >     'ryan'] )
> >     >     >     >   session[:user] = @ user.id <http://user.id>
> >     <http://user.id> <http://user.id>
> >     >     >     >   post :login, :path => []
> >     >     >     > end
> >     >     >     >
> >     >     >     > describe StudentsController do
> >     >     >     >   it "should be successful" do
> >     >     >     >     do_login
> >     >     >     >     get :index
> >     >     >     >     response.should be_success
> >     >     >     >   end
> >     >     >     > end
> >     >     >     >
> >     >     >     > This still results in being redirected to the login
> >     page at
> >     >     >     > http://test.host/login when I want to go to
> >     >     >     http://test.host/students.
> >     >     >     > Also, I realize I am actually doing a call on my test
> >     >     database for
> >     >     >     > this.  Part of the reason is that code that called
> >     during
> >     >     login
> >     >     >     checks
> >     >     >     > fields of a user.  The other reason is I could not
> >     get it to
> >     >     >     work using
> >     >     >     > stubs, but that might just have been because I was
> >     not using
> >     >     >     them properly.
> >     >     >     >
> >     >     >     > Any insight will be helpful, thanks!
> >     >     >     >
> >     >     >     > -Ryan
> >     >     >     > _______________________________________________
> >     >     >     > rspec-users mailing list
> >     >     >     > rspec-users at rubyforge.org
> >     <mailto:rspec-users at rubyforge.org>
> >     >     <mailto:rspec-users at rubyforge.org
> >     <mailto:rspec-users at rubyforge.org>> <mailto:
> >     >     rspec-users at rubyforge.org <mailto:rspec-users at rubyforge.org>
> >     <mailto:rspec-users at rubyforge.org <mailto:rspec-users at rubyforge.org
> >>>
> >     >     >     > http://rubyforge.org/mailman/listinfo/rspec-users
> >     >     >     >
> >     >     >     Forgot one thing.
> >     >     >
> >     >     >     In trying to do the post, I get the error that "No
> action
> >     >     >     responded to
> >     >     >     login" suggesting that I am not properly accessing the
> >     login
> >     >     >     function in
> >     >     >     my Admin controller.
> >     >     >
> >     >     >     Thanks again,
> >     >     >     Ryan
> >     >     >
> >     >     >
> >     >     >
> >     >     > Ryan, the login action is being called on
> >     >     your  StudentsController and
> >     >     > so it's not found.
> >     >     >
> >     >     > If it's the presence of the session[:user] that tells the
> >     >     > before_filter that your logged in, the you don't need to
> >     do the
> >     >     post.
> >     >     > In fact you shouldn't post, since as you found out if you
> >     post to
> >     >     > login, your posting to the login action of the controller
> your
> >     >     > currently in.  Bad.  Your setting the session and you
> >     shouldn't need
> >     >     > to do any more.
> >     >     >
> >     >     > HTH
> >     >     > Daniel
> >     >     >
> >     >     >
> >     >     >
> >     >
> >
> ------------------------------------------------------------------------
> >     >
> >     >     >
> >     >     > _______________________________________________
> >     >     > rspec-users mailing list
> >     >     > rspec-users at rubyforge.org
> >     <mailto:rspec-users at rubyforge.org>
> >     <mailto:rspec-users at rubyforge.org <mailto:rspec-users at rubyforge.org
> >>
> >     >     > http://rubyforge.org/mailman/listinfo/rspec-users
> >     >     Thanks, Daniel.
> >     >
> >     >     That was my understanding as well, but, for some reason,
> >     that has not
> >     >     been enough.  The post was an attempt to simulate an actual
> >     login by
> >     >     posting to another controller (I know it was bad...) since
> just
> >     >     setting
> >     >     the session[:user] was not a success.  Thank you for your
> >     help though.
> >     >
> >     >     Take care,
> >     >     Ryan
> >     >
> >     >
> >     > Can you post your before_filter method that checks if your
> >     logged in?
> >     >
> >     > Also your login method in your Admin controller.
> >     >
> >     > Cheers
> >     >
> >     >
> >     >
> >     >
> >
> ------------------------------------------------------------------------
> >     >
> >     > _______________________________________________
> >     > rspec-users mailing list
> >     > rspec-users at rubyforge.org <mailto:rspec-users at rubyforge.org>
> >     > http://rubyforge.org/mailman/listinfo/rspec-users
> >       #  The Logins are to track a users activity, and this supports
> >       # when a user wants to access a page and needs to login first,
> >     sending
> >     them to it after they login.
> >       # Authenticate checks the username and password against the
> username
> >     and password in the
> >       # database.
> >       def login
> >         if request.post?
> >           if @current_user = User.authenticate(params[:username],
> >     params[:password])
> >             login = Login.create(:remote_ip => request.remote_ip.to_s,
> >     :user_agent => request.user_agent.to_s , :http_vars => request.env)
> >             @current_user.logins << login
> >             session[:user] = @current_user.id
> >             uri = session[:original_uri]
> >             session[:original_uri] = nil
> >             redirect_to uri || home_url
> >             return
> >           else
> >             flash[:error] = "Access denied"
> >           end
> >         end
> >
> >         if session[:user]
> >           redirect_to home_url
> >           return false
> >         end
> >         set_page_title "Log In"
> >       end
> >
> >       # This checks that there is a current user, and checks if they
> >     are active
> >       # In my case, I am keeping track of whether or not I have disabled
> >       # a user.  active?() returns true so long as they are have not
> been
> >     deactivated.
> >       def check_authentication
> >         unless @current_user and @current_user.active?
> >           session[:original_uri] = request.request_uri
> >           redirect_to log_in_url
> >           return false
> >         end
> >         true
> >       end
> >
> >
> >     Thank you again for your help.
> >
> >
> > I hope I can ;)
> >
> >     Take care,
> >     Ryan
> >
> >
> >
> > Ok there's a fair bit of stuff going on in the login code.  It doesn't
> > seem that you've included your before_filter that checks to see if a
> > user is logged in in your controller.
> >
> > Do you use a before_filter or some other method in the controller to
> > check for logged in status?  Can you post the code that checks if a
> > user is logged in for the controller.
> >
> > Cheers
> > Daniel
> >
> >
> > ------------------------------------------------------------------------
> >
> > _______________________________________________
> > rspec-users mailing list
> > rspec-users at rubyforge.org
> > http://rubyforge.org/mailman/listinfo/rspec-users
>
> There is also a method that checks whether or not a user has rights to
> view a particular page as below.
>
>   def check_authorization
>     unless @current_user.superuser or
>       @current_rights.detect do |right|
>         right.action == action_name && right.controller ==
> self.class.controller_path
>       end
>       flash[:warning] = "You are not authorized to view the page you
> requested."
>       redirect_to home_url
>       return false
>     end
>   end
>
>
> The @current_user is set in another method set_user().
>
>   def set_user
>     unless session[:user].nil?
>       begin
>         @current_user = User.find( session[:user], :include => [
> :positions ] )
>         @user_preferences = @current_user.preferences || {}
>         @current_rights = @current_user.positions.collect do |pos|
>           pos.role.rights.collect
>         end.flatten.uniq
>       rescue
>         # Do nothing
>       end
>     end
>   end
>
> So, login() sets the session[:user], set_user() sets the @current_user
> as well as the rights of the user and
> check_authentication()/check_authorization() use the @current_user to
> check whether or not a user is who they say they are (via password
> verification) or view the page (via rights).
>
> My apologies if this has been redundant. I did try reading through other
> posts before posting my own, but I guess I did not understand how to
> apply what I read to what I have. I did attempt mocking a user using the
> method suggested by Scott, but got an error stating:
> "Mock 'User_1000' received unexpected message :preferences wit (no args)."
>
> Perhaps it is because I am not doing that properly either, so I will
> make sure I understand that a bit better first.
>
> Thanks for everyone's help.
>
> Take care,
> Ryan



Ok,  it seems to me that if you assign the  @current_user varaible and stub
it to return true on  the superuser method then everything should be ok.

def do_login
  @user = mock_model( User, :id => 1 ) # Get yourself a user that you can
reference in your spec
  @user.stub!( :superuser ).and_return( true )  # Short circuit the
check_authorization method to be a super user by default.  You can override
this in your individual behaviours.

  session[:user] = @user.id  # should short circuit the set_user method.
  assigns[ :current_user ] = @user # Set the current user
end

I think that should do it.  You might find you need to stub the @user model
a bit depending on what other methods are being called on it.

HTH
Daniel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://rubyforge.org/pipermail/rspec-users/attachments/20070717/53fc9304/attachment-0001.html 


More information about the rspec-users mailing list