test: cover index and AuthZeroCappedSessionsController
This commit is contained in:
1 parent
3163f1966d
commit
344df3fca2
1 file changed
+158
@@ -159,3 +159,161 @@ class AuthCappedDashboardController < Prism::Controller
|
|||||||
remember_sessions: :AuthLoginSession, max_remember_sessions: 2
|
remember_sessions: :AuthLoginSession, max_remember_sessions: 2
|
||||||
before_action :require_authentication
|
before_action :require_authentication
|
||||||
|
|
||||||
|
def index
|
||||||
|
halt(200, "hello #{current_user.email}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class AuthZeroCappedSessionsController < Prism::Controller
|
||||||
|
include Prism::Authenticatable
|
||||||
|
authenticate_with model: :AuthUser, remember_sessions: :AuthLoginSession, max_remember_sessions: 0
|
||||||
|
|
||||||
|
def create
|
||||||
|
user = AuthUser.find_by(email: params['email'])
|
||||||
|
if user && user.authenticate(params['password'])
|
||||||
|
sign_in(user, remember: true)
|
||||||
|
halt(200, 'signed in')
|
||||||
|
else
|
||||||
|
halt(401, 'invalid credentials')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class AuthZeroCappedDashboardController < Prism::Controller
|
||||||
|
include Prism::Authenticatable
|
||||||
|
authenticate_with model: :AuthUser, unauthenticated_redirect_path: '/sign_in',
|
||||||
|
remember_sessions: :AuthLoginSession, max_remember_sessions: 0
|
||||||
|
before_action :require_authentication
|
||||||
|
|
||||||
|
def index
|
||||||
|
halt(200, "hello #{current_user.email}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class AuthenticatableApp < Prism::Application
|
||||||
|
enable_sessions(secret: 'auth-secret')
|
||||||
|
post '/sign_in', to: 'auth_sessions#create'
|
||||||
|
post '/sign_out', to: 'auth_sessions#destroy'
|
||||||
|
get '/dashboard', to: 'auth_dashboard#index'
|
||||||
|
get '/api/me', to: 'auth_api#index'
|
||||||
|
get '/inherited/me', to: 'auth_inherited#index'
|
||||||
|
post '/remember/sign_in', to: 'auth_remember_sessions#create'
|
||||||
|
post '/remember/sign_out', to: 'auth_remember_sessions#destroy'
|
||||||
|
get '/remember/dashboard', to: 'auth_remember_dashboard#index'
|
||||||
|
post '/multi/sign_in', to: 'auth_multi_sessions#create'
|
||||||
|
post '/multi/sign_out', to: 'auth_multi_sessions#destroy'
|
||||||
|
get '/multi/dashboard', to: 'auth_multi_dashboard#index'
|
||||||
|
get '/multi/other_devices', to: 'auth_multi_dashboard#other_devices'
|
||||||
|
post '/multi/sign_out_others', to: 'auth_multi_dashboard#sign_out_others'
|
||||||
|
post '/multi/revoke/:id', to: 'auth_multi_dashboard#revoke'
|
||||||
|
post '/capped/sign_in', to: 'auth_capped_sessions#create'
|
||||||
|
get '/capped/dashboard', to: 'auth_capped_dashboard#index'
|
||||||
|
post '/zero-capped/sign_in', to: 'auth_zero_capped_sessions#create'
|
||||||
|
get '/zero-capped/dashboard', to: 'auth_zero_capped_dashboard#index'
|
||||||
|
end
|
||||||
|
|
||||||
|
class AuthenticatableTest < Minitest::Test
|
||||||
|
include TestSupport
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@dir = Dir.mktmpdir('prism-authenticatable')
|
||||||
|
@store = Prism::Orm::Store.new(File.join(@dir, 'test.pstore'))
|
||||||
|
@store.create_table(:auth_users, %w[id email password_digest remember_token])
|
||||||
|
@store.create_table(:auth_login_sessions, %w[id user_id token user_agent ip_address])
|
||||||
|
user_class = Class.new(Prism::Orm::Model) do
|
||||||
|
table_name :auth_users
|
||||||
|
has_secure_password
|
||||||
|
has_secure_token :remember_token
|
||||||
|
end
|
||||||
|
user_class.store = @store
|
||||||
|
Object.const_set(:AuthUser, user_class)
|
||||||
|
|
||||||
|
login_session_class = Class.new(Prism::Orm::Model) do
|
||||||
|
table_name :auth_login_sessions
|
||||||
|
has_secure_token :token
|
||||||
|
end
|
||||||
|
login_session_class.store = @store
|
||||||
|
Object.const_set(:AuthLoginSession, login_session_class)
|
||||||
|
|
||||||
|
AuthUser.create!(email: 'foksiu@example.com', password: 'hunter2')
|
||||||
|
end
|
||||||
|
|
||||||
|
def teardown
|
||||||
|
FileUtils.remove_entry(@dir)
|
||||||
|
Object.send(:remove_const, :AuthUser) if Object.const_defined?(:AuthUser)
|
||||||
|
Object.send(:remove_const, :AuthLoginSession) if Object.const_defined?(:AuthLoginSession)
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(method, path, **opts)
|
||||||
|
AuthenticatableApp.call(env_for(method, path, **opts))
|
||||||
|
end
|
||||||
|
|
||||||
|
def session_cookie_from(headers)
|
||||||
|
cookie_named(headers, 'prism.session')
|
||||||
|
end
|
||||||
|
|
||||||
|
def cookie_named(headers, name)
|
||||||
|
line = headers['Set-Cookie'].split("\n").find { |c| c.start_with?("#{name}=") }
|
||||||
|
line&.split(';')&.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def sign_in_cookie
|
||||||
|
_, headers, = call('POST', '/sign_in',
|
||||||
|
headers: { 'Content-Type' => 'application/x-www-form-urlencoded' },
|
||||||
|
body: 'email=foksiu@example.com&password=hunter2')
|
||||||
|
session_cookie_from(headers)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_wrong_password_is_rejected
|
||||||
|
status, = call('POST', '/sign_in',
|
||||||
|
headers: { 'Content-Type' => 'application/x-www-form-urlencoded' },
|
||||||
|
body: 'email=foksiu@example.com&password=wrong')
|
||||||
|
assert_equal 401, status
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_dashboard_without_session_redirects_to_configured_path
|
||||||
|
status, headers, = call('GET', '/dashboard')
|
||||||
|
assert_equal 302, status
|
||||||
|
assert_equal '/sign_in', headers['Location']
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_api_without_session_halts_with_401
|
||||||
|
status, = call('GET', '/api/me')
|
||||||
|
assert_equal 401, status
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_sign_in_then_dashboard_sees_current_user
|
||||||
|
cookie = sign_in_cookie
|
||||||
|
status, _, body = call('GET', '/dashboard', cookies: cookie)
|
||||||
|
assert_equal 200, status
|
||||||
|
assert_equal 'hello foksiu@example.com', body.join
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_sign_out_forgets_current_user
|
||||||
|
cookie = sign_in_cookie
|
||||||
|
_, sign_out_headers, = call('POST', '/sign_out', cookies: cookie)
|
||||||
|
fresh_cookie = session_cookie_from(sign_out_headers)
|
||||||
|
|
||||||
|
status, = call('GET', '/dashboard', cookies: fresh_cookie)
|
||||||
|
assert_equal 302, status
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_return_to_url_is_remembered_across_the_redirect
|
||||||
|
_, headers, = call('GET', '/dashboard')
|
||||||
|
refute_nil headers['Location']
|
||||||
|
cookie = session_cookie_from(headers)
|
||||||
|
|
||||||
|
_, sign_in_headers, body = call('POST', '/sign_in',
|
||||||
|
headers: { 'Content-Type' => 'application/x-www-form-urlencoded' },
|
||||||
|
cookies: cookie,
|
||||||
|
body: 'email=foksiu@example.com&password=hunter2')
|
||||||
|
assert_equal '/dashboard', body.join
|
||||||
|
refute_nil sign_in_headers['Set-Cookie']
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_authenticate_with_declared_on_a_base_controller_redirects_a_subclass_without_a_session
|
||||||
|
status, headers, = call('GET', '/inherited/me')
|
||||||
|
assert_equal 302, status
|
||||||
|
assert_equal '/sign_in', headers['Location']
|
||||||
|
end
|
||||||
|
|
||||||
Reference in new issue
Block a user