cassette 1.0.18 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +89 -12
- data/lib/cassette/authentication/authorities.rb +34 -30
- data/lib/cassette/authentication/cache.rb +22 -18
- data/lib/cassette/authentication/filter.rb +52 -33
- data/lib/cassette/authentication/user.rb +20 -16
- data/lib/cassette/authentication.rb +39 -27
- data/lib/cassette/cache.rb +2 -2
- data/lib/cassette/client/cache.rb +39 -35
- data/lib/cassette/client.rb +5 -4
- data/lib/cassette/http/parsed_response.rb +20 -0
- data/lib/cassette/http/request.rb +44 -0
- data/lib/cassette/http/ticket_response.rb +48 -0
- data/lib/cassette/http.rb +8 -0
- data/lib/cassette/rubycas/helper.rb +2 -8
- data/lib/cassette/rubycas/routing_constraint.rb +23 -0
- data/lib/cassette/rubycas/single_sign_out_constraint.rb +8 -8
- data/lib/cassette/rubycas/user_factory.rb +14 -0
- data/lib/cassette/rubycas.rb +2 -0
- data/lib/cassette/version.rb +2 -2
- data/lib/cassette.rb +12 -50
- data/spec/cassette/authentication/authorities_spec.rb +1 -1
- data/spec/cassette/authentication/cache_spec.rb +40 -4
- data/spec/cassette/authentication/filter_spec.rb +106 -36
- data/spec/cassette/authentication/user_factory_spec.rb +42 -0
- data/spec/cassette/authentication/user_spec.rb +4 -3
- data/spec/cassette/authentication_spec.rb +24 -12
- data/spec/cassette/cache_spec.rb +0 -2
- data/spec/cassette/client/cache_spec.rb +1 -1
- data/spec/cassette/client_spec.rb +319 -0
- data/spec/cassette/errors_spec.rb +1 -1
- data/spec/cassette/http/parsed_response_spec.rb +27 -0
- data/spec/cassette/http/request_spec.rb +41 -0
- data/spec/cassette/http/ticket_response_spec.rb +41 -0
- data/spec/cassette/rubycas/routing_constraint_spec.rb +84 -0
- data/spec/cassette_spec.rb +36 -0
- data/spec/integration/cas/client_spec.rb +0 -3
- data/spec/spec_helper.rb +5 -0
- data/spec/support/controllers/controller_mock.rb +19 -0
- metadata +98 -36
- data/spec/cas_spec.rb +0 -78
@@ -0,0 +1,44 @@
|
|
1
|
+
module Cassette
|
2
|
+
module Http
|
3
|
+
module Request
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def post(uri, payload, timeout = DEFAULT_TIMEOUT)
|
7
|
+
perform(:post, uri, timeout) do |request|
|
8
|
+
request.body = URI.encode_www_form(payload)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def perform(http_verb, uri, timeout, &block)
|
15
|
+
request(uri, timeout)
|
16
|
+
.tap(&log_request)
|
17
|
+
.public_send(http_verb, &block)
|
18
|
+
.tap(&check_response)
|
19
|
+
end
|
20
|
+
|
21
|
+
def request(uri, timeout)
|
22
|
+
Faraday.new(url: uri, ssl: { verify: false, version: 'TLSv1' }) do |con|
|
23
|
+
con.adapter Faraday.default_adapter
|
24
|
+
con.options.timeout = timeout
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def log_request
|
29
|
+
lambda { |request| Cassette.logger.debug "Request: #{request.inspect}" }
|
30
|
+
end
|
31
|
+
|
32
|
+
def check_response
|
33
|
+
lambda do |resp|
|
34
|
+
Cassette.logger.debug(
|
35
|
+
"Got response: #{resp.body.inspect} (#{resp.status}), " \
|
36
|
+
"#{resp.headers.inspect}"
|
37
|
+
)
|
38
|
+
|
39
|
+
Cassette::Errors.raise_by_code(resp.status) unless resp.success?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Cassette
|
2
|
+
module Http
|
3
|
+
class TicketResponse
|
4
|
+
def initialize(response)
|
5
|
+
@content = ParsedResponse.new(response)
|
6
|
+
end
|
7
|
+
|
8
|
+
def login
|
9
|
+
fetch_val(
|
10
|
+
content,
|
11
|
+
'serviceResponse',
|
12
|
+
'authenticationSuccess',
|
13
|
+
'user',
|
14
|
+
'__content__'
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def name
|
19
|
+
fetch_val(attributes, 'cn', '__content__')
|
20
|
+
end
|
21
|
+
|
22
|
+
def authorities
|
23
|
+
fetch_val(attributes, 'authorities', '__content__')
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :content
|
29
|
+
|
30
|
+
def fetch_val(hash, *keys)
|
31
|
+
keys.reduce(hash, &access_key)
|
32
|
+
end
|
33
|
+
|
34
|
+
def access_key
|
35
|
+
lambda { |hash, key| hash.try(:[], key) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def attributes
|
39
|
+
fetch_val(
|
40
|
+
content,
|
41
|
+
'serviceResponse',
|
42
|
+
'authenticationSuccess',
|
43
|
+
'attributes'
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -6,6 +6,7 @@ module Cassette
|
|
6
6
|
module Rubycas
|
7
7
|
module Helper
|
8
8
|
extend ActiveSupport::Concern
|
9
|
+
extend UserFactory
|
9
10
|
|
10
11
|
included do
|
11
12
|
before_filter :validate_authentication_ticket
|
@@ -60,14 +61,7 @@ module Cassette
|
|
60
61
|
return fake_user if ENV['NOAUTH']
|
61
62
|
return nil unless session[:cas_user]
|
62
63
|
|
63
|
-
@current_user ||=
|
64
|
-
attributes = session[:cas_extra_attributes]
|
65
|
-
Cassette::Authentication::User.new(login: session[:cas_user],
|
66
|
-
name: attributes.try(:[], :cn),
|
67
|
-
email: attributes.try(:[], :email),
|
68
|
-
authorities: attributes.try(:[], :authorities),
|
69
|
-
type: attributes.try(:[], :type).try(:downcase))
|
70
|
-
end
|
64
|
+
@current_user ||= from_session(session)
|
71
65
|
end
|
72
66
|
end
|
73
67
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Cassette
|
2
|
+
module Rubycas
|
3
|
+
class RoutingConstraint
|
4
|
+
include UserFactory
|
5
|
+
|
6
|
+
attr_reader :role, :options
|
7
|
+
|
8
|
+
def initialize(role, opts = {})
|
9
|
+
defaults = { raw: false }
|
10
|
+
@role = role
|
11
|
+
@options = defaults.merge(opts)
|
12
|
+
end
|
13
|
+
|
14
|
+
def matches?(request)
|
15
|
+
user = from_session(request.session)
|
16
|
+
|
17
|
+
meth = options[:raw] ? :has_raw_role? : :has_role?
|
18
|
+
|
19
|
+
user.send(meth, role)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -3,18 +3,18 @@
|
|
3
3
|
module Cassette
|
4
4
|
module Rubycas
|
5
5
|
class SingleSignOutConstraint
|
6
|
+
LOGOUT_PAYLOAD_EXPR = %r{<samlp:LogoutRequest.*?<samlp:SessionIndex>(.*)<\/samlp:SessionIndex}m
|
7
|
+
|
8
|
+
def logout_request?(params)
|
9
|
+
[params['logoutRequest'], URI.unescape(params['logoutRequest'])].find { |xml| xml =~ LOGOUT_PAYLOAD_EXPR }
|
10
|
+
end
|
11
|
+
|
6
12
|
def matches?(request)
|
7
|
-
if (content_type = request.headers['CONTENT_TYPE']) &&
|
8
|
-
content_type =~ /^multipart\//
|
13
|
+
if (content_type = request.headers['CONTENT_TYPE']) && content_type =~ %r{^multipart/}
|
9
14
|
return false
|
10
15
|
end
|
11
16
|
|
12
|
-
if request.post? &&
|
13
|
-
request.request_parameters['logoutRequest'] &&
|
14
|
-
[request.request_parameters['logoutRequest'],
|
15
|
-
URI.unescape(request.request_parameters['logoutRequest'])]
|
16
|
-
.find { |xml| xml =~ /^<samlp:LogoutRequest.*?<samlp:SessionIndex>(.*)<\/samlp:SessionIndex>/m }
|
17
|
-
|
17
|
+
if request.post? && request.request_parameters['logoutRequest'] && logout_request?(request.request_parameters)
|
18
18
|
Cassette.logger.debug "Intercepted a single sign out request on #{request}"
|
19
19
|
return true
|
20
20
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Cassette
|
2
|
+
module Rubycas
|
3
|
+
module UserFactory
|
4
|
+
def from_session(session)
|
5
|
+
attributes = session[:cas_extra_attributes]
|
6
|
+
Cassette::Authentication::User.new(login: session[:cas_user],
|
7
|
+
name: attributes.try(:[], :cn),
|
8
|
+
email: attributes.try(:[], :email),
|
9
|
+
authorities: attributes.try(:[], :authorities),
|
10
|
+
type: attributes.try(:[], :type).try(:downcase))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/cassette/rubycas.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
+
require 'cassette/rubycas/user_factory'
|
3
4
|
require 'cassette/rubycas/helper'
|
4
5
|
require 'cassette/rubycas/single_sign_out_constraint'
|
5
6
|
require 'cassette/rubycas/not_single_sign_out_constraint'
|
7
|
+
require 'cassette/rubycas/routing_constraint'
|
6
8
|
|
7
9
|
module Cassette
|
8
10
|
module Rubycas
|
data/lib/cassette/version.rb
CHANGED
data/lib/cassette.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'cassette/errors'
|
4
4
|
require 'cassette/cache'
|
5
|
+
require 'cassette/http'
|
5
6
|
require 'cassette/client/cache'
|
6
7
|
require 'cassette/client'
|
7
8
|
require 'cassette/authentication'
|
@@ -16,62 +17,23 @@ require 'logger'
|
|
16
17
|
module Cassette
|
17
18
|
extend self
|
18
19
|
|
20
|
+
attr_writer :config, :logger
|
21
|
+
|
19
22
|
DEFAULT_TIMEOUT = 10
|
20
23
|
|
21
24
|
def logger
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
def logger=(logger)
|
32
|
-
@@logger = logger
|
25
|
+
@logger ||= begin
|
26
|
+
if defined?(::Rails) && ::Rails.logger
|
27
|
+
::Rails.logger
|
28
|
+
else
|
29
|
+
Logger.new('/dev/null')
|
30
|
+
end
|
31
|
+
end
|
33
32
|
end
|
34
33
|
|
35
34
|
def config
|
36
|
-
if defined?(
|
37
|
-
@@config
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def config=(config)
|
42
|
-
@@config = config
|
43
|
-
end
|
44
|
-
|
45
|
-
def new_request(uri, timeout)
|
46
|
-
Faraday.new(url: uri, ssl: { verify: false, version: 'TLSv1' }) do |builder|
|
47
|
-
builder.adapter Faraday.default_adapter
|
48
|
-
builder.options.timeout = timeout
|
49
|
-
end
|
35
|
+
@config if defined?(@config)
|
50
36
|
end
|
51
37
|
|
52
|
-
|
53
|
-
perform(:get, uri, payload, timeout) do |req|
|
54
|
-
req.params = payload
|
55
|
-
logger.debug "Request: #{req.inspect}"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def post(uri, payload, timeout = DEFAULT_TIMEOUT)
|
60
|
-
perform(:post, uri, payload, timeout) do |req|
|
61
|
-
req.body = URI.encode_www_form(payload)
|
62
|
-
logger.debug "Request: #{req.inspect}"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
protected
|
67
|
-
|
68
|
-
def perform(op, uri, _payload, timeout = DEFAULT_TIMEOUT, &block)
|
69
|
-
request = new_request(uri, timeout)
|
70
|
-
res = request.send(op, &block)
|
71
|
-
|
72
|
-
res.tap do |response|
|
73
|
-
logger.debug "Got response: #{response.body.inspect} (#{response.status}), #{response.headers.inspect}"
|
74
|
-
Cassette::Errors.raise_by_code(response.status) unless response.success?
|
75
|
-
end
|
76
|
-
end
|
38
|
+
delegate :post, to: :'Http::Request'
|
77
39
|
end
|
@@ -1,8 +1,44 @@
|
|
1
|
-
|
2
1
|
# encoding: utf-8
|
3
2
|
|
4
|
-
require 'spec_helper'
|
5
|
-
|
6
3
|
describe Cassette::Authentication::Cache do
|
7
|
-
|
4
|
+
subject(:cache) { described_class.new(Logger.new('/dev/null')) }
|
5
|
+
|
6
|
+
describe '#fetch_authentication' do
|
7
|
+
subject(:fetch_authentication) do
|
8
|
+
cache.fetch_authentication(ticket, service, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:second_call) do
|
12
|
+
cache.fetch_authentication(ticket, service, &other_block)
|
13
|
+
end
|
14
|
+
let(:call_with_other_service) do
|
15
|
+
cache.fetch_authentication(ticket, other_service, &other_block)
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:ticket) { 'ticket' }
|
19
|
+
|
20
|
+
let(:service) { 'lala' }
|
21
|
+
let(:other_service) { 'popo' }
|
22
|
+
|
23
|
+
let(:block) { -> { 1 } }
|
24
|
+
let(:other_block) { -> { 2 } }
|
25
|
+
|
26
|
+
|
27
|
+
before { cache.fetch_authentication(ticket, service, &block) }
|
28
|
+
|
29
|
+
it { is_expected.to eq(1) }
|
30
|
+
|
31
|
+
context 'when for a second time' do
|
32
|
+
it { expect(second_call).to eq(1) }
|
33
|
+
|
34
|
+
it do
|
35
|
+
expect(other_block).not_to receive(:call)
|
36
|
+
second_call
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when calling with a different service' do
|
40
|
+
it { expect(call_with_other_service).to eq(2) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
8
44
|
end
|
@@ -1,24 +1,12 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
3
|
+
|
5
4
|
|
6
5
|
describe Cassette::Authentication::Filter do
|
7
6
|
before do
|
8
7
|
allow(Cassette::Authentication).to receive(:validate_ticket)
|
9
8
|
end
|
10
9
|
|
11
|
-
class ControllerMock
|
12
|
-
attr_accessor :params, :request, :current_user
|
13
|
-
def self.before_filter(*); end
|
14
|
-
include Cassette::Authentication::Filter
|
15
|
-
|
16
|
-
def initialize(params = {}, headers = {})
|
17
|
-
self.params = params.with_indifferent_access
|
18
|
-
self.request = OpenStruct.new(headers: headers.with_indifferent_access)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
10
|
shared_context 'with NOAUTH' do
|
23
11
|
before do
|
24
12
|
ENV['NOAUTH'] = 'yes'
|
@@ -30,7 +18,7 @@ describe Cassette::Authentication::Filter do
|
|
30
18
|
end
|
31
19
|
|
32
20
|
describe '#validate_raw_role!' do
|
33
|
-
let(:controller) { ControllerMock.new }
|
21
|
+
let(:controller) { ControllerMock(described_class).new }
|
34
22
|
let(:current_user) { instance_double(Cassette::Authentication::User) }
|
35
23
|
|
36
24
|
before do
|
@@ -64,7 +52,7 @@ describe Cassette::Authentication::Filter do
|
|
64
52
|
end
|
65
53
|
|
66
54
|
describe '#validate_role!' do
|
67
|
-
let(:controller) { ControllerMock.new }
|
55
|
+
let(:controller) { ControllerMock(described_class).new }
|
68
56
|
let(:current_user) { instance_double(Cassette::Authentication::User) }
|
69
57
|
|
70
58
|
before do
|
@@ -97,7 +85,6 @@ describe Cassette::Authentication::Filter do
|
|
97
85
|
end
|
98
86
|
end
|
99
87
|
|
100
|
-
|
101
88
|
describe '#validate_authentication_ticket' do
|
102
89
|
shared_examples_for 'controller without authentication' do
|
103
90
|
it 'does not validate tickets' do
|
@@ -113,14 +100,14 @@ describe Cassette::Authentication::Filter do
|
|
113
100
|
|
114
101
|
it_behaves_like 'with NOAUTH' do
|
115
102
|
context 'and no ticket' do
|
116
|
-
let(:controller) { ControllerMock.new }
|
103
|
+
let(:controller) { ControllerMock(described_class).new }
|
117
104
|
|
118
105
|
it_behaves_like 'controller without authentication'
|
119
106
|
end
|
120
107
|
|
121
108
|
context 'and a ticket header' do
|
122
109
|
let(:controller) do
|
123
|
-
ControllerMock.new({}, 'Service-Ticket' => 'le ticket')
|
110
|
+
ControllerMock(described_class).new({}, 'Service-Ticket' => 'le ticket')
|
124
111
|
end
|
125
112
|
|
126
113
|
it_behaves_like 'controller without authentication'
|
@@ -128,43 +115,126 @@ describe Cassette::Authentication::Filter do
|
|
128
115
|
|
129
116
|
context 'and a ticket param' do
|
130
117
|
let(:controller) do
|
131
|
-
ControllerMock.new(ticket: 'le ticket')
|
118
|
+
ControllerMock(described_class).new(ticket: 'le ticket')
|
132
119
|
end
|
133
120
|
|
134
121
|
it_behaves_like 'controller without authentication'
|
135
122
|
end
|
136
123
|
end
|
137
124
|
|
138
|
-
context '
|
125
|
+
context 'when accepts_authentication_service? returns false' do
|
139
126
|
let(:controller) do
|
140
|
-
ControllerMock.new(
|
127
|
+
ControllerMock(described_class).new(ticket: 'le ticket')
|
141
128
|
end
|
142
129
|
|
143
|
-
|
144
|
-
controller.
|
145
|
-
|
130
|
+
before do
|
131
|
+
expect(controller).to receive(:accepts_authentication_service?)
|
132
|
+
.with(Cassette.config.service) { false }
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'raises a Cassette::Errors::Forbidden' do
|
136
|
+
expect { controller.validate_authentication_ticket }
|
137
|
+
.to raise_error(Cassette::Errors::Forbidden)
|
146
138
|
end
|
147
139
|
end
|
148
140
|
|
149
|
-
context '
|
150
|
-
|
151
|
-
|
141
|
+
context 'when accepts_authentication_service? returns true' do
|
142
|
+
before do
|
143
|
+
expect(controller).to receive(:accepts_authentication_service?).with(anything) { true }
|
152
144
|
end
|
153
145
|
|
154
|
-
|
155
|
-
controller
|
156
|
-
|
146
|
+
context 'with a ticket in the query string *AND* headers' do
|
147
|
+
let(:controller) do
|
148
|
+
ControllerMock(described_class).new({ 'ticket' => 'le other ticket' },
|
149
|
+
'Service-Ticket' => 'le ticket')
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should send only the header ticket to validation' do
|
153
|
+
controller.validate_authentication_ticket
|
154
|
+
expect(Cassette::Authentication).to have_received(:validate_ticket).with('le ticket', Cassette.config.service)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'with a ticket in the query string' do
|
159
|
+
let(:controller) do
|
160
|
+
ControllerMock(described_class).new('ticket' => 'le ticket')
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should send the ticket to validation' do
|
164
|
+
controller.validate_authentication_ticket
|
165
|
+
expect(Cassette::Authentication).to have_received(:validate_ticket).with('le ticket', Cassette.config.service)
|
166
|
+
end
|
157
167
|
end
|
168
|
+
|
169
|
+
context 'when #authentication_service is overriden' do
|
170
|
+
let(:controller) do
|
171
|
+
mod = Module.new do
|
172
|
+
def authentication_service
|
173
|
+
"subdomain.#{Cassette.config.service}"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
ControllerMock(described_class, mod).new({}, 'Service-Ticket' => 'le ticket')
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'validates with the overriden value and not the config' do
|
181
|
+
controller.validate_authentication_ticket
|
182
|
+
|
183
|
+
expect(Cassette::Authentication).to have_received(:validate_ticket)
|
184
|
+
.with('le ticket', "subdomain.#{Cassette.config.service}")
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'with a ticket in the Service-Ticket header' do
|
189
|
+
let(:controller) do
|
190
|
+
ControllerMock(described_class).new({}, 'Service-Ticket' => 'le ticket')
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'sends the ticket to validation' do
|
194
|
+
controller.validate_authentication_ticket
|
195
|
+
|
196
|
+
expect(Cassette::Authentication).to have_received(:validate_ticket)
|
197
|
+
.with('le ticket', Cassette.config.service)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe '#accepts_authentication_service?' do
|
204
|
+
let(:controller) do
|
205
|
+
ControllerMock(described_class).new(ticket: 'le ticket')
|
158
206
|
end
|
159
207
|
|
160
|
-
|
161
|
-
|
162
|
-
|
208
|
+
before do
|
209
|
+
allow(Cassette).to receive(:config) { config }
|
210
|
+
end
|
211
|
+
|
212
|
+
subject { controller.accepts_authentication_service?(service) }
|
213
|
+
|
214
|
+
context 'when config responds to #services' do
|
215
|
+
let(:subdomain) { "subdomain.acme.org" }
|
216
|
+
let(:not_related) { "acme.org" }
|
217
|
+
|
218
|
+
let(:config) do
|
219
|
+
OpenStruct.new(YAML.load_file('spec/config.yml').merge(services: [subdomain]))
|
163
220
|
end
|
164
221
|
|
165
|
-
|
166
|
-
|
167
|
-
|
222
|
+
context 'and the authentication service is included in the configuration' do
|
223
|
+
let(:service) { subdomain }
|
224
|
+
|
225
|
+
it { is_expected.to eq true }
|
226
|
+
end
|
227
|
+
|
228
|
+
context 'and the authentication service is Cassette.config.service' do
|
229
|
+
let(:service) { Cassette.config.service }
|
230
|
+
|
231
|
+
it { is_expected.to eq true }
|
232
|
+
end
|
233
|
+
|
234
|
+
context 'and the authentication service is not included in the configuration' do
|
235
|
+
let(:service) { not_related }
|
236
|
+
|
237
|
+
it { is_expected.to eq false }
|
168
238
|
end
|
169
239
|
end
|
170
240
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Cassette::Rubycas::UserFactory do
|
4
|
+
let(:mod) do
|
5
|
+
Module.new do
|
6
|
+
extend Cassette::Rubycas::UserFactory
|
7
|
+
extend self
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#from_session' do
|
12
|
+
let(:session) do
|
13
|
+
name = Faker.name
|
14
|
+
|
15
|
+
{
|
16
|
+
cas_user: Faker::Internet.user_name(name),
|
17
|
+
cas_extra_attributes: {
|
18
|
+
email: Faker::Internet.email(name),
|
19
|
+
type: 'Customer',
|
20
|
+
authorities: '[CASTEST_ADMIN]'
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:attributes) do
|
26
|
+
session[:cas_extra_attributes]
|
27
|
+
end
|
28
|
+
|
29
|
+
subject do
|
30
|
+
mod.from_session(session)
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'with default attributes' do
|
34
|
+
its(:login) { is_expected.to eq(session[:cas_user]) }
|
35
|
+
its(:name) { is_expected.to eq(attributes[:name]) }
|
36
|
+
its(:email) { is_expected.to eq(attributes[:email]) }
|
37
|
+
its(:type) { is_expected.to eq(attributes[:type].downcase) }
|
38
|
+
it { is_expected.to be_customer }
|
39
|
+
it { is_expected.not_to be_employee }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
|
3
3
|
describe Cassette::Authentication::User do
|
4
4
|
let(:base_authority) do
|
@@ -20,13 +20,14 @@ describe Cassette::Authentication::User do
|
|
20
20
|
expect(config).to receive(:base_authority).and_return('TESTAPI')
|
21
21
|
expect(Cassette::Authentication::Authorities).to receive(:new).with('[CUSTOMERAPI, SAPI]', 'TESTAPI')
|
22
22
|
|
23
|
-
Cassette::Authentication::User.new(login: 'john.doe', name: 'John Doe',
|
23
|
+
Cassette::Authentication::User.new(login: 'john.doe', name: 'John Doe',
|
24
|
+
authorities: '[CUSTOMERAPI, SAPI]', config: config)
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
28
29
|
describe '#has_role?' do
|
29
|
-
let
|
30
|
+
let(:user) do
|
30
31
|
Cassette::Authentication::User.new(login: 'john.doe', name: 'John Doe',
|
31
32
|
authorities: "[#{base_authority}, SAPI, #{base_authority}_CREATE-USER]")
|
32
33
|
end
|