casino_core 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. data/Gemfile +1 -0
  2. data/Gemfile.lock +3 -0
  3. data/VERSION +1 -1
  4. data/casino_core.gemspec +12 -3
  5. data/config/cas.yml +10 -11
  6. data/db/migrate/20121231114141_add_authenticator_to_ticket_granting_tickets.rb +15 -0
  7. data/db/schema.rb +3 -2
  8. data/lib/casino_core/builder/ticket_validation_response.rb +0 -2
  9. data/lib/casino_core/model/ticket_granting_ticket.rb +2 -2
  10. data/lib/casino_core/processor/login_credential_acceptor.rb +11 -12
  11. data/lib/casino_core/processor/login_credential_requestor.rb +7 -2
  12. data/lib/casino_core/processor/session_overview.rb +4 -1
  13. data/lib/casino_core/settings.rb +3 -3
  14. data/spec/model/service_ticket/single_sign_out_notifier_spec.rb +3 -4
  15. data/spec/model/ticket_granting_ticket_spec.rb +6 -13
  16. data/spec/processor/legacy_validator_spec.rb +2 -12
  17. data/spec/processor/login_credential_acceptor_spec.rb +10 -1
  18. data/spec/processor/login_credential_requestor_spec.rb +26 -10
  19. data/spec/processor/logout_spec.rb +2 -9
  20. data/spec/processor/proxy_ticket_provider_spec.rb +1 -10
  21. data/spec/processor/proxy_ticket_validator_spec.rb +13 -14
  22. data/spec/processor/session_destroyer_spec.rb +6 -34
  23. data/spec/processor/session_overview_spec.rb +15 -17
  24. data/spec/processor/ticket_validator_spec.rb +16 -14
  25. data/spec/spec_helper.rb +11 -0
  26. data/spec/support/factories/login_ticket_factory.rb +16 -0
  27. data/spec/support/factories/proxy_granting_ticket_factory.rb +16 -0
  28. data/spec/support/factories/proxy_ticket_factory.rb +17 -0
  29. data/spec/support/factories/service_ticket_factory.rb +17 -0
  30. data/spec/support/factories/ticket_granting_ticket_factory.rb +13 -0
  31. metadata +20 -3
data/Gemfile CHANGED
@@ -19,6 +19,7 @@ group :development, :test do
19
19
  gem 'database_cleaner'
20
20
  gem 'webmock'
21
21
  gem 'nokogiri'
22
+ gem 'factory_girl', '~> 4.1.0'
22
23
  end
23
24
 
24
25
  gem 'activerecord', '~> 3.2.9'
@@ -18,6 +18,8 @@ GEM
18
18
  crack (0.3.1)
19
19
  database_cleaner (0.9.1)
20
20
  diff-lcs (1.1.3)
21
+ factory_girl (4.1.0)
22
+ activesupport (>= 3.0.0)
21
23
  git (1.2.5)
22
24
  i18n (0.6.1)
23
25
  jeweler (1.8.4)
@@ -60,6 +62,7 @@ DEPENDENCIES
60
62
  addressable (~> 2.3.2)
61
63
  bundler (~> 1.2.0)
62
64
  database_cleaner
65
+ factory_girl (~> 4.1.0)
63
66
  jeweler (~> 1.8.4)
64
67
  nokogiri
65
68
  redcarpet
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.3
1
+ 1.0.4
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "casino_core"
8
- s.version = "1.0.3"
8
+ s.version = "1.0.4"
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-29"
12
+ s.date = "2012-12-30"
13
13
  s.description = "A CAS server core library."
14
14
  s.email = "ncaspar@me.com"
15
15
  s.extra_rdoc_files = [
@@ -48,6 +48,7 @@ Gem::Specification.new do |s|
48
48
  "db/migrate/20121225231713_no_default_granter_type.rb",
49
49
  "db/migrate/20121226192211_fix_index_for_granter_on_proxy_granting_ticket.rb",
50
50
  "db/migrate/20121226211511_allow_service_tickets_without_ticket_granting_ticket.rb",
51
+ "db/migrate/20121231114141_add_authenticator_to_ticket_granting_tickets.rb",
51
52
  "db/schema.rb",
52
53
  "lib/casino_core.rb",
53
54
  "lib/casino_core/authenticator.rb",
@@ -101,7 +102,12 @@ Gem::Specification.new do |s|
101
102
  "spec/processor/session_destroyer_spec.rb",
102
103
  "spec/processor/session_overview_spec.rb",
103
104
  "spec/processor/ticket_validator_spec.rb",
104
- "spec/spec_helper.rb"
105
+ "spec/spec_helper.rb",
106
+ "spec/support/factories/login_ticket_factory.rb",
107
+ "spec/support/factories/proxy_granting_ticket_factory.rb",
108
+ "spec/support/factories/proxy_ticket_factory.rb",
109
+ "spec/support/factories/service_ticket_factory.rb",
110
+ "spec/support/factories/ticket_granting_ticket_factory.rb"
105
111
  ]
106
112
  s.homepage = "http://github.com/pencil/CASinoCore"
107
113
  s.licenses = ["MIT"]
@@ -126,6 +132,7 @@ Gem::Specification.new do |s|
126
132
  s.add_development_dependency(%q<database_cleaner>, [">= 0"])
127
133
  s.add_development_dependency(%q<webmock>, [">= 0"])
128
134
  s.add_development_dependency(%q<nokogiri>, [">= 0"])
135
+ s.add_development_dependency(%q<factory_girl>, ["~> 4.1.0"])
129
136
  else
130
137
  s.add_dependency(%q<activerecord>, ["~> 3.2.9"])
131
138
  s.add_dependency(%q<addressable>, ["~> 2.3.2"])
@@ -140,6 +147,7 @@ Gem::Specification.new do |s|
140
147
  s.add_dependency(%q<database_cleaner>, [">= 0"])
141
148
  s.add_dependency(%q<webmock>, [">= 0"])
142
149
  s.add_dependency(%q<nokogiri>, [">= 0"])
150
+ s.add_dependency(%q<factory_girl>, ["~> 4.1.0"])
143
151
  end
144
152
  else
145
153
  s.add_dependency(%q<activerecord>, ["~> 3.2.9"])
@@ -155,6 +163,7 @@ Gem::Specification.new do |s|
155
163
  s.add_dependency(%q<database_cleaner>, [">= 0"])
156
164
  s.add_dependency(%q<webmock>, [">= 0"])
157
165
  s.add_dependency(%q<nokogiri>, [">= 0"])
166
+ s.add_dependency(%q<factory_girl>, ["~> 4.1.0"])
158
167
  end
159
168
  end
160
169
 
@@ -7,25 +7,24 @@ defaults: &defaults
7
7
  proxy_ticket:
8
8
  lifetime_unconsumed: 300
9
9
  lifetime_consumed: 86400
10
-
11
- development:
12
- <<: *defaults
13
10
  authenticators:
14
- -
11
+ static_1:
15
12
  class: "CASinoCore::Authenticator::Static"
16
13
  options:
17
14
  users:
18
15
  testuser:
19
16
  password: "foobar123"
20
17
  name: "Test User"
21
-
22
- test:
23
- <<: *defaults
24
- authenticators:
25
- -
18
+ static_2:
26
19
  class: "CASinoCore::Authenticator::Static"
27
20
  options:
28
21
  users:
29
- testuser:
30
- password: "foobar123"
22
+ example:
23
+ password: "dito123"
31
24
  name: "Test User"
25
+
26
+ development:
27
+ <<: *defaults
28
+
29
+ test:
30
+ <<: *defaults
@@ -0,0 +1,15 @@
1
+ class AddAuthenticatorToTicketGrantingTickets < ActiveRecord::Migration
2
+ def up
3
+ add_column :ticket_granting_tickets, :authenticator, :string, null: true
4
+ CASinoCore::Model::TicketGrantingTicket.delete_all
5
+ change_column :ticket_granting_tickets, :authenticator, :string, null: false
6
+ add_index :ticket_granting_tickets, [:authenticator, :username]
7
+ remove_index :ticket_granting_tickets, :username
8
+ end
9
+
10
+ def down
11
+ remove_index :ticket_granting_tickets, [:authenticator, :username]
12
+ remove_column :ticket_granting_tickets, :authenticator
13
+ add_index :ticket_granting_tickets, :username
14
+ end
15
+ end
@@ -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 => 20121226211511) do
14
+ ActiveRecord::Schema.define(:version => 20121231114141) do
15
15
 
16
16
  create_table "login_tickets", :force => true do |t|
17
17
  t.string "ticket", :null => false
@@ -67,9 +67,10 @@ ActiveRecord::Schema.define(:version => 20121226211511) do
67
67
  t.datetime "created_at", :null => false
68
68
  t.datetime "updated_at", :null => false
69
69
  t.string "user_agent"
70
+ t.string "authenticator", :null => false
70
71
  end
71
72
 
73
+ add_index "ticket_granting_tickets", ["authenticator", "username"], :name => "index_ticket_granting_tickets_on_authenticator_and_username"
72
74
  add_index "ticket_granting_tickets", ["ticket"], :name => "index_ticket_granting_tickets_on_ticket", :unique => true
73
- add_index "ticket_granting_tickets", ["username"], :name => "index_ticket_granting_tickets_on_username"
74
75
 
75
76
  end
@@ -37,8 +37,6 @@ class CASinoCore::Builder::TicketValidationResponse < CASinoCore::Builder
37
37
  def serialize_extra_attribute(builder, key, value)
38
38
  if value.kind_of?(String) || value.kind_of?(Numeric) || value.kind_of?(Symbol)
39
39
  builder.cas key, "#{value}"
40
- elsif value.kind_of?(Numeric)
41
- builder.cas key, value.to_s
42
40
  else
43
41
  builder.cas key do |container|
44
42
  container.cdata! value.to_yaml
@@ -1,7 +1,7 @@
1
1
  require 'casino_core/model'
2
2
 
3
3
  class CASinoCore::Model::TicketGrantingTicket < ActiveRecord::Base
4
- attr_accessible :ticket, :username, :user_agent, :extra_attributes
4
+ attr_accessible :ticket, :authenticator, :username, :user_agent, :extra_attributes
5
5
  serialize :extra_attributes, Hash
6
6
  validates :ticket, uniqueness: true
7
7
  has_many :service_tickets
@@ -18,7 +18,7 @@ class CASinoCore::Model::TicketGrantingTicket < ActiveRecord::Base
18
18
  if other_ticket.nil?
19
19
  false
20
20
  else
21
- other_ticket.username == self.username
21
+ other_ticket.username == self.username && other_ticket.authenticator == self.authenticator
22
22
  end
23
23
  end
24
24
 
@@ -23,9 +23,9 @@ class CASinoCore::Processor::LoginCredentialAcceptor < CASinoCore::Processor
23
23
  params ||= {}
24
24
  cookies ||= {}
25
25
  if login_ticket_valid?(params[:lt])
26
- user_data = validate_login_credentials(params[:username], params[:password])
27
- if !user_data.nil?
28
- ticket_granting_ticket = acquire_ticket_granting_ticket(user_data, user_agent)
26
+ authentication_result = validate_login_credentials(params[:username], params[:password])
27
+ if !authentication_result.nil?
28
+ ticket_granting_ticket = acquire_ticket_granting_ticket(authentication_result, user_agent)
29
29
  url = unless params[:service].nil?
30
30
  acquire_service_ticket(ticket_granting_ticket, params[:service], true).service_with_ticket_url
31
31
  end
@@ -55,24 +55,23 @@ class CASinoCore::Processor::LoginCredentialAcceptor < CASinoCore::Processor
55
55
  end
56
56
 
57
57
  def validate_login_credentials(username, password)
58
- user_data = nil
59
- CASinoCore::Settings.authenticators.each do |authenticator|
58
+ authentication_result = nil
59
+ CASinoCore::Settings.authenticators.each do |authenticator_name, authenticator|
60
60
  data = authenticator.validate(username, password)
61
61
  if data
62
- if data[:username].nil?
63
- data[:username] = username
64
- end
65
- user_data = data
66
- logger.info("Credentials for username '#{data[:username]}' successfully validated using #{authenticator.class}")
62
+ authentication_result = { authenticator: authenticator_name, user_data: data }
63
+ logger.info("Credentials for username '#{data[:username]}' successfully validated using authenticator '#{authenticator_name}' (#{authenticator.class})")
67
64
  break
68
65
  end
69
66
  end
70
- user_data
67
+ authentication_result
71
68
  end
72
69
 
73
- def acquire_ticket_granting_ticket(user_data, user_agent = nil)
70
+ def acquire_ticket_granting_ticket(authentication_result, user_agent = nil)
71
+ user_data = authentication_result[:user_data]
74
72
  CASinoCore::Model::TicketGrantingTicket.create!({
75
73
  ticket: random_ticket_string('TGC'),
74
+ authenticator: authentication_result[:authenticator],
76
75
  username: user_data[:username],
77
76
  extra_attributes: user_data[:extra_attributes],
78
77
  user_agent: user_agent
@@ -28,8 +28,13 @@ class CASinoCore::Processor::LoginCredentialRequestor < CASinoCore::Processor
28
28
  end
29
29
  @listener.user_logged_in(service_url_with_ticket)
30
30
  else
31
- login_ticket = acquire_login_ticket
32
- @listener.user_not_logged_in(login_ticket)
31
+ if params[:gateway] == 'true' && params[:service]
32
+ # we actually lie to the listener to simplify things
33
+ @listener.user_logged_in(params[:service])
34
+ else
35
+ login_ticket = acquire_login_ticket
36
+ @listener.user_not_logged_in(login_ticket)
37
+ end
33
38
  end
34
39
  end
35
40
  end
@@ -18,7 +18,10 @@ class CASinoCore::Processor::SessionOverview < CASinoCore::Processor
18
18
  if tgt.nil?
19
19
  @listener.user_not_logged_in
20
20
  else
21
- ticket_granting_tickets = CASinoCore::Model::TicketGrantingTicket.where(username: tgt.username).order('updated_at DESC')
21
+ ticket_granting_tickets = CASinoCore::Model::TicketGrantingTicket.where(
22
+ username: tgt.username,
23
+ authenticator: tgt.authenticator
24
+ ).order('updated_at DESC')
22
25
  @listener.ticket_granting_tickets_found(ticket_granting_tickets)
23
26
  end
24
27
  end
@@ -17,12 +17,12 @@ module CASinoCore
17
17
  end
18
18
 
19
19
  def authenticators=(authenticators)
20
- @authenticators = []
21
- authenticators.each do |authenticator|
20
+ @authenticators = {}
21
+ authenticators.each do |index, authenticator|
22
22
  unless authenticator.is_a?(CASinoCore::Authenticator)
23
23
  authenticator = authenticator[:class].constantize.new(authenticator[:options])
24
24
  end
25
- @authenticators << authenticator
25
+ @authenticators[index] = authenticator
26
26
  end
27
27
  end
28
28
  end
@@ -2,9 +2,8 @@ require 'spec_helper'
2
2
  require 'nokogiri'
3
3
 
4
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 }
5
+ let(:service_ticket) { FactoryGirl.create :service_ticket }
6
+ let(:service) { service_ticket.service }
8
7
  let(:notifier) { described_class.new service_ticket }
9
8
 
10
9
  describe '#notify' do
@@ -18,7 +17,7 @@ describe CASinoCore::Model::ServiceTicket::SingleSignOutNotifier do
18
17
  post_params = CGI.parse(request.body)
19
18
  post_params.should_not be_nil
20
19
  xml = Nokogiri::XML post_params['logoutRequest'].first
21
- xml.at_xpath('/samlp:LogoutRequest/samlp:SessionIndex').text.strip.should == service_ticket.ticket
20
+ xml.at_xpath('/samlp:LogoutRequest/samlp:SessionIndex').text.should == service_ticket.ticket
22
21
  }
23
22
  end
24
23
 
@@ -1,16 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe CASinoCore::Model::TicketGrantingTicket do
4
- let(:subject) { described_class.create! ticket: 'TGT-3ep9awhy2ty5UhL8wM1xAZ', username: 'example-user' }
5
- let(:service_ticket) {
6
- subject.service_tickets.create! ticket: 'ST-12345', service: 'https://example.com/cas-service'
7
- }
8
- let(:consumed_service_ticket) {
9
- service_ticket = subject.service_tickets.create! ticket: 'ST-n9oZvDtYkVFHj5M3s59Ws5', service: 'https://example.com/cas-service'
10
- service_ticket.consumed = true
11
- service_ticket.save!
12
- service_ticket
13
- }
4
+ let(:ticket_granting_ticket) { described_class.create! ticket: 'TGT-3ep9awhy2ty5UhL8wM1xAZ', username: 'example-user', authenticator: 'test' }
5
+ let(:service_ticket) { FactoryGirl.create :service_ticket, ticket_granting_ticket: ticket_granting_ticket }
6
+ let(:consumed_service_ticket) { FactoryGirl.create :service_ticket, :consumed, ticket_granting_ticket: ticket_granting_ticket }
14
7
 
15
8
  describe '#destroy' do
16
9
  context 'when notification for a service ticket fails' do
@@ -21,14 +14,14 @@ describe CASinoCore::Model::TicketGrantingTicket do
21
14
  it 'deletes depending proxy-granting tickets' do
22
15
  consumed_service_ticket.proxy_granting_tickets.create! ticket: 'PGT-12345', iou: 'PGTIOU-12345', pgt_url: 'bla'
23
16
  lambda {
24
- subject.destroy
17
+ ticket_granting_ticket.destroy
25
18
  }.should change(CASinoCore::Model::ProxyGrantingTicket, :count).by(-1)
26
19
  end
27
20
 
28
21
  it 'nullifies depending service tickets' do
29
22
  lambda {
30
- subject.destroy
31
- }.should change { consumed_service_ticket.reload.ticket_granting_ticket_id }.from(subject.id).to(nil)
23
+ ticket_granting_ticket.destroy
24
+ }.should change { consumed_service_ticket.reload.ticket_granting_ticket_id }.from(ticket_granting_ticket.id).to(nil)
32
25
  end
33
26
  end
34
27
  end
@@ -4,18 +4,8 @@ describe CASinoCore::Processor::LegacyValidator do
4
4
  describe '#process' do
5
5
  let(:listener) { Object.new }
6
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 }}
7
+ let(:service_ticket) { FactoryGirl.create :service_ticket }
8
+ let(:parameters) { { service: service_ticket.service, ticket: service_ticket.ticket }}
19
9
 
20
10
  before(:each) do
21
11
  listener.stub(:validation_failed)
@@ -12,8 +12,17 @@ describe CASinoCore::Processor::LoginCredentialAcceptor do
12
12
  end
13
13
  end
14
14
 
15
+ context 'with an expired login ticket' do
16
+ let(:expired_login_ticket) { FactoryGirl.create :login_ticket, :expired }
17
+
18
+ it 'calls the #invalid_login_ticket method on the listener' do
19
+ listener.should_receive(:invalid_login_ticket).with(kind_of(CASinoCore::Model::LoginTicket))
20
+ processor.process(lt: expired_login_ticket.ticket)
21
+ end
22
+ end
23
+
15
24
  context 'with a valid login ticket' do
16
- let(:login_ticket) { CASinoCore::Model::LoginTicket.create! ticket: "LT-#{Random.rand(10000000)}" }
25
+ let(:login_ticket) { FactoryGirl.create :login_ticket }
17
26
 
18
27
  context 'with invalid credentials' do
19
28
  it 'calls the #invalid_login_credentials method on the listener' do
@@ -10,18 +10,32 @@ describe CASinoCore::Processor::LoginCredentialRequestor do
10
10
  listener.should_receive(:user_not_logged_in).with(kind_of(CASinoCore::Model::LoginTicket))
11
11
  processor.process
12
12
  end
13
+
14
+ context 'with gateway parameter' do
15
+ context 'with a service' do
16
+ let(:service) { 'http://example.com/' }
17
+ let(:params) { { service: service, gateway: 'true' } }
18
+
19
+ it 'calls the #user_logged_in method on the listener' do
20
+ listener.should_receive(:user_logged_in).with(service)
21
+ processor.process(params)
22
+ end
23
+ end
24
+
25
+ context 'without a service' do
26
+ let(:params) { { gateway: 'true' } }
27
+
28
+ it 'calls the #user_not_logged_in method on the listener' do
29
+ listener.should_receive(:user_not_logged_in).with(kind_of(CASinoCore::Model::LoginTicket))
30
+ processor.process
31
+ end
32
+ end
33
+ end
13
34
  end
14
35
 
15
36
  context 'when logged in' do
16
- let(:user_agent) { 'TestBrowser 1.0' }
17
- let(:ticket_granting_ticket) {
18
- CASinoCore::Model::TicketGrantingTicket.create!({
19
- ticket: 'TGC-9H6Vx4850i2Ksp3R8hTCwO',
20
- username: 'test',
21
- extra_attributes: nil,
22
- user_agent: user_agent
23
- })
24
- }
37
+ let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
38
+ let(:user_agent) { ticket_granting_ticket.user_agent }
25
39
  let(:cookies) { { tgt: ticket_granting_ticket.ticket } }
26
40
 
27
41
  before(:each) do
@@ -64,9 +78,11 @@ describe CASinoCore::Processor::LoginCredentialRequestor do
64
78
  end
65
79
 
66
80
  context 'with a changed browser' do
81
+ let(:user_agent) { 'FooBar 1.0' }
82
+
67
83
  it 'calls the #user_not_logged_in method on the listener' do
68
84
  listener.should_receive(:user_not_logged_in).with(kind_of(CASinoCore::Model::LoginTicket))
69
- processor.process(nil, cookies)
85
+ processor.process(nil, cookies, user_agent)
70
86
  end
71
87
  end
72
88
  end
@@ -7,22 +7,15 @@ describe CASinoCore::Processor::Logout do
7
7
  let(:cookies) { { tgt: tgt } }
8
8
  let(:url) { nil }
9
9
  let(:params) { { :url => url } unless url.nil? }
10
- let(:user_agent) { 'TestBrowser 1.0' }
11
10
 
12
11
  before(:each) do
13
12
  listener.stub(:user_logged_out)
14
13
  end
15
14
 
16
15
  context 'with an existing ticket-granting ticket' do
17
- let(:ticket_granting_ticket) {
18
- CASinoCore::Model::TicketGrantingTicket.create!({
19
- ticket: 'TGC-HXdkW233TsRtiqYGq4b8U7',
20
- username: 'test',
21
- extra_attributes: nil,
22
- user_agent: user_agent
23
- })
24
- }
16
+ let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
25
17
  let(:tgt) { ticket_granting_ticket.ticket }
18
+ let(:user_agent) { ticket_granting_ticket.user_agent }
26
19
 
27
20
  it 'deletes the ticket-granting ticket' do
28
21
  processor.process(params, cookies, user_agent)
@@ -40,16 +40,7 @@ describe CASinoCore::Processor::ProxyTicketProvider do
40
40
  end
41
41
 
42
42
  context 'with a proxy-granting ticket' do
43
- let(:ticket_granting_ticket) {
44
- CASinoCore::Model::TicketGrantingTicket.create!({
45
- ticket: 'TGC-Qu6B5IVQ7RmLc972TruM9u',
46
- username: 'test'
47
- })
48
- }
49
- let(:service_ticket) { ticket_granting_ticket.service_tickets.create! ticket: 'ST-2nOcXx56dtPTsB069yYf0h', service: 'http://www.example.com/' }
50
- let(:proxy_granting_ticket) {
51
- service_ticket.proxy_granting_tickets.create! ticket: 'PGT-OIE42ZadV3B9VcaG2xMjAf', iou: 'PGTIOU-PYg4CCPQHNyyS9s6bJF6Rg', pgt_url: 'https://www.example.com/pgtUrl'
52
- }
43
+ let(:proxy_granting_ticket) { FactoryGirl.create :proxy_granting_ticket }
53
44
  let(:params_with_valid_pgt) { params.merge(pgt: proxy_granting_ticket.ticket) }
54
45
 
55
46
  it 'calls the #request_succeeded method on the listener' do
@@ -7,21 +7,20 @@ describe CASinoCore::Processor::ProxyTicketValidator do
7
7
  describe '#process' do
8
8
  let(:regex_success) { /\A<cas:serviceResponse.*\n.*authenticationSuccess/ }
9
9
 
10
+ context 'with a login ticket' do
11
+ let(:login_ticket) { FactoryGirl.create :login_ticket }
12
+ let(:parameters) { { ticket: login_ticket.ticket, service: 'http://www.example.org/' } }
13
+
14
+ it 'calls the #validation_failed method on the listener' do
15
+ listener.should_receive(:validation_failed)
16
+ processor.process(parameters)
17
+ end
18
+ end
19
+
10
20
  context 'with an unconsumed proxy ticket' do
11
- let(:ticket_granting_ticket) {
12
- CASinoCore::Model::TicketGrantingTicket.create!({
13
- ticket: 'TGC-Qu6B5IVQ7RmLc972TruM9u',
14
- username: 'test'
15
- })
16
- }
17
- let(:service_ticket) { ticket_granting_ticket.service_tickets.create! ticket: 'ST-2nOcXx56dtPTsB069yYf0h', service: 'http://www.example.com/' }
18
- let(:proxy_granting_ticket) {
19
- service_ticket.proxy_granting_tickets.create! ticket: 'PGT-OIE42ZadV3B9VcaG2xMjAf', iou: 'PGTIOU-PYg4CCPQHNyyS9s6bJF6Rg', pgt_url: 'https://www.example.com/pgtUrl'
20
- }
21
- let(:proxy_service) { 'imaps://127.0.0.1:4578/' }
22
- let(:proxy_ticket) { proxy_granting_ticket.proxy_tickets.create! ticket: 'PT-8nA7vuxuNY7RcpVoaDvuZi', service: proxy_service }
23
- let(:parameters) { { ticket: proxy_ticket.ticket, service: proxy_service } }
24
- let(:regex_proxy) { /<cas:proxies>\s*<cas:proxy>https:\/\/www.example.com\/pgtUrl<\/cas:proxy>\s*<\/cas:proxies[>]/ }
21
+ let(:proxy_ticket) { FactoryGirl.create :proxy_ticket }
22
+ let(:parameters) { { ticket: proxy_ticket.ticket, service: proxy_ticket.service } }
23
+ let(:regex_proxy) { /<cas:proxies>\s*<cas:proxy>#{proxy_ticket.proxy_granting_ticket.pgt_url}<\/cas:proxy>\s*<\/cas:proxies>/ }
25
24
 
26
25
  it 'calls the #validation_succeeded method on the listener' do
27
26
  listener.should_receive(:validation_succeeded).with(regex_success)
@@ -4,15 +4,8 @@ describe CASinoCore::Processor::SessionDestroyer do
4
4
  describe '#process' do
5
5
  let(:listener) { Object.new }
6
6
  let(:processor) { described_class.new(listener) }
7
- let(:user_agent) { 'TestBrowser 1.0' }
8
- let(:owner_ticket_granting_ticket) {
9
- CASinoCore::Model::TicketGrantingTicket.create!({
10
- ticket: 'TGC-ocCudGzZjJtrvOXJ485mt3',
11
- username: 'test',
12
- extra_attributes: nil,
13
- user_agent: user_agent
14
- })
15
- }
7
+ let(:owner_ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
8
+ let(:user_agent) { owner_ticket_granting_ticket.user_agent }
16
9
  let(:cookies) { { tgt: owner_ticket_granting_ticket.ticket } }
17
10
 
18
11
  before(:each) do
@@ -21,23 +14,9 @@ describe CASinoCore::Processor::SessionDestroyer do
21
14
  end
22
15
 
23
16
  context 'with an existing ticket-granting ticket' do
24
- let(:ticket_granting_ticket) {
25
- CASinoCore::Model::TicketGrantingTicket.create!({
26
- ticket: 'TGC-HXdkW233TsRtiqYGq4b8U7',
27
- username: 'test',
28
- extra_attributes: nil,
29
- user_agent: user_agent
30
- })
31
- }
32
- let(:service_ticket) {
33
- ticket_granting_ticket.service_tickets.create! ticket: 'ST-6NBRr5DAg2NW181H5chaHh', service: 'http://www.example.com'
34
- }
35
- let(:consumed_service_ticket) {
36
- st = ticket_granting_ticket.service_tickets.create! ticket: 'ST-6NBRr5DAg2NW181H5chaHh', service: 'http://www.example.com'
37
- st.consumed = true
38
- st.save!
39
- st
40
- }
17
+ let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
18
+ let(:service_ticket) { FactoryGirl.create :service_ticket, ticket_granting_ticket: ticket_granting_ticket }
19
+ let(:consumed_service_ticket) { FactoryGirl.create :service_ticket, :consumed, ticket_granting_ticket: ticket_granting_ticket }
41
20
  let(:params) { { id: ticket_granting_ticket.id } }
42
21
 
43
22
  it 'deletes only one ticket-granting ticket' do
@@ -75,14 +54,7 @@ describe CASinoCore::Processor::SessionDestroyer do
75
54
  end
76
55
 
77
56
  context 'when trying to delete ticket-granting ticket of another user' do
78
- let(:ticket_granting_ticket) {
79
- CASinoCore::Model::TicketGrantingTicket.create!({
80
- ticket: 'TGC-HXdkW233TsRtiqYGq4b8U7',
81
- username: 'this_is_another_user',
82
- extra_attributes: nil,
83
- user_agent: user_agent
84
- })
85
- }
57
+ let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket, username: 'other_user' }
86
58
  let(:params) { { id: ticket_granting_ticket.id } }
87
59
 
88
60
  it 'does not delete a ticket-granting ticket' do
@@ -4,15 +4,8 @@ describe CASinoCore::Processor::SessionOverview do
4
4
  describe '#process' do
5
5
  let(:listener) { Object.new }
6
6
  let(:processor) { described_class.new(listener) }
7
- let(:user_agent) { 'TestBrowser 1.0' }
8
- let(:other_ticket_granting_ticket) {
9
- CASinoCore::Model::TicketGrantingTicket.create!({
10
- ticket: 'TGC-ocCudGzZjJtrvOXJ485mt3',
11
- username: 'test',
12
- extra_attributes: nil,
13
- user_agent: user_agent
14
- })
15
- }
7
+ let(:other_ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
8
+ let(:user_agent) { other_ticket_granting_ticket.user_agent }
16
9
  let(:cookies) { { tgt: tgt } }
17
10
 
18
11
  before(:each) do
@@ -22,14 +15,7 @@ describe CASinoCore::Processor::SessionOverview do
22
15
  end
23
16
 
24
17
  context 'with an existing ticket-granting ticket' do
25
- let(:ticket_granting_ticket) {
26
- CASinoCore::Model::TicketGrantingTicket.create!({
27
- ticket: 'TGC-HXdkW233TsRtiqYGq4b8U7',
28
- username: 'test',
29
- extra_attributes: nil,
30
- user_agent: user_agent
31
- })
32
- }
18
+ let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket }
33
19
  let(:tgt) { ticket_granting_ticket.ticket }
34
20
  it 'calls the #ticket_granting_tickets_found method on the listener' do
35
21
  listener.should_receive(:ticket_granting_tickets_found) do |tickets|
@@ -39,6 +25,18 @@ describe CASinoCore::Processor::SessionOverview do
39
25
  end
40
26
  end
41
27
 
28
+ context 'with a ticket-granting ticket with same username but different authenticator' do
29
+ let(:ticket_granting_ticket) { FactoryGirl.create :ticket_granting_ticket, authenticator: 'other' }
30
+ let(:tgt) { ticket_granting_ticket.ticket }
31
+
32
+ it 'calls the #ticket_granting_tickets_found method on the listener' do
33
+ listener.should_receive(:ticket_granting_tickets_found) do |tickets|
34
+ tickets.length.should == 1
35
+ end
36
+ processor.process(cookies, user_agent)
37
+ end
38
+ end
39
+
42
40
  context 'with an invalid ticket-granting ticket' do
43
41
  let(:tgt) { 'TGT-lalala' }
44
42
  it 'calls the #user_not_logged_in method on the listener' do
@@ -5,19 +5,8 @@ require 'spec_helper'
5
5
  describe '#process' do
6
6
  let(:listener) { Object.new }
7
7
  let(:processor) { described_class.new(listener) }
8
- let(:user_agent) { 'TestBrowser 1.0' }
9
- let(:ticket_granting_ticket) {
10
- CASinoCore::Model::TicketGrantingTicket.create!({
11
- ticket: 'TGC-HXdkW233TsRtiqYGq4b8U7',
12
- username: 'test',
13
- extra_attributes: { name: "Example User", roles: ['User', 'Admin'] },
14
- user_agent: user_agent
15
- })
16
- }
17
- let(:service) { 'https://www.example.com/cas-service' }
18
- let(:service_ticket) { ticket_granting_ticket.service_tickets.create! ticket: 'ST-2nOcXx56dtPTsB069yYf0h', service: service }
19
- let(:parameters) { { service: service, ticket: service_ticket.ticket }}
20
-
8
+ let(:service_ticket) { FactoryGirl.create :service_ticket }
9
+ let(:parameters) { { service: service_ticket.service, ticket: service_ticket.ticket }}
21
10
  let(:regex_failure) { /\A\<cas\:serviceResponse.*\n.*authenticationFailure/ }
22
11
  let(:regex_success) { /\A\<cas\:serviceResponse.*\n.*authenticationSuccess/ }
23
12
 
@@ -26,6 +15,19 @@ require 'spec_helper'
26
15
  listener.stub(:validation_succeeded)
27
16
  end
28
17
 
18
+ context 'without all required parameters' do
19
+ [:ticket, :service].each do |missing_parameter|
20
+ let(:invalid_parameters) { parameters.except(missing_parameter) }
21
+
22
+ context "without '#{missing_parameter}'" do
23
+ it 'calls the #validation_failed method on the listener' do
24
+ listener.should_receive(:validation_failed).with(regex_failure)
25
+ processor.process(invalid_parameters)
26
+ end
27
+ end
28
+ end
29
+ end
30
+
29
31
  context 'with an unconsumed service ticket' do
30
32
  context 'without renew flag' do
31
33
  it 'consumes the service ticket' do
@@ -43,7 +45,7 @@ require 'spec_helper'
43
45
  context 'with empty query values' do
44
46
  it 'calls the #validation_succeeded method on the listener' do
45
47
  listener.should_receive(:validation_succeeded).with(regex_success)
46
- processor.process(parameters.merge(service: "#{service}/?"))
48
+ processor.process(parameters.merge(service: "#{service_ticket.service}/?"))
47
49
  end
48
50
  end
49
51
 
@@ -10,6 +10,11 @@ require 'simplecov'
10
10
  # loaded once.
11
11
  #
12
12
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
13
+
14
+ # Requires supporting ruby files with custom matchers and macros, etc,
15
+ # in spec/support/ and its subdirectories.
16
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
17
+
13
18
  RSpec.configure do |config|
14
19
  config.treat_symbols_as_metadata_keys_with_true_values = true
15
20
 
@@ -21,6 +26,12 @@ RSpec.configure do |config|
21
26
 
22
27
  SimpleCov.start do
23
28
  add_filter '/spec'
29
+ base_path = "#{File.dirname(__FILE__)}/../"
30
+ Dir["#{base_path}lib/casino_core/*.rb"].each do |f|
31
+ f.gsub!(/\A#{base_path}(.+)\.rb\z/, '\1')
32
+ name = File.basename(f).humanize.pluralize
33
+ add_group name, f
34
+ end
24
35
  end
25
36
 
26
37
  CASinoCore.setup 'test'
@@ -0,0 +1,16 @@
1
+ require 'factory_girl'
2
+
3
+ FactoryGirl.define do
4
+ factory :login_ticket, class: CASinoCore::Model::LoginTicket do
5
+ sequence :ticket do |n|
6
+ "LT-ticket#{n}"
7
+ end
8
+
9
+ trait :consumed do
10
+ consumed true
11
+ end
12
+ trait :expired do
13
+ created_at 601.seconds.ago
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require 'factory_girl'
2
+
3
+ FactoryGirl.define do
4
+ factory :proxy_granting_ticket, class: CASinoCore::Model::ProxyGrantingTicket do
5
+ association :granter, factory: :service_ticket
6
+ sequence :ticket do |n|
7
+ "PGT-ticket#{n}"
8
+ end
9
+ sequence :iou do |n|
10
+ "PGTIOU-ticket#{n}"
11
+ end
12
+ sequence :pgt_url do |n|
13
+ "https://www#{n}.example.org/pgtUrl"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ require 'factory_girl'
2
+
3
+ FactoryGirl.define do
4
+ factory :proxy_ticket, class: CASinoCore::Model::ProxyTicket do
5
+ proxy_granting_ticket
6
+ sequence :ticket do |n|
7
+ "PT-ticket#{n}"
8
+ end
9
+ sequence :service do |n|
10
+ "imaps://mail#{n}.example.org/"
11
+ end
12
+
13
+ trait :consumed do
14
+ consumed true
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'factory_girl'
2
+
3
+ FactoryGirl.define do
4
+ factory :service_ticket, class: CASinoCore::Model::ServiceTicket do
5
+ ticket_granting_ticket
6
+ sequence :ticket do |n|
7
+ "ST-ticket#{n}"
8
+ end
9
+ sequence :service do |n|
10
+ "http://www#{n}.example.org/"
11
+ end
12
+
13
+ trait :consumed do
14
+ consumed true
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ require 'factory_girl'
2
+
3
+ FactoryGirl.define do
4
+ factory :ticket_granting_ticket, class: CASinoCore::Model::TicketGrantingTicket do
5
+ sequence :ticket do |n|
6
+ "TGC-ticket#{n}"
7
+ end
8
+ authenticator 'test'
9
+ username 'test'
10
+ extra_attributes({ fullname: "Test User", age: 15, roles: [:user] })
11
+ user_agent 'TestBrowser 1.0'
12
+ end
13
+ end
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.3
5
+ version: 1.0.4
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-29 00:00:00 Z
13
+ date: 2012-12-30 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -155,6 +155,17 @@ dependencies:
155
155
  type: :development
156
156
  prerelease: false
157
157
  version_requirements: *id013
158
+ - !ruby/object:Gem::Dependency
159
+ name: factory_girl
160
+ requirement: &id014 !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ~>
164
+ - !ruby/object:Gem::Version
165
+ version: 4.1.0
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: *id014
158
169
  description: A CAS server core library.
159
170
  email: ncaspar@me.com
160
171
  executables: []
@@ -196,6 +207,7 @@ files:
196
207
  - db/migrate/20121225231713_no_default_granter_type.rb
197
208
  - db/migrate/20121226192211_fix_index_for_granter_on_proxy_granting_ticket.rb
198
209
  - db/migrate/20121226211511_allow_service_tickets_without_ticket_granting_ticket.rb
210
+ - db/migrate/20121231114141_add_authenticator_to_ticket_granting_tickets.rb
199
211
  - db/schema.rb
200
212
  - lib/casino_core.rb
201
213
  - lib/casino_core/authenticator.rb
@@ -250,6 +262,11 @@ files:
250
262
  - spec/processor/session_overview_spec.rb
251
263
  - spec/processor/ticket_validator_spec.rb
252
264
  - spec/spec_helper.rb
265
+ - spec/support/factories/login_ticket_factory.rb
266
+ - spec/support/factories/proxy_granting_ticket_factory.rb
267
+ - spec/support/factories/proxy_ticket_factory.rb
268
+ - spec/support/factories/service_ticket_factory.rb
269
+ - spec/support/factories/ticket_granting_ticket_factory.rb
253
270
  homepage: http://github.com/pencil/CASinoCore
254
271
  licenses:
255
272
  - MIT
@@ -263,7 +280,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
263
280
  requirements:
264
281
  - - ">="
265
282
  - !ruby/object:Gem::Version
266
- hash: 1358580775161495326
283
+ hash: -1912000289096139821
267
284
  segments:
268
285
  - 0
269
286
  version: "0"