casino_core 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -17,6 +17,7 @@ group :development, :test do
17
17
  gem 'simplecov', '~> 0.7.1'
18
18
  gem 'sqlite3'
19
19
  gem 'database_cleaner'
20
+ gem 'webmock'
20
21
  end
21
22
 
22
23
  gem 'activerecord', '~> 3.2.9'
data/Gemfile.lock CHANGED
@@ -15,6 +15,7 @@ GEM
15
15
  addressable (2.3.2)
16
16
  arel (3.0.2)
17
17
  builder (3.0.4)
18
+ crack (0.3.1)
18
19
  database_cleaner (0.9.1)
19
20
  diff-lcs (1.1.3)
20
21
  git (1.2.5)
@@ -25,8 +26,8 @@ GEM
25
26
  rake
26
27
  rdoc
27
28
  json (1.7.5)
28
- multi_json (1.4.0)
29
- rake (10.0.2)
29
+ multi_json (1.5.0)
30
+ rake (10.0.3)
30
31
  rdoc (3.12)
31
32
  json (~> 1.4)
32
33
  redcarpet (2.2.2)
@@ -34,10 +35,10 @@ GEM
34
35
  rspec-core (~> 2.12.0)
35
36
  rspec-expectations (~> 2.12.0)
36
37
  rspec-mocks (~> 2.12.0)
37
- rspec-core (2.12.0)
38
- rspec-expectations (2.12.0)
38
+ rspec-core (2.12.2)
39
+ rspec-expectations (2.12.1)
39
40
  diff-lcs (~> 1.1.3)
40
- rspec-mocks (2.12.0)
41
+ rspec-mocks (2.12.1)
41
42
  simplecov (0.7.1)
42
43
  multi_json (~> 1.0)
43
44
  simplecov-html (~> 0.7.1)
@@ -45,6 +46,9 @@ GEM
45
46
  sqlite3 (1.3.6)
46
47
  tzinfo (0.3.35)
47
48
  useragent (0.4.15)
49
+ webmock (1.9.0)
50
+ addressable (>= 2.2.7)
51
+ crack (>= 0.1.7)
48
52
  yard (0.8.3)
49
53
 
50
54
  PLATFORMS
@@ -61,4 +65,5 @@ DEPENDENCIES
61
65
  simplecov (~> 0.7.1)
62
66
  sqlite3
63
67
  useragent (~> 0.4.13)
68
+ webmock
64
69
  yard (~> 0.8.3)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.5
1
+ 0.0.6
data/casino_core.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "casino_core"
8
- s.version = "0.0.5"
8
+ s.version = "0.0.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Nils Caspar"]
12
- s.date = "2012-12-19"
12
+ s.date = "2012-12-24"
13
13
  s.description = "A CAS server core library."
14
14
  s.email = "ncaspar@me.com"
15
15
  s.extra_rdoc_files = [
@@ -41,6 +41,7 @@ Gem::Specification.new do |s|
41
41
  "db/migrate/20121125091934_add_issued_from_credentials_to_service_tickets.rb",
42
42
  "db/migrate/20121125185415_create_proxy_granting_tickets.rb",
43
43
  "db/migrate/20121125190013_tickets_should_be_unique.rb",
44
+ "db/migrate/20121223135227_proxy_granting_tickets_belongs_to_service_ticket.rb",
44
45
  "db/schema.rb",
45
46
  "lib/casino_core.rb",
46
47
  "lib/casino_core/authenticator.rb",
@@ -49,6 +50,7 @@ Gem::Specification.new do |s|
49
50
  "lib/casino_core/helper/browser.rb",
50
51
  "lib/casino_core/helper/logger.rb",
51
52
  "lib/casino_core/helper/login_tickets.rb",
53
+ "lib/casino_core/helper/proxy_granting_tickets.rb",
52
54
  "lib/casino_core/helper/service_tickets.rb",
53
55
  "lib/casino_core/helper/ticket_granting_tickets.rb",
54
56
  "lib/casino_core/helper/tickets.rb",
@@ -63,6 +65,7 @@ Gem::Specification.new do |s|
63
65
  "lib/casino_core/processor/login_credential_acceptor.rb",
64
66
  "lib/casino_core/processor/login_credential_requestor.rb",
65
67
  "lib/casino_core/processor/logout.rb",
68
+ "lib/casino_core/processor/service_ticket_validator.rb",
66
69
  "lib/casino_core/processor/session_destroyer.rb",
67
70
  "lib/casino_core/processor/session_overview.rb",
68
71
  "lib/casino_core/railtie.rb",
@@ -77,6 +80,7 @@ Gem::Specification.new do |s|
77
80
  "spec/processor/login_credential_acceptor_spec.rb",
78
81
  "spec/processor/login_credential_requestor_spec.rb",
79
82
  "spec/processor/logout_spec.rb",
83
+ "spec/processor/service_ticket_validator_spec.rb",
80
84
  "spec/processor/session_destroyer_spec.rb",
81
85
  "spec/processor/session_overview_spec.rb",
82
86
  "spec/spec_helper.rb"
@@ -102,6 +106,7 @@ Gem::Specification.new do |s|
102
106
  s.add_development_dependency(%q<simplecov>, ["~> 0.7.1"])
103
107
  s.add_development_dependency(%q<sqlite3>, [">= 0"])
104
108
  s.add_development_dependency(%q<database_cleaner>, [">= 0"])
109
+ s.add_development_dependency(%q<webmock>, [">= 0"])
105
110
  else
106
111
  s.add_dependency(%q<activerecord>, ["~> 3.2.9"])
107
112
  s.add_dependency(%q<addressable>, ["~> 2.3.2"])
@@ -114,6 +119,7 @@ Gem::Specification.new do |s|
114
119
  s.add_dependency(%q<simplecov>, ["~> 0.7.1"])
115
120
  s.add_dependency(%q<sqlite3>, [">= 0"])
116
121
  s.add_dependency(%q<database_cleaner>, [">= 0"])
122
+ s.add_dependency(%q<webmock>, [">= 0"])
117
123
  end
118
124
  else
119
125
  s.add_dependency(%q<activerecord>, ["~> 3.2.9"])
@@ -127,6 +133,7 @@ Gem::Specification.new do |s|
127
133
  s.add_dependency(%q<simplecov>, ["~> 0.7.1"])
128
134
  s.add_dependency(%q<sqlite3>, [">= 0"])
129
135
  s.add_dependency(%q<database_cleaner>, [">= 0"])
136
+ s.add_dependency(%q<webmock>, [">= 0"])
130
137
  end
131
138
  end
132
139
 
data/config/cas.yml CHANGED
@@ -13,7 +13,8 @@ development:
13
13
  options:
14
14
  users:
15
15
  testuser:
16
- password: foobar123
16
+ password: "foobar123"
17
+ name: "Test User"
17
18
 
18
19
  test:
19
20
  <<: *defaults
@@ -23,4 +24,5 @@ test:
23
24
  options:
24
25
  users:
25
26
  testuser:
26
- password: foobar123
27
+ password: "foobar123"
28
+ name: "Test User"
@@ -0,0 +1,14 @@
1
+ require 'casino_core/model'
2
+
3
+ class ProxyGrantingTicketsBelongsToServiceTicket < ActiveRecord::Migration
4
+ def change
5
+ CASinoCore::Model::ProxyGrantingTicket.delete_all
6
+
7
+ remove_index :proxy_granting_tickets, :ticket_granting_ticket_id
8
+ remove_column :proxy_granting_tickets, :ticket_granting_ticket_id
9
+
10
+ add_column :proxy_granting_tickets, :service_ticket_id, :integer
11
+ change_column :proxy_granting_tickets, :service_ticket_id, :integer, null: false
12
+ add_index :proxy_granting_tickets, :service_ticket_id
13
+ end
14
+ end
data/db/schema.rb CHANGED
@@ -11,7 +11,7 @@
11
11
  #
12
12
  # It's strongly recommended to check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20121125190013) do
14
+ ActiveRecord::Schema.define(:version => 20121223135227) do
15
15
 
16
16
  create_table "login_tickets", :force => true do |t|
17
17
  t.string "ticket", :null => false
@@ -22,16 +22,16 @@ ActiveRecord::Schema.define(:version => 20121125190013) do
22
22
  add_index "login_tickets", ["ticket"], :name => "index_login_tickets_on_ticket", :unique => true
23
23
 
24
24
  create_table "proxy_granting_tickets", :force => true do |t|
25
- t.string "ticket", :null => false
26
- t.string "iou", :null => false
27
- t.integer "ticket_granting_ticket_id", :null => false
28
- t.datetime "created_at", :null => false
29
- t.datetime "updated_at", :null => false
25
+ t.string "ticket", :null => false
26
+ t.string "iou", :null => false
27
+ t.datetime "created_at", :null => false
28
+ t.datetime "updated_at", :null => false
29
+ t.integer "service_ticket_id", :null => false
30
30
  end
31
31
 
32
32
  add_index "proxy_granting_tickets", ["iou"], :name => "index_proxy_granting_tickets_on_iou", :unique => true
33
+ add_index "proxy_granting_tickets", ["service_ticket_id"], :name => "index_proxy_granting_tickets_on_service_ticket_id"
33
34
  add_index "proxy_granting_tickets", ["ticket"], :name => "index_proxy_granting_tickets_on_ticket", :unique => true
34
- add_index "proxy_granting_tickets", ["ticket_granting_ticket_id"], :name => "index_proxy_granting_tickets_on_ticket_granting_ticket_id"
35
35
 
36
36
  create_table "service_tickets", :force => true do |t|
37
37
  t.string "ticket", :null => false
@@ -1,11 +1,10 @@
1
+ require 'casino_core/settings'
2
+
1
3
  module CASinoCore
2
4
  module Helper
3
5
  module Logger
4
6
  def logger
5
- # TODO this is just a "silent logger", make logger a setting!
6
- logger = ::Logger.new(STDOUT)
7
- logger.level = ::Logger::Severity::UNKNOWN
8
- logger
7
+ CASinoCore::Settings.logger
9
8
  end
10
9
  end
11
10
  end
@@ -0,0 +1,45 @@
1
+ require 'addressable/uri'
2
+ require 'net/https'
3
+
4
+ require 'casino_core/helper/logger'
5
+ require 'casino_core/helper/tickets'
6
+
7
+ module CASinoCore
8
+ module Helper
9
+ module ProxyGrantingTickets
10
+ include CASinoCore::Helper::Logger
11
+ include CASinoCore::Helper::Tickets
12
+
13
+ def acquire_proxy_granting_ticket(pgt_url, service_ticket)
14
+ begin
15
+ uri = Addressable::URI.parse(pgt_url)
16
+ https = Net::HTTP.new(uri.host, uri.port || 443)
17
+ https.use_ssl = true
18
+
19
+ https.start do |conn|
20
+ pgt = service_ticket.proxy_granting_tickets.new({
21
+ ticket: random_ticket_string('PGT'),
22
+ iou: random_ticket_string('PGTIOU')
23
+ })
24
+
25
+ uri.query_values = (uri.query_values || {}).merge(pgtId: pgt.ticket, pgtIou: pgt.iou)
26
+
27
+ response = conn.request_get(uri.request_uri)
28
+ # TODO: follow redirects... 2.5.4 says that redirects MAY be followed
29
+ if "#{response.code}" == "200"
30
+ # 3.4 (proxy-granting ticket IOU)
31
+ pgt.save!
32
+ logger.debug "Proxy-granting ticket generated for pgt_url '#{pgt_url}': #{pgt.inspect}"
33
+ return pgt
34
+ else
35
+ logger.warn "Proxy-granting ticket callback server responded with a bad result code '#{response.code}'. PGT will not be stored."
36
+ end
37
+ end
38
+ rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError
39
+ logger.warn "Exception while communication with proxy-granting ticket callback server: #{e.message}"
40
+ end
41
+ nil
42
+ end
43
+ end
44
+ end
45
+ end
@@ -26,6 +26,40 @@ module CASinoCore
26
26
 
27
27
  clean_service
28
28
  end
29
+
30
+ def validate_service_ticket_for_service(ticket, service, renew = false)
31
+ result = if service.nil? or ticket.nil?
32
+ logger.warn 'Invalid validate request: no valid ticket or no valid service given'
33
+ 'INVALID_REQUEST'
34
+ else
35
+ if ticket.consumed?
36
+ logger.warn "Service ticket '#{ticket.ticket}' already consumed"
37
+ 'INVALID_TICKET'
38
+ elsif Time.now - ticket.created_at > CASinoCore::Settings.service_ticket[:lifetime_unconsumed]
39
+ logger.warn "Service ticket '#{ticket.ticket}' has expired"
40
+ 'INVALID_TICKET'
41
+ elsif clean_service_url(service) != ticket.service
42
+ logger.warn "Service ticket '#{ticket.ticket}' is not valid for service '#{service}'"
43
+ 'INVALID_SERVICE'
44
+ elsif renew && !ticket.issued_from_credentials?
45
+ logger.info "Service ticket '#{ticket.ticket}' was not issued from credentials but service '#{service}' will only accept a renewed ticket"
46
+ 'INVALID_TICKET'
47
+ else
48
+ logger.info "Service ticket '#{ticket.ticket}' for service '#{service}' successfully validated"
49
+ true
50
+ end
51
+ end
52
+ unless ticket.nil?
53
+ logger.debug "Consumed ticket '#{ticket.ticket}'"
54
+ ticket.consumed = true
55
+ ticket.save!
56
+ end
57
+ result
58
+ end
59
+
60
+ def service_ticket_valid_for_service?(ticket, service, renew = false)
61
+ validate_service_ticket_for_service(ticket, service, renew) == true
62
+ end
29
63
  end
30
64
  end
31
65
  end
@@ -6,6 +6,7 @@ module CASinoCore
6
6
  autoload :Browser, 'casino_core/helper/browser.rb'
7
7
  autoload :Logger, 'casino_core/helper/logger.rb'
8
8
  autoload :LoginTickets, 'casino_core/helper/login_tickets.rb'
9
+ autoload :ProxyGrantingTickets, 'casino_core/helper/proxy_granting_tickets.rb'
9
10
  autoload :ServiceTickets, 'casino_core/helper/service_tickets.rb'
10
11
  autoload :Tickets, 'casino_core/helper/tickets.rb'
11
12
  autoload :TicketGrantingTickets, 'casino_core/helper/ticket_granting_tickets.rb'
@@ -1,8 +1,8 @@
1
1
  require 'casino_core/model'
2
2
 
3
3
  class CASinoCore::Model::ProxyGrantingTicket < ActiveRecord::Base
4
- attr_accessible :iou, :ticket, :ticket_granting_ticket_id
4
+ attr_accessible :iou, :ticket, :service_ticket_id
5
5
  validates :ticket, uniqueness: true
6
6
  validates :iou, uniqueness: true
7
- belongs_to :ticket_granting_ticket
7
+ belongs_to :service_ticket
8
8
  end
@@ -9,6 +9,7 @@ class CASinoCore::Model::ServiceTicket < ActiveRecord::Base
9
9
  validates :ticket, uniqueness: true
10
10
  belongs_to :ticket_granting_ticket
11
11
  before_destroy :send_single_sing_out_notification
12
+ has_many :proxy_granting_tickets
12
13
 
13
14
  def self.cleanup_unconsumed
14
15
  self.delete_all(['created_at < ? AND consumed = ?', CASinoCore::Settings.service_ticket[:lifetime_unconsumed].seconds.ago, false])
@@ -5,7 +5,6 @@ class CASinoCore::Model::TicketGrantingTicket < ActiveRecord::Base
5
5
  serialize :extra_attributes, Hash
6
6
  validates :ticket, uniqueness: true
7
7
  has_many :service_tickets
8
- has_many :proxy_granting_tickets
9
8
 
10
9
  def browser_info
11
10
  user_agent = UserAgent.parse(self.user_agent)
@@ -8,48 +8,17 @@ class CASinoCore::Processor::LegacyValidator < CASinoCore::Processor
8
8
  include CASinoCore::Helper::ServiceTickets
9
9
 
10
10
  # This method will call `#validation_succeeded` or `#validation_failed`. In both cases, it supplies
11
- # a string as argument. The webapplication should present that string (and nothing else) to the
11
+ # a string as argument. The web application should present that string (and nothing else) to the
12
12
  # requestor.
13
13
  #
14
14
  # @param [Hash] params parameters supplied by requestor (a service)
15
15
  def process(params = nil)
16
16
  params ||= {}
17
17
  ticket = CASinoCore::Model::ServiceTicket.where(ticket: params[:ticket]).first
18
- if ticket_valid_for_service?(ticket, params[:service], !!params[:renew])
18
+ if service_ticket_valid_for_service?(ticket, params[:service], !!params[:renew])
19
19
  @listener.validation_succeeded("yes\n#{ticket.ticket_granting_ticket.username}\n")
20
20
  else
21
21
  @listener.validation_failed("no\n\n")
22
22
  end
23
23
  end
24
-
25
- private
26
- def ticket_valid_for_service?(ticket, service, renew = false)
27
- ticket_valid = if service.nil? or ticket.nil?
28
- logger.warn 'Invalid validate request: no valid ticket or no valid service given'
29
- false
30
- else
31
- if ticket.consumed?
32
- logger.warn "Service ticket '#{ticket.ticket}' already consumed"
33
- false
34
- elsif Time.now - ticket.created_at > CASinoCore::Settings.service_ticket[:lifetime_unconsumed]
35
- logger.warn "Service ticket '#{ticket.ticket}' has expired"
36
- false
37
- elsif clean_service_url(service) != ticket.service
38
- logger.warn "Service ticket '#{ticket.ticket}' is not valid for service '#{service}'"
39
- false
40
- elsif renew && !ticket.issued_from_credentials?
41
- logger.info "Service ticket '#{ticket.ticket}' was not issued from credentials but service '#{service}' will only accept a renewed ticket"
42
- false
43
- else
44
- logger.info "Service ticket '#{ticket.ticket}' for service '#{service}' successfully validated"
45
- true
46
- end
47
- end
48
- unless ticket.nil?
49
- logger.debug "Consumed ticket '#{ticket.ticket}'"
50
- ticket.consumed = true
51
- ticket.save!
52
- end
53
- ticket_valid
54
- end
55
24
  end
@@ -0,0 +1,69 @@
1
+ require 'builder'
2
+ require 'casino_core/processor'
3
+ require 'casino_core/helper'
4
+ require 'casino_core/model'
5
+
6
+ # The ServiceTicketValidator processor should be used to handle GET requests to /serviceValidate
7
+ class CASinoCore::Processor::ServiceTicketValidator < CASinoCore::Processor
8
+ include CASinoCore::Helper::ServiceTickets
9
+ include CASinoCore::Helper::ProxyGrantingTickets
10
+
11
+ # This method will call `#validation_succeeded` or `#validation_failed`. In both cases, it supplies
12
+ # a string as argument. The web application should present that string (and nothing else) to the
13
+ # requestor. The Content-Type should be set to 'text/xml; charset=utf-8'
14
+ #
15
+ # @param [Hash] params parameters delivered by the client
16
+ def process(params = nil)
17
+ params ||= {}
18
+ ticket = CASinoCore::Model::ServiceTicket.where(ticket: params[:ticket]).first
19
+ validation_result = validate_service_ticket_for_service(ticket, params[:service], !!params[:renew])
20
+ if validation_result == true
21
+ options = { service_ticket: ticket }
22
+ unless params[:pgtUrl].nil?
23
+ options[:proxy_granting_ticket] = acquire_proxy_granting_ticket(params[:pgtUrl], ticket)
24
+ end
25
+ @listener.validation_succeeded(build_xml(true, options))
26
+ else
27
+ @listener.validation_failed(build_xml(false, error_code: validation_result, error_message: 'Validation failed'))
28
+ end
29
+ end
30
+
31
+ private
32
+ def build_xml(success, options = {})
33
+ xml = Builder::XmlMarkup.new(indent: 2)
34
+ xml.cas :serviceResponse, 'xmlns:cas' => 'http://www.yale.edu/tp/cas' do |service_response|
35
+ if success
36
+ ticket_granting_ticket = options[:service_ticket].ticket_granting_ticket
37
+ service_response.cas :authenticationSuccess do |authentication_success|
38
+ authentication_success.cas :user, ticket_granting_ticket.username
39
+ unless ticket_granting_ticket.extra_attributes.blank?
40
+ authentication_success.cas :attributes do |attributes|
41
+ ticket_granting_ticket.extra_attributes.each do |key, value|
42
+ serialize_extra_attribute(attributes, key, value)
43
+ end
44
+ end
45
+ end
46
+ if options[:proxy_granting_ticket]
47
+ proxy_granting_ticket = options[:proxy_granting_ticket]
48
+ authentication_success.cas :proxyGrantingTicket, proxy_granting_ticket.iou
49
+ end
50
+ end
51
+ else
52
+ service_response.cas :authenticationFailure, options[:error_message], code: options[:error_code]
53
+ end
54
+ end
55
+ xml.target!
56
+ end
57
+
58
+ def serialize_extra_attribute(builder, key, value)
59
+ if value.kind_of?(String) || value.kind_of?(Numeric) || value.kind_of?(Symbol)
60
+ builder.cas key, "#{value}"
61
+ elsif value.kind_of?(Numeric)
62
+ builder.cas key, value.to_s
63
+ else
64
+ builder.cas key do
65
+ builder.cdata! value.to_yaml
66
+ end
67
+ end
68
+ end
69
+ end
@@ -6,6 +6,7 @@ module CASinoCore
6
6
  autoload :LoginCredentialAcceptor, 'casino_core/processor/login_credential_acceptor.rb'
7
7
  autoload :LoginCredentialRequestor, 'casino_core/processor/login_credential_requestor.rb'
8
8
  autoload :Logout, 'casino_core/processor/logout.rb'
9
+ autoload :ServiceTicketValidator, 'casino_core/processor/service_ticket_validator.rb'
9
10
  autoload :SessionDestroyer, 'casino_core/processor/session_destroyer.rb'
10
11
  autoload :SessionOverview, 'casino_core/processor/session_overview.rb'
11
12
 
@@ -7,8 +7,12 @@ module CASinoCore
7
7
  CASinoCore::RakeTasks.load_tasks
8
8
  end
9
9
 
10
- initializer "casino_core.load_configuration" do
10
+ initializer 'casino_core.load_configuration' do
11
11
  CASinoCore.setup Rails.env
12
12
  end
13
+
14
+ initializer 'casino_core.setup_logger' do
15
+ CASinoCore::Settings.logger = Rails.logger
16
+ end
13
17
  end
14
18
  end
@@ -3,7 +3,7 @@ require 'casino_core/authenticator'
3
3
  module CASinoCore
4
4
  class Settings
5
5
  class << self
6
- attr_accessor :login_ticket, :service_ticket, :authenticators
6
+ attr_accessor :login_ticket, :service_ticket, :authenticators, :logger
7
7
  def init(config = {})
8
8
  config.each do |key,value|
9
9
  if respond_to?("#{key}=")
@@ -12,6 +12,10 @@ module CASinoCore
12
12
  end
13
13
  end
14
14
 
15
+ def logger
16
+ @logger ||= ::Logger.new(STDOUT)
17
+ end
18
+
15
19
  def authenticators=(authenticators)
16
20
  @authenticators = []
17
21
  authenticators.each do |authenticator|
@@ -13,4 +13,11 @@ describe CASinoCore::Model::LoginTicket do
13
13
  described_class.find_by_ticket('LT-12345').should be_false
14
14
  end
15
15
  end
16
+
17
+ describe '#to_s' do
18
+ it 'returns the ticket identifier' do
19
+ ticket = described_class.new ticket: 'LT-12345'
20
+ "#{ticket}".should == ticket.ticket
21
+ end
22
+ end
16
23
  end
@@ -37,18 +37,18 @@ describe CASinoCore::Processor::LegacyValidator do
37
37
  end
38
38
 
39
39
  context 'with renew flag' do
40
- let(:parameters) { { service: service, ticket: service_ticket.ticket, renew: 'true' }}
40
+ let(:parameters_with_renew) { parameters.merge renew: 'true' }
41
41
 
42
42
  context 'with a service ticket without issued_from_credentials flag' do
43
43
  it 'consumes the service ticket' do
44
- processor.process(parameters)
44
+ processor.process(parameters_with_renew)
45
45
  service_ticket.reload
46
46
  service_ticket.consumed.should == true
47
47
  end
48
48
 
49
49
  it 'calls the #validation_failed method on the listener' do
50
50
  listener.should_receive(:validation_failed).with("no\n\n")
51
- processor.process(parameters)
51
+ processor.process(parameters_with_renew)
52
52
  end
53
53
  end
54
54
 
@@ -59,14 +59,14 @@ describe CASinoCore::Processor::LegacyValidator do
59
59
  end
60
60
 
61
61
  it 'consumes the service ticket' do
62
- processor.process(parameters)
62
+ processor.process(parameters_with_renew)
63
63
  service_ticket.reload
64
64
  service_ticket.consumed.should == true
65
65
  end
66
66
 
67
67
  it 'calls the #validation_succeeded method on the listener' do
68
68
  listener.should_receive(:validation_succeeded).with("yes\ntest\n")
69
- processor.process(parameters)
69
+ processor.process(parameters_with_renew)
70
70
  end
71
71
  end
72
72
  end
@@ -0,0 +1,123 @@
1
+ require 'spec_helper'
2
+
3
+ describe CASinoCore::Processor::ServiceTicketValidator do
4
+ describe '#process' do
5
+ let(:listener) { Object.new }
6
+ let(:processor) { described_class.new(listener) }
7
+ let(:user_agent) { 'TestBrowser 1.0' }
8
+ let(:ticket_granting_ticket) {
9
+ CASinoCore::Model::TicketGrantingTicket.create!({
10
+ ticket: 'TGC-HXdkW233TsRtiqYGq4b8U7',
11
+ username: 'test',
12
+ extra_attributes: nil,
13
+ user_agent: user_agent
14
+ })
15
+ }
16
+ let(:service) { 'https://example.com/cas-service' }
17
+ let(:service_ticket) { ticket_granting_ticket.service_tickets.create! ticket: 'ST-2nOcXx56dtPTsB069yYf0h', service: service }
18
+ let(:parameters) { { service: service, ticket: service_ticket.ticket }}
19
+
20
+ let(:regex_failure) { /\A\<cas\:serviceResponse.*\n.*authenticationFailure/ }
21
+ let(:regex_success) { /\A\<cas\:serviceResponse.*\n.*authenticationSuccess/ }
22
+
23
+ before(:each) do
24
+ listener.stub(:validation_failed)
25
+ listener.stub(:validation_succeeded)
26
+ end
27
+
28
+ context 'with an unconsumed service ticket' do
29
+ context 'without renew flag' do
30
+ it 'consumes the service ticket' do
31
+ processor.process(parameters)
32
+ service_ticket.reload
33
+ service_ticket.consumed.should == true
34
+ end
35
+
36
+ it 'calls the #validation_succeeded method on the listener' do
37
+ listener.should_receive(:validation_succeeded).with(regex_success)
38
+ processor.process(parameters)
39
+ end
40
+ end
41
+
42
+ context 'with renew flag' do
43
+ let(:parameters_with_renew) { parameters.merge renew: 'true' }
44
+
45
+ context 'with a service ticket without issued_from_credentials flag' do
46
+ it 'consumes the service ticket' do
47
+ processor.process(parameters_with_renew)
48
+ service_ticket.reload
49
+ service_ticket.consumed.should == true
50
+ end
51
+
52
+ it 'calls the #validation_failed method on the listener' do
53
+ listener.should_receive(:validation_failed).with(regex_failure)
54
+ processor.process(parameters_with_renew)
55
+ end
56
+ end
57
+
58
+ context 'with a service ticket with issued_from_credentials flag' do
59
+ before(:each) do
60
+ service_ticket.issued_from_credentials = true
61
+ service_ticket.save!
62
+ end
63
+
64
+ it 'consumes the service ticket' do
65
+ processor.process(parameters_with_renew)
66
+ service_ticket.reload
67
+ service_ticket.consumed.should == true
68
+ end
69
+
70
+ it 'calls the #validation_succeeded method on the listener' do
71
+ listener.should_receive(:validation_succeeded).with(regex_success)
72
+ processor.process(parameters_with_renew)
73
+ end
74
+ end
75
+ end
76
+
77
+ context 'with proxy-granting ticket callback server' do
78
+ let(:parameters_with_pgt_url) { parameters.merge pgtUrl: 'https://www.example.com/' }
79
+
80
+ before(:each) do
81
+ stub_request(:get, /https:\/\/www\.example\.com\/\?pgtId=[^&]+&pgtIou=[^&]+/)
82
+ end
83
+
84
+ it 'calls the #validation_succeeded method on the listener' do
85
+ listener.should_receive(:validation_succeeded).with(regex_success)
86
+ processor.process(parameters_with_pgt_url)
87
+ end
88
+
89
+ it 'includes the PGTIOU in the response' do
90
+ listener.should_receive(:validation_succeeded).with(/\<cas\:proxyGrantingTicket\>\n?\s*PGTIOU-.+/)
91
+ processor.process(parameters_with_pgt_url)
92
+ end
93
+
94
+ it 'creates a proxy-granting ticket' do
95
+ lambda do
96
+ processor.process(parameters_with_pgt_url)
97
+ end.should change(service_ticket.proxy_granting_tickets, :count).by(1)
98
+ end
99
+
100
+ it 'contacts the callback server' do
101
+ processor.process(parameters_with_pgt_url)
102
+ proxy_granting_ticket = CASinoCore::Model::ProxyGrantingTicket.last
103
+ WebMock.should have_requested(:get, 'https://www.example.com').with(query: {
104
+ pgtId: proxy_granting_ticket.ticket,
105
+ pgtIou: proxy_granting_ticket.iou
106
+ })
107
+ end
108
+ end
109
+ end
110
+
111
+ context 'with a consumed service ticket' do
112
+ before(:each) do
113
+ service_ticket.consumed = true
114
+ service_ticket.save!
115
+ end
116
+
117
+ it 'calls the #validation_failed method on the listener' do
118
+ listener.should_receive(:validation_failed).with(regex_failure)
119
+ processor.process(parameters)
120
+ end
121
+ end
122
+ end
123
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,8 @@
1
- require 'casino_core'
2
1
  require 'database_cleaner'
2
+ require 'logger'
3
+ require 'webmock/rspec'
4
+ require 'casino_core'
5
+ require 'simplecov'
3
6
 
4
7
  # This file was generated by the `rspec --init` command. Conventionally, all
5
8
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
@@ -16,7 +19,10 @@ RSpec.configure do |config|
16
19
  # --seed 1234
17
20
  config.order = 'random'
18
21
 
22
+ SimpleCov.start
23
+
19
24
  CASinoCore.setup 'test'
25
+ CASinoCore::Settings.logger.level = ::Logger::Severity::UNKNOWN
20
26
 
21
27
  config.before(:suite) do
22
28
  DatabaseCleaner.strategy = :transaction
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: casino_core
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.5
5
+ version: 0.0.6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Nils Caspar
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-12-19 00:00:00 Z
13
+ date: 2012-12-24 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -133,6 +133,17 @@ dependencies:
133
133
  type: :development
134
134
  prerelease: false
135
135
  version_requirements: *id011
136
+ - !ruby/object:Gem::Dependency
137
+ name: webmock
138
+ requirement: &id012 !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: "0"
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: *id012
136
147
  description: A CAS server core library.
137
148
  email: ncaspar@me.com
138
149
  executables: []
@@ -167,6 +178,7 @@ files:
167
178
  - db/migrate/20121125091934_add_issued_from_credentials_to_service_tickets.rb
168
179
  - db/migrate/20121125185415_create_proxy_granting_tickets.rb
169
180
  - db/migrate/20121125190013_tickets_should_be_unique.rb
181
+ - db/migrate/20121223135227_proxy_granting_tickets_belongs_to_service_ticket.rb
170
182
  - db/schema.rb
171
183
  - lib/casino_core.rb
172
184
  - lib/casino_core/authenticator.rb
@@ -175,6 +187,7 @@ files:
175
187
  - lib/casino_core/helper/browser.rb
176
188
  - lib/casino_core/helper/logger.rb
177
189
  - lib/casino_core/helper/login_tickets.rb
190
+ - lib/casino_core/helper/proxy_granting_tickets.rb
178
191
  - lib/casino_core/helper/service_tickets.rb
179
192
  - lib/casino_core/helper/ticket_granting_tickets.rb
180
193
  - lib/casino_core/helper/tickets.rb
@@ -189,6 +202,7 @@ files:
189
202
  - lib/casino_core/processor/login_credential_acceptor.rb
190
203
  - lib/casino_core/processor/login_credential_requestor.rb
191
204
  - lib/casino_core/processor/logout.rb
205
+ - lib/casino_core/processor/service_ticket_validator.rb
192
206
  - lib/casino_core/processor/session_destroyer.rb
193
207
  - lib/casino_core/processor/session_overview.rb
194
208
  - lib/casino_core/railtie.rb
@@ -203,6 +217,7 @@ files:
203
217
  - spec/processor/login_credential_acceptor_spec.rb
204
218
  - spec/processor/login_credential_requestor_spec.rb
205
219
  - spec/processor/logout_spec.rb
220
+ - spec/processor/service_ticket_validator_spec.rb
206
221
  - spec/processor/session_destroyer_spec.rb
207
222
  - spec/processor/session_overview_spec.rb
208
223
  - spec/spec_helper.rb
@@ -219,7 +234,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
219
234
  requirements:
220
235
  - - ">="
221
236
  - !ruby/object:Gem::Version
222
- hash: -263623959609363885
237
+ hash: 209769528785287815
223
238
  segments:
224
239
  - 0
225
240
  version: "0"