casino_core 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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"