aker 3.0.0.pre
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/CHANGELOG.md +210 -0
- data/README.md +282 -0
- data/assets/aker/form/login.css +73 -0
- data/assets/aker/form/login.html.erb +44 -0
- data/lib/aker/authorities/automatic_access.rb +36 -0
- data/lib/aker/authorities/composite.rb +301 -0
- data/lib/aker/authorities/static.rb +283 -0
- data/lib/aker/authorities/support/find_sole_user.rb +24 -0
- data/lib/aker/authorities/support.rb +9 -0
- data/lib/aker/authorities.rb +46 -0
- data/lib/aker/cas/authority.rb +79 -0
- data/lib/aker/cas/configuration_helper.rb +85 -0
- data/lib/aker/cas/middleware/logout_responder.rb +49 -0
- data/lib/aker/cas/middleware/ticket_remover.rb +35 -0
- data/lib/aker/cas/middleware.rb +6 -0
- data/lib/aker/cas/proxy_mode.rb +108 -0
- data/lib/aker/cas/rack_proxy_callback.rb +188 -0
- data/lib/aker/cas/service_mode.rb +88 -0
- data/lib/aker/cas/service_url.rb +62 -0
- data/lib/aker/cas/user_ext.rb +64 -0
- data/lib/aker/cas.rb +31 -0
- data/lib/aker/central_parameters.rb +101 -0
- data/lib/aker/configuration.rb +534 -0
- data/lib/aker/deprecation.rb +105 -0
- data/lib/aker/form/custom_views_mode.rb +80 -0
- data/lib/aker/form/login_form_asset_provider.rb +56 -0
- data/lib/aker/form/middleware/custom_view_login_responder.rb +19 -0
- data/lib/aker/form/middleware/login_renderer.rb +72 -0
- data/lib/aker/form/middleware/login_responder.rb +71 -0
- data/lib/aker/form/middleware/logout_responder.rb +26 -0
- data/lib/aker/form/middleware.rb +10 -0
- data/lib/aker/form/mode.rb +118 -0
- data/lib/aker/form.rb +26 -0
- data/lib/aker/group.rb +67 -0
- data/lib/aker/group_membership.rb +162 -0
- data/lib/aker/ldap/authority.rb +392 -0
- data/lib/aker/ldap/user_ext.rb +19 -0
- data/lib/aker/ldap.rb +22 -0
- data/lib/aker/modes/base.rb +85 -0
- data/lib/aker/modes/http_basic.rb +100 -0
- data/lib/aker/modes/support/attempted_path.rb +22 -0
- data/lib/aker/modes/support/rfc_2617.rb +32 -0
- data/lib/aker/modes/support.rb +12 -0
- data/lib/aker/modes.rb +48 -0
- data/lib/aker/rack/authenticate.rb +37 -0
- data/lib/aker/rack/configuration_helper.rb +18 -0
- data/lib/aker/rack/default_logout_responder.rb +36 -0
- data/lib/aker/rack/environment_helper.rb +34 -0
- data/lib/aker/rack/facade.rb +102 -0
- data/lib/aker/rack/failure.rb +69 -0
- data/lib/aker/rack/logout.rb +63 -0
- data/lib/aker/rack/request_ext.rb +19 -0
- data/lib/aker/rack/session_timer.rb +95 -0
- data/lib/aker/rack/setup.rb +77 -0
- data/lib/aker/rack.rb +107 -0
- data/lib/aker/test/helpers.rb +22 -0
- data/lib/aker/test.rb +8 -0
- data/lib/aker/user.rb +231 -0
- data/lib/aker/version.rb +3 -0
- data/lib/aker.rb +51 -0
- data/spec/aker/aker-sample.yml +11 -0
- data/spec/aker/authorities/automatic_access_spec.rb +52 -0
- data/spec/aker/authorities/composite_spec.rb +488 -0
- data/spec/aker/authorities/nu-schema.jar +0 -0
- data/spec/aker/authorities/static_spec.rb +455 -0
- data/spec/aker/authorities/support/find_sole_user_spec.rb +33 -0
- data/spec/aker/authorities_spec.rb +16 -0
- data/spec/aker/cas/authority_spec.rb +106 -0
- data/spec/aker/cas/configuration_helper_spec.rb +92 -0
- data/spec/aker/cas/middleware/logout_responder_spec.rb +47 -0
- data/spec/aker/cas/middleware/ticket_remover_spec.rb +49 -0
- data/spec/aker/cas/proxy_mode_spec.rb +185 -0
- data/spec/aker/cas/rack_proxy_callback_spec.rb +190 -0
- data/spec/aker/cas/service_mode_spec.rb +122 -0
- data/spec/aker/cas/service_url_spec.rb +114 -0
- data/spec/aker/cas/user_ext_spec.rb +27 -0
- data/spec/aker/cas_spec.rb +19 -0
- data/spec/aker/central_parameters_spec.rb +44 -0
- data/spec/aker/configuration_spec.rb +465 -0
- data/spec/aker/deprecation_spec.rb +115 -0
- data/spec/aker/form/a_form_mode.rb +129 -0
- data/spec/aker/form/custom_views_mode_spec.rb +34 -0
- data/spec/aker/form/login_form_asset_provider_spec.rb +80 -0
- data/spec/aker/form/middleware/a_form_login_responder.rb +89 -0
- data/spec/aker/form/middleware/custom_view_login_responder_spec.rb +47 -0
- data/spec/aker/form/middleware/login_renderer_spec.rb +56 -0
- data/spec/aker/form/middleware/login_responder_spec.rb +34 -0
- data/spec/aker/form/middleware/logout_responder_spec.rb +55 -0
- data/spec/aker/form/mode_spec.rb +15 -0
- data/spec/aker/form_spec.rb +11 -0
- data/spec/aker/group_membership_spec.rb +208 -0
- data/spec/aker/group_spec.rb +66 -0
- data/spec/aker/ldap/authority_spec.rb +414 -0
- data/spec/aker/ldap/ldap-users.ldif +197 -0
- data/spec/aker/ldap_spec.rb +11 -0
- data/spec/aker/modes/a_aker_mode.rb +41 -0
- data/spec/aker/modes/http_basic_spec.rb +127 -0
- data/spec/aker/modes/support/attempted_path_spec.rb +32 -0
- data/spec/aker/modes_spec.rb +11 -0
- data/spec/aker/rack/authenticate_spec.rb +78 -0
- data/spec/aker/rack/default_logout_responder_spec.rb +67 -0
- data/spec/aker/rack/facade_spec.rb +154 -0
- data/spec/aker/rack/failure_spec.rb +151 -0
- data/spec/aker/rack/logout_spec.rb +63 -0
- data/spec/aker/rack/request_ext_spec.rb +29 -0
- data/spec/aker/rack/session_timer_spec.rb +134 -0
- data/spec/aker/rack/setup_spec.rb +87 -0
- data/spec/aker/rack_spec.rb +216 -0
- data/spec/aker/test/helpers_spec.rb +44 -0
- data/spec/aker/user_spec.rb +362 -0
- data/spec/aker_spec.rb +80 -0
- data/spec/deprecation_helper.rb +58 -0
- data/spec/java_helper.rb +5 -0
- data/spec/logger_helper.rb +17 -0
- data/spec/matchers.rb +31 -0
- data/spec/mock_builder.rb +25 -0
- data/spec/spec_helper.rb +52 -0
- metadata +265 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
require File.expand_path("../../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
|
|
5
|
+
module Aker::Authorities
|
|
6
|
+
describe Static do
|
|
7
|
+
before do
|
|
8
|
+
@s = Static.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "initialization" do
|
|
12
|
+
it "will accept an argument" do
|
|
13
|
+
lambda { Static.new('ignored') }.should_not raise_error
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "does not require an argument" do
|
|
17
|
+
lambda { Static.new }.should_not raise_error
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe "setting and checking credentials" do
|
|
22
|
+
describe ":user" do
|
|
23
|
+
before do
|
|
24
|
+
@s.valid_credentials!(:user, "jo", "50-50")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "gives the user for a valid combination" do
|
|
28
|
+
@s.valid_credentials?(:user, "jo", "50-50").username.should == "jo"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "gives nil for the wrong password" do
|
|
32
|
+
@s.valid_credentials?(:user, "jo", "40-60").should be_nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "gives nil for an unknown user" do
|
|
36
|
+
@s.valid_credentials?(:user, "joe", "50-50").should be_nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "with duplicate passwords" do
|
|
40
|
+
before do
|
|
41
|
+
@s.valid_credentials!(:user, "joe", "50-50")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "authenticates the first user" do
|
|
45
|
+
@s.valid_credentials?(:user, "jo", "50-50").username.should == "jo"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "authenticates the second user" do
|
|
49
|
+
@s.valid_credentials?(:user, "joe", "50-50").username.should == "joe"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe "other kinds" do
|
|
55
|
+
before do
|
|
56
|
+
@s.valid_credentials!(:magic, "jo", "abracadabra")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "gives the user for a valid key" do
|
|
60
|
+
@s.valid_credentials?(:magic, "abracadabra").username.should == "jo"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "gives nil for an unknown key" do
|
|
64
|
+
@s.valid_credentials?(:magic, "shazam").should be_nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "gives nil for an unknown kind" do
|
|
68
|
+
@s.valid_credentials?(:radar, "abracadabra").should be_nil
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe "accessing users" do
|
|
74
|
+
it "reuses a user added with valid_credentials!" do
|
|
75
|
+
@s.valid_credentials!(:user, "jo", "123")
|
|
76
|
+
@s.user("jo").object_id.should == @s.valid_credentials?(:user, "jo", "123").object_id
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "creates a user on first reference" do
|
|
80
|
+
@s.user("jo").username.should == "jo"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "reuses user across multiple calls" do
|
|
84
|
+
@s.user("jo").object_id.should == @s.user("jo").object_id
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "yields the user to a block, if given" do
|
|
88
|
+
@s.user("jo") do |u|
|
|
89
|
+
u.first_name = "Josephine"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
@s.user("jo").first_name.should == "Josephine"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
describe "#amplify!" do
|
|
97
|
+
before do
|
|
98
|
+
@s.user("jo") do |u|
|
|
99
|
+
u.first_name = "Josephine"
|
|
100
|
+
u.last_name = "Mueller"
|
|
101
|
+
u.portals += [:ENU, :NOTIS]
|
|
102
|
+
u.group_memberships(:ENU) << Aker::GroupMembership.new(Aker::Group.new("User"))
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
@outside_jo = Aker::User.new("jo")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def actual
|
|
109
|
+
@s.amplify!(@outside_jo)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "does nothing for an unknown user" do
|
|
113
|
+
lambda { @s.amplify!(Aker::User.new("joe")) }.should_not raise_error
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe "on a blank instance" do
|
|
117
|
+
it "copies simple attributes" do
|
|
118
|
+
actual.first_name.should == "Josephine"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "copies portals" do
|
|
122
|
+
actual.portals.should == [:ENU, :NOTIS]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "copies group memberships" do
|
|
126
|
+
actual.group_memberships(:ENU).size.should == 1
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe "for portals" do
|
|
131
|
+
before do
|
|
132
|
+
@outside_jo.portals += [:ENU, :SQLSubmit]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "only includes each portal once" do
|
|
136
|
+
actual.portals.size.should == 3
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "retains portals that are in both lists" do
|
|
140
|
+
actual.may_access?(:ENU).should be_true
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "adds portals from the static authority" do
|
|
144
|
+
actual.may_access?(:NOTIS).should be_true
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it "retains portals that are only in the pre-amplified user" do
|
|
148
|
+
actual.may_access?(:SQLSubmit).should be_true
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
describe "for group memberships" do
|
|
153
|
+
it "copies group memberships for an otherwise unknown portal" do
|
|
154
|
+
@outside_jo.group_memberships(:NOTIS) <<
|
|
155
|
+
Aker::GroupMembership.new(Aker::Group.new("Admin"))
|
|
156
|
+
|
|
157
|
+
actual.group_memberships(:ENU).size.should == 1
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "leaves alone group memberships for a known portal" do
|
|
161
|
+
@outside_jo.group_memberships(:ENU) <<
|
|
162
|
+
Aker::GroupMembership.new(Aker::Group.new("Developer"))
|
|
163
|
+
|
|
164
|
+
actual.group_memberships(:ENU).include?("Developer").should be_true
|
|
165
|
+
actual.group_memberships(:ENU).include?("User").should be_false
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
describe "#find_users" do
|
|
171
|
+
before do
|
|
172
|
+
@s.user('alpha') do |u|
|
|
173
|
+
u.first_name = 'A'
|
|
174
|
+
u.last_name = 'Pha'
|
|
175
|
+
u.middle_name = 'L.'
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
@s.user('epsilon') do |u|
|
|
179
|
+
u.first_name = 'Epsi'
|
|
180
|
+
u.last_name = 'On'
|
|
181
|
+
u.middle_name = 'L.'
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
describe "with a username" do
|
|
186
|
+
it "returns the sole matching user" do
|
|
187
|
+
@s.find_users("alpha").collect(&:first_name).should == %w(A)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "returns an empty list for no users" do
|
|
191
|
+
@s.find_users("gamma").should == []
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
describe "with a hash of criteria" do
|
|
196
|
+
it "matches on user attributes" do
|
|
197
|
+
@s.find_users(:middle_name => 'L.').size.should == 2
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it "ignores unknown attributes" do
|
|
201
|
+
@s.find_users(:username => 'epsilon', :frob => 'yelp').size.should == 1
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "returns nothing if the criteria contains no known attributes" do
|
|
205
|
+
@s.find_users(:frob => 'hork').size.should == 0
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "combines attributes with AND" do
|
|
209
|
+
@s.find_users(:first_name => 'A', :last_name => 'Pha').size.should == 1
|
|
210
|
+
@s.find_users(:first_name => 'A', :last_name => 'On').size.should == 0
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
describe "with a list" do
|
|
215
|
+
describe "of usernames" do
|
|
216
|
+
it "returns the correct users" do
|
|
217
|
+
@s.find_users("epsilon", "gamma", "alpha").
|
|
218
|
+
collect(&:first_name).sort.should == %w(A Epsi)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
describe "of criteria hashes" do
|
|
223
|
+
it "returns all matching users" do
|
|
224
|
+
@s.find_users({ :first_name => 'A' }, { :last_name => 'On' }).should have(2).users
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it "does not include duplicates" do
|
|
228
|
+
@s.find_users({ :first_name => 'A' }, { :last_name => 'Pha' }).should have(1).user
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
describe "of both" do
|
|
233
|
+
it "returns the correct matches" do
|
|
234
|
+
@s.find_users({ :last_name => 'Pha' }, 'epsilon').collect(&:username).sort.
|
|
235
|
+
should == %w(alpha epsilon)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
describe "#load!" do
|
|
242
|
+
it "does not fail with an empty yaml doc" do
|
|
243
|
+
lambda { @s.load!(StringIO.new("")) }.should_not raise_error
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it "does not fail with just users" do
|
|
247
|
+
lambda { @s.load!(StringIO.new("users: {}")) }.should_not raise_error
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
it "does not fail with just groups" do
|
|
251
|
+
lambda { @s.load!(StringIO.new("groups: {}")) }.should_not raise_error
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
it "returns self" do
|
|
255
|
+
@s.load!(StringIO.new).object_id.should == @s.object_id
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
describe "from YAML" do
|
|
259
|
+
before do
|
|
260
|
+
@s.load!(StringIO.new(<<-YAML))
|
|
261
|
+
users:
|
|
262
|
+
jo:
|
|
263
|
+
password: qofhearts
|
|
264
|
+
first_name: "Jo"
|
|
265
|
+
middle_name: "Middle"
|
|
266
|
+
last_name: "Last"
|
|
267
|
+
title: "Queen"
|
|
268
|
+
business_phone: "(706)634-5789"
|
|
269
|
+
fax: "(706) 867-5309"
|
|
270
|
+
email: "jo@test.com"
|
|
271
|
+
address: "123 Fake St"
|
|
272
|
+
city: "Chicago"
|
|
273
|
+
state: "Illinois"
|
|
274
|
+
country: "USA"
|
|
275
|
+
identifiers:
|
|
276
|
+
personnel_id: 1
|
|
277
|
+
nu_employee_id: 2
|
|
278
|
+
portals:
|
|
279
|
+
- SQLSubmit
|
|
280
|
+
- ENU:
|
|
281
|
+
- User
|
|
282
|
+
- Developer
|
|
283
|
+
- NOTIS:
|
|
284
|
+
- Auditor
|
|
285
|
+
- Manager: [20, 30]
|
|
286
|
+
groups:
|
|
287
|
+
NOTIS:
|
|
288
|
+
- Admin:
|
|
289
|
+
- Manager:
|
|
290
|
+
- User:
|
|
291
|
+
- Viewer
|
|
292
|
+
- Auditor
|
|
293
|
+
YAML
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
it "associates the password" do
|
|
297
|
+
@s.valid_credentials?(:user, "jo", "qofhearts").should be_true
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
describe "user attributes" do
|
|
301
|
+
before do
|
|
302
|
+
@jo = @s.user("jo")
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
describe "other user attributes" do
|
|
306
|
+
it "includes personnel_id" do
|
|
307
|
+
@jo.identifiers[:personnel_id].should == 1
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
it "includes first_name" do
|
|
311
|
+
@jo.first_name.should == "Jo"
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it "includes middle_name" do
|
|
315
|
+
@jo.middle_name.should == "Middle"
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
it "includes last_name" do
|
|
319
|
+
@jo.last_name.should == "Last"
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
it "includes title" do
|
|
323
|
+
@jo.title.should == "Queen"
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
it "includes business_phone" do
|
|
327
|
+
@jo.business_phone.should == "(706)634-5789"
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
it "includes fax" do
|
|
331
|
+
@jo.fax.should == "(706) 867-5309"
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
it "includes email" do
|
|
335
|
+
@jo.email.should == "jo@test.com"
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
it "includes address" do
|
|
339
|
+
@jo.address.should == "123 Fake St"
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
it "includes city" do
|
|
343
|
+
@jo.city.should == "Chicago"
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
it "includes state" do
|
|
347
|
+
@jo.state.should == "Illinois"
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
it "includes country" do
|
|
351
|
+
@jo.country.should == "USA"
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
it "includes nu_employee_id" do
|
|
355
|
+
@jo.identifiers[:nu_employee_id].should == 2
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
describe "portals" do
|
|
360
|
+
it "includes groupless portals" do
|
|
361
|
+
@jo.may_access?(:SQLSubmit).should be_true
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
it "includes portals with simple groups" do
|
|
365
|
+
@jo.may_access?(:ENU).should be_true
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
it "includes portals with affiliate-based groups" do
|
|
369
|
+
@jo.may_access?(:NOTIS).should be_true
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it "does not include other portals" do
|
|
373
|
+
@jo.may_access?(:foo).should be_false
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
it "uses the first listed portal as the default" do
|
|
378
|
+
@jo.default_portal.should == :SQLSubmit
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
describe "group memberships" do
|
|
382
|
+
it "is empty for groupless portals" do
|
|
383
|
+
@jo.group_memberships(:SQLSubmit).should == []
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
it "includes direct groups for flat-grouped portals" do
|
|
387
|
+
@jo.group_memberships(:ENU).include?("User").should be_true
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
it "includes direct groups for hierarchically-grouped portals" do
|
|
391
|
+
@jo.group_memberships(:NOTIS).include?("Auditor").should be_true
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
it "includes child groups for hierarchically-grouped portals" do
|
|
395
|
+
@jo.group_memberships(:NOTIS).include?("User").should be_true
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
it "includes affiliate matches for affiliate-restricted groups" do
|
|
399
|
+
@jo.group_memberships(:NOTIS).include?("Manager", 20).should be_true
|
|
400
|
+
@jo.group_memberships(:NOTIS).include?("Manager", 21).should be_false
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
it "can be created from a file" do
|
|
408
|
+
fn = '/tmp/aker.yml'
|
|
409
|
+
File.open(fn, 'w') do |f|
|
|
410
|
+
f.write <<-YAML
|
|
411
|
+
users:
|
|
412
|
+
jo:
|
|
413
|
+
password: q
|
|
414
|
+
YAML
|
|
415
|
+
end
|
|
416
|
+
new_one = Static.from_file(fn)
|
|
417
|
+
FileUtils.rm fn
|
|
418
|
+
|
|
419
|
+
new_one.valid_credentials?(:user, "jo", "q").should be_true
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
describe "#clear" do
|
|
423
|
+
before do
|
|
424
|
+
@s.load!(StringIO.new(<<-YAML))
|
|
425
|
+
users:
|
|
426
|
+
jo:
|
|
427
|
+
password: foo
|
|
428
|
+
portals:
|
|
429
|
+
- SQLSubmit
|
|
430
|
+
groups:
|
|
431
|
+
NOTIS:
|
|
432
|
+
- Admin
|
|
433
|
+
YAML
|
|
434
|
+
@s.clear
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
it "clears the users" do
|
|
438
|
+
@s.user("jo").may_access?(:SQLSubmit).should be_false
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
it "clears the groups" do
|
|
442
|
+
# groups aren't otherwise exposed
|
|
443
|
+
@s.instance_eval { @groups }.size.should == 0
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
it "clears the credentials" do
|
|
447
|
+
@s.valid_credentials?(:user, "jo", "foo").should be_nil
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
it "returns self" do
|
|
451
|
+
@s.clear.object_id.should == @s.object_id
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require File.expand_path('../../../../spec_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
module Aker::Authorities::Support
|
|
4
|
+
describe FindSoleUser do
|
|
5
|
+
class UserFinder
|
|
6
|
+
include Aker::Authorities::Support::FindSoleUser
|
|
7
|
+
|
|
8
|
+
def initialize(expected_users)
|
|
9
|
+
@expected_users = expected_users
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def find_users(criteria)
|
|
13
|
+
@expected_users
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe "#find_user" do
|
|
18
|
+
it "returns a single user if only one matches" do
|
|
19
|
+
UserFinder.new([ Aker::User.new('jo') ]).
|
|
20
|
+
find_user("jo").username.should == 'jo'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "returns nil if more than one user matches" do
|
|
24
|
+
UserFinder.new([ Aker::User.new('a'), Aker::User.new('b') ]).
|
|
25
|
+
find_user(:letter => :single).should be_nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "returns nil if no users match" do
|
|
29
|
+
UserFinder.new([]).find_user("jo").should be_nil
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
module Aker
|
|
4
|
+
describe Authorities::Slice do
|
|
5
|
+
let(:configuration) { Configuration.new(:slices => [Authorities::Slice.new]) }
|
|
6
|
+
|
|
7
|
+
it "registers the static authority" do
|
|
8
|
+
configuration.authority_aliases[:static].should be Aker::Authorities::Static
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "registers the automatic_access authority" do
|
|
12
|
+
configuration.authority_aliases[:automatic_access].
|
|
13
|
+
should be Aker::Authorities::AutomaticAccess
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
module Aker::Cas
|
|
4
|
+
describe Authority do
|
|
5
|
+
let(:config) do
|
|
6
|
+
Aker::Configuration.new do
|
|
7
|
+
cas_parameters :base_url => "https://cas.example.net/cas/"
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
let(:authority) { Authority.new(config) }
|
|
12
|
+
|
|
13
|
+
describe "initialization" do
|
|
14
|
+
it "accepts a configuration" do
|
|
15
|
+
Authority.new(config)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "requires a base URL in the configuration" do
|
|
19
|
+
config.parameters_for(:cas)[:base_url] = nil
|
|
20
|
+
lambda { authority }.should raise_error(":base_url parameter is required for CAS")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe "of the client" do
|
|
24
|
+
it "has the right base URL" do
|
|
25
|
+
authority.cas_url.should == "https://cas.example.net/cas/"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
shared_examples_for "a CAS user modifier" do
|
|
31
|
+
describe "user modification" do
|
|
32
|
+
it "initializes the user with its proxy-granting ticket" do
|
|
33
|
+
ticket.stub!(:pgt_iou => "PGTIOU-1foo", :pgt => "PGT-1foo")
|
|
34
|
+
|
|
35
|
+
user = authority.valid_credentials?(kind, ticket, service)
|
|
36
|
+
|
|
37
|
+
user.pgt.should == "PGT-1foo"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "does not initialize the user with a proxy-granting ticket when a PGT IOU is absent" do
|
|
41
|
+
ticket.stub!(:pgt_iou => nil)
|
|
42
|
+
|
|
43
|
+
user = authority.valid_credentials?(kind, ticket, service)
|
|
44
|
+
|
|
45
|
+
user.pgt.should be_nil
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe "#valid_credentials?" do
|
|
51
|
+
it "doesn't support username-password" do
|
|
52
|
+
authority.valid_credentials?(:user, "a", "b").should == :unsupported
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe ":cas" do
|
|
56
|
+
let(:kind) { :cas }
|
|
57
|
+
let(:service) { "https://example.org/app" }
|
|
58
|
+
let(:st) { "ST-bazola" }
|
|
59
|
+
let(:ticket) { stub.as_null_object }
|
|
60
|
+
|
|
61
|
+
before do
|
|
62
|
+
authority.stub!(:service_ticket => ticket)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "returns a user based on the service ticket response" do
|
|
66
|
+
ticket.stub!(:ok? => true, :username => "jo")
|
|
67
|
+
|
|
68
|
+
authority.valid_credentials?(:cas, st, service).username.should == "jo"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "returns nil if the service ticket is invalid" do
|
|
72
|
+
ticket.stub!(:ok? => false)
|
|
73
|
+
|
|
74
|
+
authority.valid_credentials?(:cas, st, service).should be_nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it_should_behave_like "a CAS user modifier"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe ":cas_proxy" do
|
|
81
|
+
let(:kind) { :cas_proxy }
|
|
82
|
+
let(:pt) { "PT-12thththhtthhhthhttp" }
|
|
83
|
+
let(:service) { "https://example.org/app" }
|
|
84
|
+
let(:ticket) { stub.as_null_object }
|
|
85
|
+
|
|
86
|
+
before do
|
|
87
|
+
authority.stub!(:proxy_ticket => ticket)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "returns a user based on the proxy ticket response" do
|
|
91
|
+
ticket.stub!(:ok? => true, :username => "jo")
|
|
92
|
+
|
|
93
|
+
authority.valid_credentials?(:cas_proxy, pt, service).username.should == "jo"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "returns nil if the proxy ticket is invalid" do
|
|
97
|
+
ticket.stub!(:ok? => false)
|
|
98
|
+
|
|
99
|
+
authority.valid_credentials?(:cas_proxy, pt, service).should be_nil
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it_should_behave_like "a CAS user modifier"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
|
2
|
+
|
|
3
|
+
module Aker::Cas
|
|
4
|
+
describe ConfigurationHelper do
|
|
5
|
+
before do
|
|
6
|
+
@config = Aker::Configuration.new
|
|
7
|
+
@config.parameters_for(:cas)[:base_url] = "https://cas.example.org/"
|
|
8
|
+
@actual = Class.new do
|
|
9
|
+
include Aker::Cas::ConfigurationHelper
|
|
10
|
+
|
|
11
|
+
attr_reader :configuration
|
|
12
|
+
|
|
13
|
+
def initialize(config)
|
|
14
|
+
@configuration = config
|
|
15
|
+
end
|
|
16
|
+
end.new(@config)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "#cas_login_url" do
|
|
20
|
+
it "is built from the base URL" do
|
|
21
|
+
@actual.cas_login_url.should == "https://cas.example.org/login"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "preserves application mount points" do
|
|
25
|
+
@config.parameters_for(:cas)[:base_url] = "https://cas.example.org/cas/"
|
|
26
|
+
@actual.cas_login_url.should == "https://cas.example.org/cas/login"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "uses an explicit one if provided" do
|
|
30
|
+
@config.parameters_for(:cas)[:login_url] = "https://cas.example.org/entry-point"
|
|
31
|
+
@actual.cas_login_url.should == "https://cas.example.org/entry-point"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "#cas_logout_url" do
|
|
36
|
+
it "is built from the base URL" do
|
|
37
|
+
@actual.cas_logout_url.should == "https://cas.example.org/logout"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "preserves application mount points" do
|
|
41
|
+
@config.parameters_for(:cas)[:base_url] = "https://cas.example.org/cas/"
|
|
42
|
+
@actual.cas_logout_url.should == "https://cas.example.org/cas/logout"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "uses an explicit one if provided" do
|
|
46
|
+
@config.parameters_for(:cas)[:logout_url] = "https://cas.example.org/exit-point"
|
|
47
|
+
@actual.cas_logout_url.should == "https://cas.example.org/exit-point"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe "#cas_url" do
|
|
52
|
+
before do
|
|
53
|
+
@config.parameters_for(:cas)[:cas_base_url] = "https://cas2.example.org/"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "is preferentially loaded from the :base_url property" do
|
|
57
|
+
@actual.cas_url.should == "https://cas.example.org/"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "is loaded from the :cas_base_url property if that's all that's provided" do
|
|
61
|
+
@config.parameters_for(:cas)[:base_url] = nil
|
|
62
|
+
@actual.cas_url.should == "https://cas2.example.org/"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "adds a terminating / to the base URL if one isn't given" do
|
|
66
|
+
@config.parameters_for(:cas)[:base_url] = "https://cas2.example.org"
|
|
67
|
+
|
|
68
|
+
@actual.cas_url.should == "https://cas2.example.org/"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "does not add a terminating / to the base URL if one is given" do
|
|
72
|
+
@config.parameters_for(:cas)[:base_url] = "https://cas2.example.org/"
|
|
73
|
+
|
|
74
|
+
@actual.cas_url.should == "https://cas2.example.org/"
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe "#proxy_callback_url" do
|
|
79
|
+
it "is loaded from the :proxy_callback_url property" do
|
|
80
|
+
@config.parameters_for(:cas)[:proxy_callback_url] = "https://cas.example.net/callback/gpgt"
|
|
81
|
+
@actual.proxy_callback_url.should == "https://cas.example.net/callback/gpgt"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe "#proxy_retrieval_url" do
|
|
86
|
+
it "is loaded from the :proxy_retrieval_url property" do
|
|
87
|
+
@config.parameters_for(:cas)[:proxy_retrieval_url] = "https://cas.example.net/callback/rpgt"
|
|
88
|
+
@actual.proxy_retrieval_url.should == "https://cas.example.net/callback/rpgt"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|