casino_core 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -18,6 +18,7 @@ group :development, :test do
18
18
  gem 'sqlite3'
19
19
  gem 'database_cleaner'
20
20
  gem 'webmock'
21
+ gem 'nokogiri'
21
22
  end
22
23
 
23
24
  gem 'activerecord', '~> 3.2.9'
@@ -27,6 +27,7 @@ GEM
27
27
  rdoc
28
28
  json (1.7.5)
29
29
  multi_json (1.5.0)
30
+ nokogiri (1.5.6)
30
31
  rake (10.0.3)
31
32
  rdoc (3.12)
32
33
  json (~> 1.4)
@@ -60,6 +61,7 @@ DEPENDENCIES
60
61
  bundler (~> 1.2.0)
61
62
  database_cleaner
62
63
  jeweler (~> 1.8.4)
64
+ nokogiri
63
65
  redcarpet
64
66
  rspec (~> 2.12.0)
65
67
  simplecov (~> 0.7.1)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.2
1
+ 1.0.3
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "casino_core"
8
- s.version = "1.0.2"
8
+ s.version = "1.0.3"
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"]
@@ -89,6 +89,7 @@ Gem::Specification.new do |s|
89
89
  "spec/authenticator/static_spec.rb",
90
90
  "spec/model/login_ticket_spec.rb",
91
91
  "spec/model/proxy_ticket_spec.rb",
92
+ "spec/model/service_ticket/single_sign_out_notifier_spec.rb",
92
93
  "spec/model/service_ticket_spec.rb",
93
94
  "spec/model/ticket_granting_ticket_spec.rb",
94
95
  "spec/processor/legacy_validator_spec.rb",
@@ -124,6 +125,7 @@ Gem::Specification.new do |s|
124
125
  s.add_development_dependency(%q<sqlite3>, [">= 0"])
125
126
  s.add_development_dependency(%q<database_cleaner>, [">= 0"])
126
127
  s.add_development_dependency(%q<webmock>, [">= 0"])
128
+ s.add_development_dependency(%q<nokogiri>, [">= 0"])
127
129
  else
128
130
  s.add_dependency(%q<activerecord>, ["~> 3.2.9"])
129
131
  s.add_dependency(%q<addressable>, ["~> 2.3.2"])
@@ -137,6 +139,7 @@ Gem::Specification.new do |s|
137
139
  s.add_dependency(%q<sqlite3>, [">= 0"])
138
140
  s.add_dependency(%q<database_cleaner>, [">= 0"])
139
141
  s.add_dependency(%q<webmock>, [">= 0"])
142
+ s.add_dependency(%q<nokogiri>, [">= 0"])
140
143
  end
141
144
  else
142
145
  s.add_dependency(%q<activerecord>, ["~> 3.2.9"])
@@ -151,6 +154,7 @@ Gem::Specification.new do |s|
151
154
  s.add_dependency(%q<sqlite3>, [">= 0"])
152
155
  s.add_dependency(%q<database_cleaner>, [">= 0"])
153
156
  s.add_dependency(%q<webmock>, [">= 0"])
157
+ s.add_dependency(%q<nokogiri>, [">= 0"])
154
158
  end
155
159
  end
156
160
 
@@ -13,7 +13,7 @@ module CASinoCore
13
13
  def acquire_proxy_granting_ticket(pgt_url, service_ticket)
14
14
  begin
15
15
  return contact_callback_server(pgt_url, service_ticket)
16
- rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError
16
+ rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
17
17
  logger.warn "Exception while communicating with proxy-granting ticket callback server: #{e.message}"
18
18
  end
19
19
  nil
@@ -16,7 +16,7 @@ class CASinoCore::Model::ServiceTicket < ActiveRecord::Base
16
16
  end
17
17
 
18
18
  def self.cleanup_consumed
19
- self.destroy_all(['created_at < ? AND consumed = ?', CASinoCore::Settings.service_ticket[:lifetime_consumed].seconds.ago, true])
19
+ self.destroy_all(['(ticket_granting_ticket_id IS NULL OR created_at < ?) AND consumed = ?', CASinoCore::Settings.service_ticket[:lifetime_consumed].seconds.ago, true])
20
20
  end
21
21
 
22
22
  def self.cleanup_consumed_hard
@@ -20,8 +20,13 @@ class CASinoCore::Model::ServiceTicket::SingleSignOutNotifier
20
20
  private
21
21
  def build_xml
22
22
  xml = Builder::XmlMarkup.new(indent: 2)
23
- xml.samlp :LogoutRequest, ID: SecureRandom.uuid, Version: '2.0', IsseInstant: Time.now do |logout_request|
24
- logout_request.samlp :NameID, '@NOT_USED@'
23
+ xml.samlp :LogoutRequest,
24
+ 'xmlns:samlp' => 'urn:oasis:names:tc:SAML:2.0:protocol',
25
+ 'xmlns:saml' => 'urn:oasis:names:tc:SAML:2.0:assertion',
26
+ ID: SecureRandom.uuid,
27
+ Version: '2.0',
28
+ IssueInstant: Time.now do |logout_request|
29
+ logout_request.saml :NameID, '@NOT_USED@'
25
30
  logout_request.samlp :SessionIndex, @service_ticket.ticket
26
31
  end
27
32
  xml.target!
@@ -49,7 +54,7 @@ class CASinoCore::Model::ServiceTicket::SingleSignOutNotifier
49
54
  return false
50
55
  end
51
56
  end
52
- rescue Exception => e
57
+ rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
53
58
  logger.warn "Failed to send logout notification to service #{uri} due to #{e}"
54
59
  return false
55
60
  end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+ require 'nokogiri'
3
+
4
+ describe CASinoCore::Model::ServiceTicket::SingleSignOutNotifier do
5
+ let(:ticket) { 'ST-123456' }
6
+ let(:service) { 'http://www.example.org/' }
7
+ let(:service_ticket) { CASinoCore::Model::ServiceTicket.create ticket: ticket, service: service }
8
+ let(:notifier) { described_class.new service_ticket }
9
+
10
+ describe '#notify' do
11
+ before(:each) do
12
+ stub_request(:post, service)
13
+ end
14
+
15
+ it 'sends a valid Single Sign Out XML to the service URL' do
16
+ notifier.notify
17
+ WebMock.should have_requested(:post, service).with { |request|
18
+ post_params = CGI.parse(request.body)
19
+ post_params.should_not be_nil
20
+ xml = Nokogiri::XML post_params['logoutRequest'].first
21
+ xml.at_xpath('/samlp:LogoutRequest/samlp:SessionIndex').text.strip.should == service_ticket.ticket
22
+ }
23
+ end
24
+
25
+ context 'when it is a success' do
26
+ it 'returns true' do
27
+ notifier.notify.should == true
28
+ end
29
+ end
30
+
31
+ context 'with server error' do
32
+ [404, 500].each do |status_code|
33
+ context "#{status_code}" do
34
+ before(:each) do
35
+ stub_request(:post, service).to_return status: status_code
36
+ end
37
+
38
+ it 'returns false' do
39
+ notifier.notify.should == false
40
+ end
41
+ end
42
+ end
43
+
44
+ context 'connection timeout' do
45
+ before(:each) do
46
+ stub_request(:post, service).to_raise Timeout::Error
47
+ end
48
+
49
+ it 'returns false' do
50
+ notifier.notify.should == false
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -38,6 +38,22 @@ describe CASinoCore::Model::ServiceTicket do
38
38
  end.should change(described_class, :count).by(-1)
39
39
  described_class.find_by_ticket('ST-12345').should be_false
40
40
  end
41
+
42
+ it 'deletes consumed service tickets without ticket_granting_ticket' do
43
+ consumed_ticket.ticket_granting_ticket_id = nil
44
+ consumed_ticket.save!
45
+ lambda do
46
+ described_class.cleanup_consumed
47
+ end.should change(described_class, :count).by(-1)
48
+ described_class.find_by_ticket('ST-12345').should be_false
49
+ end
50
+
51
+ it 'does not delete unexpired service tickets' do
52
+ consumed_ticket # create the ticket
53
+ lambda do
54
+ described_class.cleanup_consumed
55
+ end.should_not change(described_class, :count)
56
+ end
41
57
  end
42
58
 
43
59
  describe '#destroy' do
@@ -57,19 +57,6 @@ describe CASinoCore::Processor::SessionDestroyer do
57
57
  listener.should_receive(:ticket_deleted).with(no_args)
58
58
  processor.process(params, cookies, user_agent)
59
59
  end
60
-
61
- it 'deletes the dependent service ticket' do
62
- service_ticket.ticket # creates the service ticket
63
- lambda {
64
- processor.process(params, cookies, user_agent)
65
- }.should change(CASinoCore::Model::ServiceTicket, :count).by(-1)
66
- end
67
-
68
- it 'nullifies the dependent service ticket if destroying fails' do
69
- lambda {
70
- processor.process(params, cookies, user_agent)
71
- }.should change { consumed_service_ticket.reload.ticket_granting_ticket_id }.to(nil)
72
- end
73
60
  end
74
61
 
75
62
  context 'with an invalid ticket-granting ticket' do
@@ -83,10 +83,11 @@ require 'spec_helper'
83
83
  end
84
84
 
85
85
  context 'with proxy-granting ticket callback server' do
86
- let(:parameters_with_pgt_url) { parameters.merge pgtUrl: "https://www.example.org" }
86
+ let(:pgt_url) { 'https://www.example.org' }
87
+ let(:parameters_with_pgt_url) { parameters.merge pgtUrl: pgt_url }
87
88
 
88
89
  before(:each) do
89
- stub_request(:get, /https:\/\/www\.example\.org\/\?pgtId=[^&]+&pgtIou=[^&]+/)
90
+ stub_request(:get, /#{pgt_url}\/\?pgtId=[^&]+&pgtIou=[^&]+/)
90
91
  end
91
92
 
92
93
  it 'calls the #validation_succeeded method on the listener' do
@@ -113,6 +114,40 @@ require 'spec_helper'
113
114
  pgtIou: proxy_granting_ticket.iou
114
115
  })
115
116
  end
117
+
118
+ context 'when callback server gives an error' do
119
+ before(:each) do
120
+ stub_request(:get, /#{pgt_url}.*/).to_return status: 404
121
+ end
122
+
123
+ it 'calls the #validation_succeeded method on the listener' do
124
+ listener.should_receive(:validation_succeeded).with(regex_success)
125
+ processor.process(parameters_with_pgt_url)
126
+ end
127
+
128
+ it 'does not create a proxy-granting ticket' do
129
+ lambda do
130
+ processor.process(parameters_with_pgt_url)
131
+ end.should_not change(service_ticket.proxy_granting_tickets, :count)
132
+ end
133
+ end
134
+
135
+ context 'when callback server is unreachable' do
136
+ before(:each) do
137
+ stub_request(:get, /#{pgt_url}.*/).to_raise(Timeout::Error)
138
+ end
139
+
140
+ it 'calls the #validation_succeeded method on the listener' do
141
+ listener.should_receive(:validation_succeeded).with(regex_success)
142
+ processor.process(parameters_with_pgt_url)
143
+ end
144
+
145
+ it 'does not create a proxy-granting ticket' do
146
+ lambda do
147
+ processor.process(parameters_with_pgt_url)
148
+ end.should_not change(service_ticket.proxy_granting_tickets, :count)
149
+ end
150
+ end
116
151
  end
117
152
  end
118
153
 
@@ -19,7 +19,9 @@ RSpec.configure do |config|
19
19
  # --seed 1234
20
20
  config.order = 'random'
21
21
 
22
- SimpleCov.start
22
+ SimpleCov.start do
23
+ add_filter '/spec'
24
+ end
23
25
 
24
26
  CASinoCore.setup 'test'
25
27
  CASinoCore::Settings.logger.level = ::Logger::Severity::UNKNOWN
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: casino_core
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.0.2
5
+ version: 1.0.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Nils Caspar
@@ -144,6 +144,17 @@ dependencies:
144
144
  type: :development
145
145
  prerelease: false
146
146
  version_requirements: *id012
147
+ - !ruby/object:Gem::Dependency
148
+ name: nokogiri
149
+ requirement: &id013 !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: "0"
155
+ type: :development
156
+ prerelease: false
157
+ version_requirements: *id013
147
158
  description: A CAS server core library.
148
159
  email: ncaspar@me.com
149
160
  executables: []
@@ -226,6 +237,7 @@ files:
226
237
  - spec/authenticator/static_spec.rb
227
238
  - spec/model/login_ticket_spec.rb
228
239
  - spec/model/proxy_ticket_spec.rb
240
+ - spec/model/service_ticket/single_sign_out_notifier_spec.rb
229
241
  - spec/model/service_ticket_spec.rb
230
242
  - spec/model/ticket_granting_ticket_spec.rb
231
243
  - spec/processor/legacy_validator_spec.rb
@@ -251,7 +263,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
251
263
  requirements:
252
264
  - - ">="
253
265
  - !ruby/object:Gem::Version
254
- hash: 4407808327317958750
266
+ hash: 1358580775161495326
255
267
  segments:
256
268
  - 0
257
269
  version: "0"