10.2 protect pages.
again, we will start from TDD!!!
1. since both edit and update need the same authentication, we can put their test together:
describe "authentication of edit/update pages" do
before(:each) do
@user = Factory(:user)
end
describe "for not signed-in users" do
it "should redirect to sign in page" do
get :edit, :id => @user
response.should redirect_to signin_path
end
it "should deny access to update" do
put :update, :id => @user, :user => {}
response.should redirect_to signin_path
end
end
end
2. we will add before_filter to user controller to make this test pass:
class UsersController < ApplicationController
before_filter :authenticate, :only => [:edit, :update]
.
private
def authenticate
deny_access unless signed_in?
end
end
we still need to define the deny_access method, since it is kind of authentication, I'll put it into session helper:
def deny_access
redirect_to signin_path, :notice => "please sign in first."
end
note, this line of code is equivalent with two
flash[:notice] = ""
redirect_to signin_path
you can also use:
redirect_to signin_path, :alert => "fdsfdsfsdf"
but you can't use :success or :error in this contruction.
3. except need of user to sign in, we still need to make sure current user can't edit other user info.
start from TDD again!!!
describe UsersController do
render_views
.
.
.
describe "authentication of edit/update pages" do
.
.
.
describe "for signed-in users" do
before(:each) do
wrong_user = Factory(:user, :email => "[email protected]")
test_sign_in(wrong_user)
end
it "should require matching users for 'edit'" do
get :edit, :id => @user
response.should redirect_to(root_path)
end
it "should require matching users for 'update'" do
put :update, :id => @user, :user => {}
response.should redirect_to(root_path)
end
end
end
end
4. now to make the test pass, we need to add a new before filter to user controller.
class UsersController < ApplicationController
before_filter :authenticate, :only => [:edit, :update]
before_filter :correct_user, :only => [:edit, :update]
.
.
.
def edit
@title = "Edit user"
end
.
.
.
private
def authenticate
deny_access unless signed_in?
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_path) unless current_user?(@user)
end
end
module SessionsHelper
.
.
.
def current_user?(user)
user == current_user
end
def deny_access
redirect_to signin_path, :notice => "Please sign in to access this page."
end
private
.
.
.
end
now we have make our site very safe.
5. now we are doing some useful thing:
if a unsigned in user try to visit a protected page, he is redirected to the sign in page, then after he sign in, he is always redirected to the profile page, what we want is to redirect the user to the page he was trying to visit.
this is a very good work flow to be tested by the integration test!
so let's write a integration test for this flow first.
require 'spec_helper'
describe "FriendlyForwardings" do
it "should forward to the requested page after signin" do
user = Factory(:user)
visit edit_user_path(user)
# The test automatically follows the redirect to the signin page.
fill_in :email, :with => user.email
fill_in :password, :with => user.password
click_button
# The test follows the redirect again, this time to users/edit.
response.should render_template('users/edit')
end
end
you may wondering, why I use
should render_template()
instead of
should redirect_to()
because, in integration test, it will follow the redirect, so response.should redirect_to will not work.
6. next, we will do the implementation to make the test pass.
how do we do this?
a. since http is stateless, we have to use session to store the requested url in last request, then get it from session in the new request.(the things in session will expire when browser close.)
b. we will use the request object to get the url.
module SessionsHelper
.
.
.
def deny_access
store_location
redirect_to signin_path, :notice => "Please sign in to access this page."
end
def redirect_back_or(default)
redirect_to(session[:return_to] || default)
clear_return_to
end
private
.
.
.
def store_location
session[:return_to] = request.fullpath
end
def clear_return_to
session[:return_to] = nil
end
end
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.