aker 3.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/CHANGELOG.md +210 -0
  2. data/README.md +282 -0
  3. data/assets/aker/form/login.css +73 -0
  4. data/assets/aker/form/login.html.erb +44 -0
  5. data/lib/aker/authorities/automatic_access.rb +36 -0
  6. data/lib/aker/authorities/composite.rb +301 -0
  7. data/lib/aker/authorities/static.rb +283 -0
  8. data/lib/aker/authorities/support/find_sole_user.rb +24 -0
  9. data/lib/aker/authorities/support.rb +9 -0
  10. data/lib/aker/authorities.rb +46 -0
  11. data/lib/aker/cas/authority.rb +79 -0
  12. data/lib/aker/cas/configuration_helper.rb +85 -0
  13. data/lib/aker/cas/middleware/logout_responder.rb +49 -0
  14. data/lib/aker/cas/middleware/ticket_remover.rb +35 -0
  15. data/lib/aker/cas/middleware.rb +6 -0
  16. data/lib/aker/cas/proxy_mode.rb +108 -0
  17. data/lib/aker/cas/rack_proxy_callback.rb +188 -0
  18. data/lib/aker/cas/service_mode.rb +88 -0
  19. data/lib/aker/cas/service_url.rb +62 -0
  20. data/lib/aker/cas/user_ext.rb +64 -0
  21. data/lib/aker/cas.rb +31 -0
  22. data/lib/aker/central_parameters.rb +101 -0
  23. data/lib/aker/configuration.rb +534 -0
  24. data/lib/aker/deprecation.rb +105 -0
  25. data/lib/aker/form/custom_views_mode.rb +80 -0
  26. data/lib/aker/form/login_form_asset_provider.rb +56 -0
  27. data/lib/aker/form/middleware/custom_view_login_responder.rb +19 -0
  28. data/lib/aker/form/middleware/login_renderer.rb +72 -0
  29. data/lib/aker/form/middleware/login_responder.rb +71 -0
  30. data/lib/aker/form/middleware/logout_responder.rb +26 -0
  31. data/lib/aker/form/middleware.rb +10 -0
  32. data/lib/aker/form/mode.rb +118 -0
  33. data/lib/aker/form.rb +26 -0
  34. data/lib/aker/group.rb +67 -0
  35. data/lib/aker/group_membership.rb +162 -0
  36. data/lib/aker/ldap/authority.rb +392 -0
  37. data/lib/aker/ldap/user_ext.rb +19 -0
  38. data/lib/aker/ldap.rb +22 -0
  39. data/lib/aker/modes/base.rb +85 -0
  40. data/lib/aker/modes/http_basic.rb +100 -0
  41. data/lib/aker/modes/support/attempted_path.rb +22 -0
  42. data/lib/aker/modes/support/rfc_2617.rb +32 -0
  43. data/lib/aker/modes/support.rb +12 -0
  44. data/lib/aker/modes.rb +48 -0
  45. data/lib/aker/rack/authenticate.rb +37 -0
  46. data/lib/aker/rack/configuration_helper.rb +18 -0
  47. data/lib/aker/rack/default_logout_responder.rb +36 -0
  48. data/lib/aker/rack/environment_helper.rb +34 -0
  49. data/lib/aker/rack/facade.rb +102 -0
  50. data/lib/aker/rack/failure.rb +69 -0
  51. data/lib/aker/rack/logout.rb +63 -0
  52. data/lib/aker/rack/request_ext.rb +19 -0
  53. data/lib/aker/rack/session_timer.rb +95 -0
  54. data/lib/aker/rack/setup.rb +77 -0
  55. data/lib/aker/rack.rb +107 -0
  56. data/lib/aker/test/helpers.rb +22 -0
  57. data/lib/aker/test.rb +8 -0
  58. data/lib/aker/user.rb +231 -0
  59. data/lib/aker/version.rb +3 -0
  60. data/lib/aker.rb +51 -0
  61. data/spec/aker/aker-sample.yml +11 -0
  62. data/spec/aker/authorities/automatic_access_spec.rb +52 -0
  63. data/spec/aker/authorities/composite_spec.rb +488 -0
  64. data/spec/aker/authorities/nu-schema.jar +0 -0
  65. data/spec/aker/authorities/static_spec.rb +455 -0
  66. data/spec/aker/authorities/support/find_sole_user_spec.rb +33 -0
  67. data/spec/aker/authorities_spec.rb +16 -0
  68. data/spec/aker/cas/authority_spec.rb +106 -0
  69. data/spec/aker/cas/configuration_helper_spec.rb +92 -0
  70. data/spec/aker/cas/middleware/logout_responder_spec.rb +47 -0
  71. data/spec/aker/cas/middleware/ticket_remover_spec.rb +49 -0
  72. data/spec/aker/cas/proxy_mode_spec.rb +185 -0
  73. data/spec/aker/cas/rack_proxy_callback_spec.rb +190 -0
  74. data/spec/aker/cas/service_mode_spec.rb +122 -0
  75. data/spec/aker/cas/service_url_spec.rb +114 -0
  76. data/spec/aker/cas/user_ext_spec.rb +27 -0
  77. data/spec/aker/cas_spec.rb +19 -0
  78. data/spec/aker/central_parameters_spec.rb +44 -0
  79. data/spec/aker/configuration_spec.rb +465 -0
  80. data/spec/aker/deprecation_spec.rb +115 -0
  81. data/spec/aker/form/a_form_mode.rb +129 -0
  82. data/spec/aker/form/custom_views_mode_spec.rb +34 -0
  83. data/spec/aker/form/login_form_asset_provider_spec.rb +80 -0
  84. data/spec/aker/form/middleware/a_form_login_responder.rb +89 -0
  85. data/spec/aker/form/middleware/custom_view_login_responder_spec.rb +47 -0
  86. data/spec/aker/form/middleware/login_renderer_spec.rb +56 -0
  87. data/spec/aker/form/middleware/login_responder_spec.rb +34 -0
  88. data/spec/aker/form/middleware/logout_responder_spec.rb +55 -0
  89. data/spec/aker/form/mode_spec.rb +15 -0
  90. data/spec/aker/form_spec.rb +11 -0
  91. data/spec/aker/group_membership_spec.rb +208 -0
  92. data/spec/aker/group_spec.rb +66 -0
  93. data/spec/aker/ldap/authority_spec.rb +414 -0
  94. data/spec/aker/ldap/ldap-users.ldif +197 -0
  95. data/spec/aker/ldap_spec.rb +11 -0
  96. data/spec/aker/modes/a_aker_mode.rb +41 -0
  97. data/spec/aker/modes/http_basic_spec.rb +127 -0
  98. data/spec/aker/modes/support/attempted_path_spec.rb +32 -0
  99. data/spec/aker/modes_spec.rb +11 -0
  100. data/spec/aker/rack/authenticate_spec.rb +78 -0
  101. data/spec/aker/rack/default_logout_responder_spec.rb +67 -0
  102. data/spec/aker/rack/facade_spec.rb +154 -0
  103. data/spec/aker/rack/failure_spec.rb +151 -0
  104. data/spec/aker/rack/logout_spec.rb +63 -0
  105. data/spec/aker/rack/request_ext_spec.rb +29 -0
  106. data/spec/aker/rack/session_timer_spec.rb +134 -0
  107. data/spec/aker/rack/setup_spec.rb +87 -0
  108. data/spec/aker/rack_spec.rb +216 -0
  109. data/spec/aker/test/helpers_spec.rb +44 -0
  110. data/spec/aker/user_spec.rb +362 -0
  111. data/spec/aker_spec.rb +80 -0
  112. data/spec/deprecation_helper.rb +58 -0
  113. data/spec/java_helper.rb +5 -0
  114. data/spec/logger_helper.rb +17 -0
  115. data/spec/matchers.rb +31 -0
  116. data/spec/mock_builder.rb +25 -0
  117. data/spec/spec_helper.rb +52 -0
  118. metadata +265 -0
@@ -0,0 +1,488 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ module Aker::Authorities
4
+ describe Composite do
5
+ def actual(*auths, &block)
6
+ conf = Aker::Configuration.new
7
+
8
+ conf.logger = spec_logger
9
+ conf.enhance(&block) if block
10
+
11
+ Composite.new(conf).tap do |c|
12
+ c.authorities = auths unless auths.empty?
13
+ end
14
+ end
15
+
16
+ def actual_log
17
+ @log_io.string
18
+ end
19
+
20
+ before do
21
+ @user = Aker::User.new("jo")
22
+
23
+ @a = Object.new
24
+ @b = Object.new
25
+ @c = Object.new
26
+ @comp = actual(@a, @b, @c)
27
+ end
28
+
29
+ describe "initialization" do
30
+ it "accepts a configuration instance" do
31
+ lambda { Composite.new(Aker::Configuration.new) }.should_not raise_error
32
+ end
33
+ end
34
+
35
+ describe "#authorities" do
36
+ it "uses the authorities from the configuration" do
37
+ actual { authorities Object.new, Object.new }.authorities.size.should == 2
38
+ end
39
+
40
+ it "prefers directly set authorities" do
41
+ comp = actual { authorities :static }
42
+ comp.authorities = [Static.new.tap { |s| s.valid_credentials!(:user, "foo", "bar") }]
43
+
44
+ comp.authorities.size.should == 1
45
+ comp.authorities.first.valid_credentials?(:user, "foo", "bar").should be_true
46
+ end
47
+ end
48
+
49
+ describe "#valid_credentials?" do
50
+ it "fails if none of the authorities implement valid_credentials?" do
51
+ expected = /No authentication-providing authority is configured./
52
+ lambda { @comp.valid_credentials?(:magic, 'foo') }.should raise_error expected
53
+ end
54
+
55
+ def implement_on(authority, with_user)
56
+ (class << authority; self; end).class_eval do
57
+ define_method(:valid_credentials?) do |kind, *credentials|
58
+ with_user
59
+ end
60
+ end
61
+ end
62
+
63
+ it "returns the first user returned by any authority" do
64
+ implement_on(@a, nil)
65
+ implement_on(@b, Aker::User.new("b"))
66
+ implement_on(@c, Aker::User.new("c"))
67
+
68
+ @comp.valid_credentials?(:magic, "man").username.should == "b"
69
+ end
70
+
71
+ it "returns nil if none of the authorities return a user" do
72
+ implement_on(@a, nil)
73
+ implement_on(@b, :unsupported)
74
+
75
+ @comp.valid_credentials?(:magic, "man").should be_nil
76
+ end
77
+
78
+ it "returns nil if all the authorities return :unsupported" do
79
+ implement_on(@a, :unsupported)
80
+ implement_on(@b, :unsupported)
81
+
82
+ @comp.valid_credentials?(:magic, "man").should be_nil
83
+ end
84
+
85
+ it "returns false if any of the authorities returns false" do
86
+ implement_on(@a, @user)
87
+ implement_on(@b, false)
88
+
89
+ @comp.valid_credentials?(:magic, "man").should == false
90
+ end
91
+
92
+ it "returns false if any of the authorities veto" do
93
+ implement_on(@b, @user)
94
+ def @c.veto?(user); true; end
95
+
96
+ @comp.valid_credentials?(:magic, "man").should == false
97
+ end
98
+
99
+ it "amplifies the returned user" do
100
+ implement_on(@c, @user)
101
+ def @a.amplify!(user); user.identifiers[:personnel_id] = 17; user; end
102
+
103
+ @comp.valid_credentials?(:magic, "man").identifiers[:personnel_id].should == 17
104
+ end
105
+
106
+ describe "callbacks" do
107
+ describe "on_authentication_success" do
108
+ before do
109
+ args = {}
110
+ (class << @b; self; end).class_eval do
111
+ define_method(:on_authentication_success) do |user, kind, credentials, authority|
112
+ args.merge!(:user => user, :credentials => credentials,
113
+ :kind => kind, :authority => authority)
114
+ end
115
+ end
116
+ @args = args
117
+ end
118
+
119
+ describe "when successful" do
120
+ before do
121
+ implement_on(@a, @user)
122
+ @comp.valid_credentials?(:user, "jo", "pirate")
123
+ end
124
+
125
+ it "receives the right user" do
126
+ @args[:user].should == @user
127
+ end
128
+
129
+ it "receives the right kind" do
130
+ @args[:kind].should == :user
131
+ end
132
+
133
+ it "receives the right credentials" do
134
+ @args[:credentials].should == ["jo", "pirate"]
135
+ end
136
+
137
+ it "receives the right authority" do
138
+ @args[:authority].should == @a
139
+ end
140
+
141
+ it "logs an appropriate message" do
142
+ actual_log.should =~ /User "jo" was successfully authenticated by Object./
143
+ end
144
+ end
145
+
146
+ it "is not invoked on failure" do
147
+ implement_on(@c, nil)
148
+ @comp.valid_credentials?(:user, "jo", "pirate")
149
+ @args.should be_empty
150
+ end
151
+ end
152
+
153
+ describe "on_authentication_failure" do
154
+ before do
155
+ args = {}
156
+ (class << @b; self; end).class_eval do
157
+ define_method(:on_authentication_failure) do |user, kind, credentials, reason|
158
+ args.merge!(:user => user, :credentials => credentials,
159
+ :kind => kind, :reason => reason)
160
+ end
161
+ end
162
+ @args = args
163
+ end
164
+
165
+ it "is not invoked on success" do
166
+ implement_on(@b, @user)
167
+ @comp.valid_credentials?(:user, "jo", "pirate")
168
+ @args.should be_empty
169
+ end
170
+
171
+ describe "on failure" do
172
+ def validate
173
+ @comp.valid_credentials?(:user, "jo", "piraat")
174
+ end
175
+
176
+ before do
177
+ implement_on(@a, nil)
178
+ implement_on(@b, :unsupported)
179
+ validate
180
+ end
181
+
182
+ it "receives the right kind" do
183
+ @args[:kind].should == :user
184
+ end
185
+
186
+ it "receives the right credentials" do
187
+ @args[:credentials].should == ["jo", "piraat"]
188
+ end
189
+
190
+ describe "because of bad creds" do
191
+ it "receives the right message" do
192
+ @args[:reason].should == "invalid credentials"
193
+ end
194
+
195
+ it "receives no user" do
196
+ @args[:user].should be_nil
197
+ end
198
+
199
+ it "logs an appropriate message" do
200
+ actual_log.should =~ /Authentication attempt failed: invalid credentials./
201
+ end
202
+ end
203
+
204
+ describe "because the kind is not supported" do
205
+ before do
206
+ implement_on(@a, :unsupported)
207
+ validate
208
+ end
209
+
210
+ it "receives the right reason" do
211
+ @args[:reason].should == "no configured authorities support :user credentials"
212
+ end
213
+
214
+ it "receives no user" do
215
+ @args[:user].should be_nil
216
+ end
217
+
218
+ it "logs an appropriate message" do
219
+ actual_log.should =~ /Authentication attempt failed: no configured authorities support :user credentials./
220
+ end
221
+ end
222
+
223
+ describe "because of a valid_credentials? veto" do
224
+ before do
225
+ implement_on(@a, false)
226
+ implement_on(@b, @user)
227
+ implement_on(@c, false)
228
+ def @a.to_s; "A"; end
229
+ def @c.to_s; "C"; end
230
+ validate
231
+ end
232
+
233
+ it "receives the right reason" do
234
+ @args[:reason].should == "credentials vetoed by A, C"
235
+ end
236
+
237
+ it "receives the user" do
238
+ @args[:user].should == @user
239
+ end
240
+
241
+ it "logs an appropriate message" do
242
+ actual_log.should =~ /Authentication attempt by "jo" failed: credentials vetoed by A, C./
243
+ end
244
+ end
245
+
246
+ describe "because of a veto? veto" do
247
+ before do
248
+ implement_on(@c, @user)
249
+ def @a.veto?(user); true; end
250
+ def @b.veto?(user); true; end
251
+ def @a.to_s; "A"; end
252
+ def @b.to_s; "B"; end
253
+ validate
254
+ end
255
+
256
+ it "receives the right reason" do
257
+ @args[:reason].should == "user vetoed by A, B"
258
+ end
259
+
260
+ it "receives the user" do
261
+ @args[:user].should == @user
262
+ end
263
+ end
264
+ end
265
+ end
266
+ end
267
+ end
268
+
269
+ describe "#veto?" do
270
+ it "returns false if none of the authorities implement veto?" do
271
+ @comp.veto?(@user).should be_false
272
+ end
273
+
274
+ it "returns false if all the implementors return falsy values" do
275
+ def @a.veto?(u); false; end
276
+ def @b.veto?(u); nil; end
277
+
278
+ @comp.veto?(@user).should be_false
279
+ end
280
+
281
+ it "returns true if one of the authorities returns true" do
282
+ def @a.veto?(u); true; end
283
+ def @b.veto?(u); false; end
284
+
285
+ @comp.veto?(@user).should be_true
286
+ end
287
+ end
288
+
289
+ describe "#on_authentication_success" do
290
+ it "doesn't cause an error if none of the authorities implement it" do
291
+ lambda { @comp.on_authentication_success(Aker::User.new("dc"), :dc, [:dc], :dc) }.
292
+ should_not raise_error
293
+ end
294
+
295
+ def implement_on(auth)
296
+ captured_args = {}
297
+ (class << auth; self; end).class_eval do
298
+ define_method(:on_authentication_success) do |user, kind, credentials, authority|
299
+ captured_args.merge!(:user => user, :credentials => credentials,
300
+ :kind => kind, :authority => authority)
301
+ end
302
+ end
303
+ captured_args
304
+ end
305
+
306
+ describe "invocation" do
307
+ before do
308
+ @a_args = implement_on(@a)
309
+ @b_args = implement_on(@b)
310
+ @comp.on_authentication_success(@user, :magic, ["frob"], @a)
311
+ end
312
+
313
+ { "A" => :@a_args, "B" => :@b_args }.each_pair do |name, arg_var|
314
+ describe "on #{name}" do
315
+ before do
316
+ @args = instance_variable_get(arg_var)
317
+ end
318
+
319
+ it "passes on the user" do
320
+ @args[:user].username.should == @user.username
321
+ end
322
+
323
+ it "passes on the credential kind" do
324
+ @args[:kind].should == :magic
325
+ end
326
+
327
+ it "passes on the credentials" do
328
+ @args[:credentials].should == ["frob"]
329
+ end
330
+
331
+ it "passes on the authority" do
332
+ @args[:authority].object_id.should == @a.object_id
333
+ end
334
+ end
335
+ end
336
+ end
337
+ end
338
+
339
+ describe "#on_authentication_failure" do
340
+ it "doesn't cause an error if none of the authorities implement it" do
341
+ lambda { @comp.on_authentication_failure(Aker::User.new("dc"), :dc, [:dc], :dc) }.
342
+ should_not raise_error
343
+ end
344
+
345
+ def implement_on(auth)
346
+ captured_args = {}
347
+ (class << auth; self; end).class_eval do
348
+ define_method(:on_authentication_failure) do |user, kind, credentials, reason|
349
+ captured_args.merge!(:user => user, :credentials => credentials,
350
+ :kind => kind, :reason => reason)
351
+ end
352
+ end
353
+ captured_args
354
+ end
355
+
356
+ describe "invocation" do
357
+ before do
358
+ @a_args = implement_on(@a)
359
+ @b_args = implement_on(@b)
360
+ @comp.on_authentication_failure(@user, :magic, ["frob"], "A said no")
361
+ end
362
+
363
+ { "A" => :@a_args, "B" => :@b_args }.each_pair do |name, arg_var|
364
+ describe "on #{name}" do
365
+ before do
366
+ @args = instance_variable_get(arg_var)
367
+ end
368
+
369
+ it "passes on the user" do
370
+ @args[:user].username.should == @user.username
371
+ end
372
+
373
+ it "passes on the credential kind" do
374
+ @args[:kind].should == :magic
375
+ end
376
+
377
+ it "passes on the credentials" do
378
+ @args[:credentials].should == ["frob"]
379
+ end
380
+
381
+ it "passes on the authority" do
382
+ @args[:reason].should == "A said no"
383
+ end
384
+ end
385
+ end
386
+ end
387
+ end
388
+
389
+ describe "#amplify!" do
390
+ it "adds the default portal from the configuration if there is one" do
391
+ actual { portal :ENU; authority :static }.amplify!(@user)
392
+ @user.default_portal.should == :ENU
393
+ end
394
+
395
+ it "does not cause an error if the configuration doesn't have a portal" do
396
+ lambda { actual(@a).amplify!(@user) }.should_not raise_error
397
+ end
398
+
399
+ it "doesn't cause an error if none of the authorities implement it" do
400
+ lambda { @comp.amplify!(@user) }.should_not raise_error
401
+ end
402
+
403
+ it "returns the same user that was passed in" do
404
+ @comp.amplify!(@user).object_id.should == @user.object_id
405
+ end
406
+
407
+ it "passes the user to all the authorities" do
408
+ def @a.amplify!(user); user.last_name = "Miller"; user; end
409
+ def @b.amplify!(user); user.first_name = "Jo"; user; end
410
+
411
+ @comp.amplify!(@user)
412
+
413
+ @user.first_name.should == "Jo"
414
+ @user.last_name.should == "Miller"
415
+ end
416
+
417
+ it "passes the user to all the authorities in order" do
418
+ def @a.amplify!(user); user.city = "Chicago" unless user.city; user; end
419
+ def @b.amplify!(user); user.city = "Evanston" unless user.city; user; end
420
+
421
+ @comp.amplify!(@user).city.should == "Chicago"
422
+ end
423
+ end
424
+
425
+ describe "#find_users" do
426
+ it "returns an empty array if none of the authorities implement find_users" do
427
+ @comp.find_users("wak").should == []
428
+ end
429
+
430
+ it "aggregates distinct users into a single response array" do
431
+ def @a.find_users(*options); [ Aker::User.new("fred") ]; end
432
+ def @c.find_users(*options); [ Aker::User.new("katherine") ]; end
433
+
434
+ @comp.find_users(:something => "foo").
435
+ collect { |u| u.username }.should == %w(fred katherine)
436
+ end
437
+
438
+ it "merges users with the same username in authority order" do
439
+ def @a.find_users(options)
440
+ [ Aker::User.new('jo').tap { |u| u.first_name = 'Jo'; u.city = 'Chicago'; },
441
+ Aker::User.new('alice') ]
442
+ end
443
+ def @b.find_users(options)
444
+ [ Aker::User.new('jo').tap { |u| u.last_name = 'Mueller'; u.city = 'Evanston'; },
445
+ Aker::User.new('betty') ]
446
+ end
447
+
448
+ actual = @comp.find_users('jo')
449
+ actual.size.should == 3
450
+ actual.collect { |u| u.username }.should == %w(jo alice betty)
451
+ actual.first.full_name.should == "Jo Mueller"
452
+ actual.first.city.should == "Chicago"
453
+ end
454
+
455
+ it "rejects nil authority responses" do
456
+ def @a.find_users(*options); [ nil ]; end
457
+ def @c.find_users(*options); nil; end
458
+
459
+ @comp.find_users(:etc => 'alia').should == []
460
+ end
461
+
462
+ it "splats the arguments given to the authorities" do
463
+ def @a.find_users(*options); @options = options; []; end
464
+ def @a.actual_options; @options; end
465
+
466
+ @comp.find_users(:email => 'baz')
467
+ @a.actual_options.should == [{ :email => 'baz' }]
468
+ end
469
+
470
+ it "amplifies found users" do
471
+ def @a.find_users(*options); [ Aker::User.new('jo') ]; end
472
+ def @a.amplify!(user); user.last_name = "Miller"; user; end
473
+ def @b.amplify!(user); user.first_name = "Jo"; user; end
474
+
475
+ actual = @comp.find_users('jo')
476
+ actual.size.should == 1
477
+ actual.first.full_name.should == "Jo Miller"
478
+ end
479
+ end
480
+
481
+ describe "#find_user" do
482
+ # behavior is tested in the module spec
483
+ it "exists" do
484
+ @comp.should respond_to(:find_user)
485
+ end
486
+ end
487
+ end
488
+ end
Binary file