casino_core 1.0.2 → 1.0.3

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
@@ -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"