Permalink
Browse files

Bring Ticket Stores under test

Write tests for Ticket Store classes
Fixes #30
Update a lot of our gems
  • Loading branch information...
1 parent 0c7bde5 commit fac373fca2b8c87312265a4ad3f33f5d2a2ecfaa @soupmatt soupmatt committed Feb 13, 2012
View
1 .simplecov
@@ -1,6 +1,7 @@
SimpleCov.start do
add_filter "/spec/.*_spec\.rb"
add_filter "/spec/.*/shared_examples.*"
+ add_filter "/spec/.*/.*helper(s?).rb"
end
# vim: filetype=ruby
View
9 Gemfile
@@ -1,15 +1,18 @@
source "http://rubygems.org"
group :development do
- gem "json", "~> 1.6.1"
- gem "rspec", "~> 2.7.0"
+ gem "json"
+ gem "rspec"
gem "bundler", ">= 1.0"
- gem "jeweler", "~> 1.6.2"
+ gem "jeweler"
gem "actionpack"
+ gem "activerecord"
gem "rake"
gem "simplecov", :require => false
gem "guard"
gem "guard-rspec"
+ gem "sqlite3", :require => false
+ gem "database_cleaner"
end
gem "activesupport", :require => "active_support"
View
33 Gemfile.lock
@@ -4,48 +4,55 @@ GEM
actionpack (2.3.11)
activesupport (= 2.3.11)
rack (~> 1.1.0)
+ activerecord (2.3.11)
+ activesupport (= 2.3.11)
activesupport (2.3.11)
+ database_cleaner (0.7.1)
diff-lcs (1.1.3)
ffi (1.0.11)
git (1.2.5)
guard (1.0.0)
ffi (>= 0.5.0)
thor (~> 0.14.6)
- guard-rspec (0.5.11)
- guard (>= 0.8.4)
+ guard-rspec (0.6.0)
+ guard (>= 0.10.0)
jeweler (1.6.4)
bundler (~> 1.0)
git (>= 1.2.5)
rake
- json (1.6.1)
+ json (1.6.5)
multi_json (1.0.4)
rack (1.1.2)
rake (0.9.2.2)
- rspec (2.7.0)
- rspec-core (~> 2.7.0)
- rspec-expectations (~> 2.7.0)
- rspec-mocks (~> 2.7.0)
- rspec-core (2.7.1)
- rspec-expectations (2.7.0)
+ rspec (2.8.0)
+ rspec-core (~> 2.8.0)
+ rspec-expectations (~> 2.8.0)
+ rspec-mocks (~> 2.8.0)
+ rspec-core (2.8.0)
+ rspec-expectations (2.8.0)
diff-lcs (~> 1.1.2)
- rspec-mocks (2.7.0)
+ rspec-mocks (2.8.0)
simplecov (0.5.4)
multi_json (~> 1.0.3)
simplecov-html (~> 0.5.3)
simplecov-html (0.5.3)
+ sqlite3 (1.3.5)
thor (0.14.6)
PLATFORMS
ruby
DEPENDENCIES
actionpack
+ activerecord
activesupport
bundler (>= 1.0)
+ database_cleaner
guard
guard-rspec
- jeweler (~> 1.6.2)
- json (~> 1.6.1)
+ jeweler
+ json
rake
- rspec (~> 2.7.0)
+ rspec
simplecov
+ sqlite3
View
2 Guardfile
@@ -5,5 +5,7 @@ guard 'rspec', :version => 2, :cli => '-c -f doc' do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" }
+ watch(%r{^spec/support/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
end
View
2 lib/casclient.rb
@@ -56,7 +56,7 @@ def set_real_logger(real_logger)
# Log using the appropriate method if we have a logger
# if we dont' have a logger, gracefully ignore.
def method_missing(name, *args)
- if @real_logger && @real_logger.respond_to?(name)
+ if !@real_logger.nil? && @real_logger.respond_to?(name)
@real_logger.send(name, *args)
end
end
View
49 lib/casclient/tickets/storage.rb
@@ -4,31 +4,34 @@ module Storage
class AbstractTicketStore
attr_accessor :log
- @log = CASClient::LoggerWrapper.new
+ def log
+ @log ||= CASClient::LoggerWrapper.new
+ end
- def process_single_sign_out(si)
+ def process_single_sign_out(st)
- session_id, session = get_session_for_service_ticket(si)
+ session_id, session = get_session_for_service_ticket(st)
if session
session.destroy
- log.debug("Destroyed #{session.inspect} for session #{session_id.inspect} corresponding to service ticket #{si.inspect}.")
+ log.debug("Destroyed #{session.inspect} for session #{session_id.inspect} corresponding to service ticket #{st.inspect}.")
else
log.debug("Data for session #{session_id.inspect} was not found. It may have already been cleared by a local CAS logout request.")
end
if session_id
log.info("Single-sign-out for service ticket #{session_id.inspect} completed successfuly.")
else
- log.debug("No session id found for CAS ticket #{si}")
+ log.debug("No session id found for CAS ticket #{st}")
end
end
def get_session_for_service_ticket(st)
- session_id = read_service_session_lookup(si)
- if session_id
- session = ActiveRecord::SessionStore::Session.find_by_session_id(session_id)
+ session_id = read_service_session_lookup(st)
+ unless session_id.nil?
+ # This feels a bit hackish, but there isn't really a better way to go about it that I am aware of yet
+ session = ActiveRecord::SessionStore.session_class.find_by_session_id(session_id)
else
- log.warn("Couldn't destroy session with SessionIndex #{si} because no corresponding session id could be looked up.")
+ log.warn("Couldn't destroy session service ticket #{st} because no corresponding session id could be found.")
end
[session_id, session]
end
@@ -53,6 +56,12 @@ def retrieve_pgt(pgt_iou)
def read_service_session_lookup(st)
raise 'Implement this in a subclass!'
end
+
+ def session_id_from_controller(controller)
+ session_id = controller.request.session_options[:id] || controller.session.session_id
+ raise CASClient::CASException, "Failed to extract session_id from controller" if session_id.nil?
+ session_id
+ end
end
# A Ticket Store that keeps it's tickets in a directory on the local filesystem.
@@ -83,10 +92,10 @@ def initialize(config={})
# Rails session id.
# Returns the filename of the lookup file created.
def store_service_session_lookup(st, controller)
- raise CASException, "No service_ticket specified." unless st
- raise CASException, "No controller specified." unless controller
+ raise CASException, "No service_ticket specified." if st.nil?
+ raise CASException, "No controller specified." if controller.nil?
- sid = controller.request.session_options[:id] || controller.session.session_id
+ sid = session_id_from_controller(controller)
st = st.ticket if st.kind_of? ServiceTicket
f = File.new(filename_of_service_session_lookup(st), 'w')
@@ -100,11 +109,11 @@ def store_service_session_lookup(st, controller)
# cas_sess.<session ticket> file created in a prior call to
# #store_service_session_lookup.
def read_service_session_lookup(st)
- raise CASException, "No service_ticket specified." unless st
+ raise CASException, "No service_ticket specified." if st.nil?
st = st.ticket if st.kind_of? ServiceTicket
ssl_filename = filename_of_service_session_lookup(st)
- return File.exists?(ssl_filename) && IO.read(ssl_filename)
+ return IO.read(ssl_filename) if File.exists?(ssl_filename)
end
# Removes a stored relationship between a ServiceTicket and a local
@@ -113,14 +122,17 @@ def read_service_session_lookup(st)
#
# See #store_service_session_lookup.
def cleanup_service_session_lookup(st)
- raise CASException, "No service_ticket specified." unless st
+ raise CASException, "No service_ticket specified." if st.nil?
st = st.ticket if st.kind_of? ServiceTicket
ssl_filename = filename_of_service_session_lookup(st)
File.delete(ssl_filename) if File.exists?(ssl_filename)
end
def save_pgt_iou(pgt_iou, pgt)
+ raise CASException, "Invalid pgt_iou" if pgt_iou.nil?
+ raise CASException, "Invalid pgt" if pgt.nil?
+
# TODO: pstore contents should probably be encrypted...
pstore = open_pstore
@@ -135,17 +147,14 @@ def retrieve_pgt(pgt_iou)
pstore = open_pstore
pgt = nil
+ # TODO: need to periodically clean the storage, otherwise it will just keep growing
pstore.transaction do
pgt = pstore[pgt_iou]
+ pstore.delete pgt_iou
end
raise CASException, "Invalid pgt_iou specified. Perhaps this pgt has already been retrieved?" unless pgt
- # TODO: need to periodically clean the storage, otherwise it will just keep growing
- pstore.transaction do
- pstore.delete pgt_iou
- end
-
pgt
end
View
17 lib/casclient/tickets/storage/active_record_ticket_store.rb
@@ -19,35 +19,40 @@ def initialize(config={})
end
def store_service_session_lookup(st, controller)
- #get the session from the rack env using ActiveRecord::SessionStore::SESSION_RECORD_KEY = 'rack.session.record'
+ raise CASException, "No service_ticket specified." unless st
+ raise CASException, "No controller specified." unless controller
st = st.ticket if st.kind_of? ServiceTicket
session = controller.session
session[:service_ticket] = st
end
- def get_session_for_service_ticket(st)
+ def read_service_session_lookup(st)
+ raise CASException, "No service_ticket specified." unless st
st = st.ticket if st.kind_of? ServiceTicket
session = ActiveRecord::SessionStore::Session.find_by_service_ticket(st)
- session_id = session ? session.session_id : nil
- [session_id, session]
+ session ? session.session_id : nil
end
def cleanup_service_session_lookup(st)
#no cleanup needed for this ticket store
+ #we still raise the exception for API compliance
+ raise CASException, "No service_ticket specified." unless st
end
def save_pgt_iou(pgt_iou, pgt)
+ raise CASClient::CASException.new("Invalid pgt_iou") if pgt_iou.nil?
+ raise CASClient::CASException.new("Invalid pgt") if pgt.nil?
pgtiou = CasPgtiou.create(:pgt_iou => pgt_iou, :pgt_id => pgt)
end
def retrieve_pgt(pgt_iou)
raise CASException, "No pgt_iou specified. Cannot retrieve the pgt." unless pgt_iou
pgtiou = CasPgtiou.find_by_pgt_iou(pgt_iou)
- pgt = pgtiou.pgt_id
- raise CASException, "Invalid pgt_iou specified. Perhaps this pgt has already been retrieved?" unless pgt
+ raise CASException, "Invalid pgt_iou specified. Perhaps this pgt has already been retrieved?" unless pgtiou
+ pgt = pgtiou.pgt_id
pgtiou.destroy
View
1 spec/.gitignore
@@ -0,0 +1 @@
+test.sqlite3
View
48 spec/casclient/frameworks/rails/filter_spec.rb
@@ -4,32 +4,6 @@
describe CASClient::Frameworks::Rails::Filter do
- def controller_with_session(request = nil, session={})
-
- query_parameters = {:ticket => "bogusticket", :renew => false}
- parameters = query_parameters.dup
-
- #TODO this really need to be replaced with a "real" rails controller
- request ||= mock_post_request
- request.stub(:query_parameters) {query_parameters}
- request.stub(:path_parameters) {{}}
- controller = double("Controller")
- controller.stub(:session) {session}
- controller.stub(:request) {request}
- controller.stub(:url_for) {"bogusurl"}
- controller.stub(:query_parameters) {query_parameters}
- controller.stub(:path_parameters) {{}}
- controller.stub(:parameters) {parameters}
- controller.stub(:params) {parameters}
- controller
- end
-
- def mock_post_request
- mock_request = ActionController::Request.new({})
- mock_request.stub(:post?) {true}
- mock_request
- end
-
before(:each) do
CASClient::Frameworks::Rails::Filter.configure(
:cas_base_url => 'http://test.local/',
@@ -42,7 +16,7 @@ def mock_post_request
context "faking user without attributes" do
before { CASClient::Frameworks::Rails::Filter.fake('tester@test.com') }
it 'should set the session user' do
- CASClient::Frameworks::Rails::Filter.filter(controller_with_session(nil, subject))
+ CASClient::Frameworks::Rails::Filter.filter(mock_controller_with_session(nil, subject))
subject.should eq({:cas_user => 'tester@test.com', :casfilteruser => 'tester@test.com'})
end
after { CASClient::Frameworks::Rails::Filter.fake(nil,nil) }
@@ -51,7 +25,7 @@ def mock_post_request
context "faking user with attributes" do
before { CASClient::Frameworks::Rails::Filter.fake('tester@test.com', {:test => 'stuff', :this => 'that'}) }
it 'should set the session user and attributes' do
- CASClient::Frameworks::Rails::Filter.filter(controller_with_session(nil, subject))
+ CASClient::Frameworks::Rails::Filter.filter(mock_controller_with_session(nil, subject))
subject.should eq({ :cas_user => 'tester@test.com', :casfilteruser => 'tester@test.com', :cas_extra_attributes => {:test => 'stuff', :this => 'that' }})
end
after { CASClient::Frameworks::Rails::Filter.fake(nil,nil) }
@@ -76,7 +50,7 @@ def mock_post_request
CASClient::Client.any_instance.stub(:request_cas_response).and_return(response)
CASClient::Client.any_instance.stub(:retrieve_proxy_granting_ticket).and_return(pgt)
- controller = controller_with_session()
+ controller = mock_controller_with_session()
CASClient::Frameworks::Rails::Filter.filter(controller).should eq(true)
end
end
@@ -92,7 +66,7 @@ def mock_post_request
CASClient::Client.any_instance.stub(:request_cas_response).and_return(response)
CASClient::Frameworks::Rails::Filter.stub(:unauthorized!) {"bogusresponse"}
- controller = controller_with_session()
+ controller = mock_controller_with_session()
CASClient::Frameworks::Rails::Filter.filter(controller).should eq(false)
end
end
@@ -103,7 +77,7 @@ def mock_post_request
CASClient::Frameworks::Rails::Filter.stub(:unauthorized!) {"bogusresponse"}
- controller = controller_with_session()
+ controller = mock_controller_with_session()
controller.stub(:params) {{}}
CASClient::Frameworks::Rails::Filter.filter(controller).should eq(false)
end
@@ -116,7 +90,7 @@ def mock_post_request
CASClient::Frameworks::Rails::Filter.stub(:unauthorized!) {"bogusresponse"}
CASClient::Frameworks::Rails::Filter.config[:use_gatewaying] = false
- controller = controller_with_session()
+ controller = mock_controller_with_session()
controller.session[:cas_sent_to_gateway] = true
controller.stub(:params) {{}}
CASClient::Frameworks::Rails::Filter.filter(controller).should eq(false)
@@ -127,7 +101,7 @@ def mock_post_request
it "should return failure from filter" do
CASClient::Frameworks::Rails::Filter.config[:use_gatewaying] = true
- controller = controller_with_session()
+ controller = mock_controller_with_session()
controller.session[:cas_sent_to_gateway] = true
controller.stub(:params) {{}}
CASClient::Frameworks::Rails::Filter.filter(controller).should eq(true)
@@ -151,7 +125,7 @@ def mock_post_request
CASClient::Client.any_instance.stub(:request_cas_response).and_return(response)
CASClient::Client.any_instance.stub(:retrieve_proxy_granting_ticket).and_raise CASClient::CASException
- controller = controller_with_session()
+ controller = mock_controller_with_session()
expect { CASClient::Frameworks::Rails::Filter.filter(controller) }.to raise_error(CASClient::CASException)
end
end
@@ -161,7 +135,7 @@ def mock_post_request
CASClient::Client.any_instance.stub(:request_cas_response).and_raise "Some exception"
- controller = controller_with_session()
+ controller = mock_controller_with_session()
expect { CASClient::Frameworks::Rails::Filter.filter(controller) }.to raise_error(RuntimeError)
end
end
@@ -177,7 +151,7 @@ def mock_post_request
subject[:cas_last_valid_ticket] = 'bogusticket'
subject[:cas_last_valid_ticket_service] = 'bogusurl'
- controller = controller_with_session(mock_post_request(), subject)
+ controller = mock_controller_with_session(mock_post_request(), subject)
CASClient::Frameworks::Rails::Filter.filter(controller).should eq(true)
end
end
@@ -189,7 +163,7 @@ def mock_post_request
request = double('mock request')
request.stub(:format).and_return(nil)
- controller = controller_with_session(request)
+ controller = mock_controller_with_session(request)
CASClient::Frameworks::Rails::Filter.
should_receive(:redirect_to_cas_for_authentication).
View
6 spec/casclient/tickets/storage/active_record_ticket_store_spec.rb
@@ -0,0 +1,6 @@
+require 'spec_helper'
+require 'casclient/tickets/storage/active_record_ticket_store'
+
+describe CASClient::Tickets::Storage::ActiveRecordTicketStore do
+ it_should_behave_like "a ticket store"
+end
View
47 spec/casclient/tickets/storage_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+require 'support/local_hash_ticket_store'
+
+if RUBY_VERSION >= "1.9.3"
+ require 'tmpdir'
+end
+
+describe CASClient::Tickets::Storage::AbstractTicketStore do
+ describe "#store_service_session_lookup" do
+ it "should raise an exception" do
+ expect { subject.store_service_session_lookup("service_ticket", mock_controller_with_session) }.to raise_exception 'Implement this in a subclass!'
+ end
+ end
+ describe "#cleanup_service_session_lookup" do
+ it "should raise an exception" do
+ expect { subject.cleanup_service_session_lookup("service_ticket") }.to raise_exception 'Implement this in a subclass!'
+ end
+ end
+ describe "#save_pgt_iou" do
+ it "should raise an exception" do
+ expect { subject.save_pgt_iou("pgt_iou", "pgt") }.to raise_exception 'Implement this in a subclass!'
+ end
+ end
+ describe "#retrieve_pgt" do
+ it "should raise an exception" do
+ expect { subject.retrieve_pgt("pgt_iou") }.to raise_exception 'Implement this in a subclass!'
+ end
+ end
+ describe "#get_session_for_service_ticket" do
+ it "should raise an exception" do
+ expect { subject.get_session_for_service_ticket("service_ticket") }.to raise_exception 'Implement this in a subclass!'
+ end
+ end
+end
+
+describe CASClient::Tickets::Storage::LocalDirTicketStore do
+ around do |example|
+ Dir.mktmpdir(described_class.name) do |dir|
+ @dir = dir
+ Dir.mkdir(File.join(dir, "sessions"))
+ example.run
+ end
+ end
+ it_should_behave_like "a ticket store" do
+ let(:ticket_store) {described_class.new(:storage_dir => @dir)}
+ end
+end
View
3 spec/database.yml
@@ -0,0 +1,3 @@
+test:
+ adapter: sqlite3
+ database: spec/test.sqlite3
View
36 spec/spec_helper.rb
@@ -1,17 +1,39 @@
require 'bundler'
Bundler.setup(:default, :development)
+require 'simplecov'
Bundler.require
-require 'simplecov'
+require 'rubycas-client'
+
+Dir["./spec/support/**/*.rb"].each do |f|
+ require f unless f.end_with? '_spec.rb'
+end
+
+require 'database_cleaner'
RSpec.configure do |config|
- #config.include Rack::Test::Methods
- #config.include Webrat::Methods
- #config.include Webrat::Matchers
- #config.include TestHelpers
- #config.include Helpers
config.mock_with :rspec
config.mock_framework = :rspec
+ config.include ActionControllerHelpers
+
+ config.before(:all) do
+ end
+
+ config.after(:suite) do
+ ActiveRecordHelpers.teardown_active_record
+ end
+ config.before(:suite) do
+ ActiveRecordHelpers.setup_active_record
+ DatabaseCleaner.strategy = :transaction
+ DatabaseCleaner.clean_with(:truncation)
+ end
+
+ config.before(:each) do
+ DatabaseCleaner.start
+ end
+
+ config.after(:each) do
+ DatabaseCleaner.clean
+ end
end
-require 'rubycas-client'
View
30 spec/support/action_controller_helpers.rb
@@ -0,0 +1,30 @@
+require 'actionpack'
+
+module ActionControllerHelpers
+
+ def mock_controller_with_session(request = nil, session={})
+
+ query_parameters = {:ticket => "bogusticket", :renew => false}
+ parameters = query_parameters.dup
+
+ #TODO this really need to be replaced with a "real" rails controller
+ request ||= mock_post_request
+ request.stub(:query_parameters) {query_parameters}
+ request.stub(:path_parameters) {{}}
+ controller = double("Controller")
+ controller.stub(:session) {session}
+ controller.stub(:request) {request}
+ controller.stub(:url_for) {"bogusurl"}
+ controller.stub(:query_parameters) {query_parameters}
+ controller.stub(:path_parameters) {{}}
+ controller.stub(:parameters) {parameters}
+ controller.stub(:params) {parameters}
+ controller
+ end
+
+ def mock_post_request
+ mock_request = ActionController::Request.new({})
+ mock_request.stub(:post?) {true}
+ mock_request
+ end
+end
View
48 spec/support/active_record_helpers.rb
@@ -0,0 +1,48 @@
+require 'active_record'
+
+module ActiveRecordHelpers
+
+ class << self
+ def setup_active_record
+ config_file = File.open("spec/database.yml")
+ db_config = HashWithIndifferentAccess.new(YAML.load(config_file))
+ ActiveRecord::Base.establish_connection(db_config[:test])
+ ActiveRecord::Migration.verbose = false
+ RubyCasTables.migrate(:up)
+ end
+
+ def teardown_active_record
+ ActiveRecord::Migration.verbose = false
+ RubyCasTables.migrate(:down)
+ end
+ end
+
+ class RubyCasTables < ActiveRecord::Migration
+ def self.up
+ #default rails sessions table
+ create_table :sessions do |t|
+ t.string :session_id, :null => false
+ t.text :data
+ t.timestamps
+ end
+ add_index :sessions, :session_id
+ add_index :sessions, :updated_at
+
+ #column added to sessions table by rubycas-client
+ add_column :sessions, :service_ticket, :string
+ add_index :sessions, :service_ticket
+
+ # pgtious table
+ create_table :cas_pgtious do |t|
+ t.string :pgt_iou, :null => false
+ t.string :pgt_id, :null => false
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :sessions
+ drop_table :cas_pgtious
+ end
+ end
+end
View
48 spec/support/local_hash_ticket_store.rb
@@ -0,0 +1,48 @@
+require 'casclient/tickets/storage'
+
+class LocalHashTicketStore < CASClient::Tickets::Storage::AbstractTicketStore
+
+ attr_accessor :st_hash
+ attr_accessor :pgt_hash
+
+ def store_service_session_lookup(st, controller)
+ raise CASClient::CASException, "No service_ticket specified." if st.nil?
+ raise CASClient::CASException, "No controller specified." if controller.nil?
+ session_id = session_id_from_controller(controller)
+ st = st.ticket if st.kind_of? CASClient::ServiceTicket
+ st_hash[st] = session_id
+ end
+
+ def read_service_session_lookup(st)
+ raise CASClient::CASException, "No service_ticket specified." if st.nil?
+ st = st.ticket if st.kind_of? CASClient::ServiceTicket
+ st_hash[st]
+ end
+
+ def cleanup_service_session_lookup(st)
+ raise CASClient::CASException, "No service_ticket specified." if st.nil?
+ st = st.ticket if st.kind_of? CASClient::ServiceTicket
+ st_hash.delete(st)
+ end
+
+ def save_pgt_iou(pgt_iou, pgt)
+ raise CASClient::CASException.new("Invalid pgt_iou") if pgt_iou.nil?
+ raise CASClient::CASException.new("Invalid pgt") if pgt.nil?
+ pgt_hash[pgt_iou] = pgt
+ end
+
+ def retrieve_pgt(pgt_iou)
+ pgt = pgt_hash.delete(pgt_iou)
+ raise CASClient::CASException.new("Invalid pgt_iou") if pgt.nil?
+ pgt
+ end
+
+ def pgt_hash
+ @pgt_hash ||= {}
+ end
+
+ def st_hash
+ @pgt_hash ||= {}
+ end
+
+end
View
5 spec/support/local_hash_ticket_store_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe LocalHashTicketStore do
+ it_should_behave_like "a ticket store"
+end
View
137 spec/support/shared_examples_for_ticket_stores.rb
@@ -0,0 +1,137 @@
+shared_examples "a ticket store interacting with sessions" do
+ describe "#store_service_session_lookup" do
+ it "should raise CASException if the Service Ticket is nil" do
+ expect { subject.store_service_session_lookup(nil, "controller") }.to raise_exception(CASClient::CASException, /No service_ticket specified/)
+ end
+ it "should raise CASException if the controller is nil" do
+ expect { subject.store_service_session_lookup("service_ticket", nil) }.to raise_exception(CASClient::CASException, /No controller specified/)
+ end
+ it "should store the ticket without any errors" do
+ expect { subject.store_service_session_lookup(service_ticket, mock_controller_with_session(nil, session)) }.to_not raise_exception
+ end
+ end
+
+ describe "#get_session_for_service_ticket" do
+ context "the service ticket is nil" do
+ it "should raise CASException" do
+ expect { subject.get_session_for_service_ticket(nil) }.to raise_exception(CASClient::CASException, /No service_ticket specified/)
+ end
+ end
+ context "the service ticket is associated with a session" do
+ before do
+ subject.store_service_session_lookup(service_ticket, mock_controller_with_session(nil, session))
+ session.save!
+ end
+ it "should return the session_id and session for the given service ticket" do
+ result_session_id, result_session = subject.get_session_for_service_ticket(service_ticket)
+ result_session_id.should == session.session_id
+ result_session.session_id.should == session.session_id
+ result_session.data.should == session.data
+ end
+ end
+ context "the service ticket is not associated with a session" do
+ it "should return nils if there is no session for the given service ticket" do
+ subject.get_session_for_service_ticket(service_ticket).should == [nil, nil]
+ end
+ end
+ end
+
+ describe "#process_single_sign_out" do
+ context "the service ticket is nil" do
+ it "should raise CASException" do
+ expect { subject.process_single_sign_out(nil) }.to raise_exception(CASClient::CASException, /No service_ticket specified/)
+ end
+ end
+ context "the service ticket is associated with a session" do
+ before do
+ subject.store_service_session_lookup(service_ticket, mock_controller_with_session(nil, session))
+ session.save!
+ subject.process_single_sign_out(service_ticket)
+ end
+ context "the session" do
+ it "should be destroyed" do
+ ActiveRecord::SessionStore.session_class.find_by_session_id(session.session_id).should be_nil
+ end
+ end
+ it "should destroy session for the given service ticket" do
+ subject.process_single_sign_out(service_ticket)
+ end
+ end
+ context "the service ticket is not associated with a session" do
+ it "should run without error if there is no session for the given service ticket" do
+ expect { subject.process_single_sign_out(service_ticket) }.to_not raise_error
+ end
+ end
+ end
+
+ describe "#cleanup_service_session_lookup" do
+ context "the service ticket is nil" do
+ it "should raise CASException" do
+ expect { subject.cleanup_service_session_lookup(nil) }.to raise_exception(CASClient::CASException, /No service_ticket specified/)
+ end
+ end
+ it "should run without error" do
+ expect { subject.cleanup_service_session_lookup(service_ticket) }.to_not raise_exception
+ end
+ end
+end
+
+shared_examples "a ticket store" do
+ let(:ticket_store) { described_class.new }
+ let(:service_url) { "https://www.example.com/cas" }
+ let(:session) do
+ ActiveRecord::SessionStore::Session.create!(:session_id => "session#{rand(1000)}", :data => {})
+ end
+ subject { ticket_store }
+
+ context "when dealing with sessions, Service Tickets, and Single Sign Out" do
+ context "and the service ticket is a String" do
+ it_behaves_like "a ticket store interacting with sessions" do
+ let(:service_ticket) { "ST-ABC#{rand(1000)}" }
+ end
+ end
+ context "and the service ticket is a ServiceTicket" do
+ it_behaves_like "a ticket store interacting with sessions" do
+ let(:service_ticket) { CASClient::ServiceTicket.new("ST-ABC#{rand(1000)}", service_url) }
+ end
+ end
+ context "and the service ticket is a ProxyTicket" do
+ it_behaves_like "a ticket store interacting with sessions" do
+ let(:service_ticket) { CASClient::ProxyTicket.new("ST-ABC#{rand(1000)}", service_url) }
+ end
+ end
+ end
+
+ context "when dealing with Proxy Granting Tickets and their IOUs" do
+ let(:pgt) { "my_pgt_#{rand(1000)}" }
+ let(:pgt_iou) { "my_pgt_iou_#{rand(1000)}" }
+
+ describe "#save_pgt_iou" do
+ it "should raise CASClient::CASException if the pgt_iou is nil" do
+ expect { subject.save_pgt_iou(nil, pgt) }.to raise_exception(CASClient::CASException, /Invalid pgt_iou/)
+ end
+ it "should raise CASClient::CASException if the pgt is nil" do
+ expect { subject.save_pgt_iou(pgt_iou, nil) }.to raise_exception(CASClient::CASException, /Invalid pgt/)
+ end
+ end
+
+ describe "#retrieve_pgt" do
+ before do
+ subject.save_pgt_iou(pgt_iou, pgt)
+ end
+
+ it "should return the stored pgt" do
+ subject.retrieve_pgt(pgt_iou).should == pgt
+ end
+
+ it "should raise CASClient::CASException if the pgt_iou isn't in the store" do
+ expect { subject.retrieve_pgt("not_my"+pgt_iou) }.to raise_exception(CASClient::CASException, /Invalid pgt_iou/)
+ end
+
+ it "should not return the stored pgt a second time" do
+ subject.retrieve_pgt(pgt_iou).should == pgt
+ expect { subject.retrieve_pgt(pgt_iou) }.to raise_exception(CASClient::CASException, /Invalid pgt_iou/)
+ end
+ end
+ end
+end

0 comments on commit fac373f

Please sign in to comment.