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.
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,154 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ module Aker::Rack
4
+ describe Facade do
5
+ ##
6
+ # @return [Object] the options passed to the warden throw
7
+ # @raise RuntimeError if :warden is never thrown
8
+ def catch_warden_throw(&block)
9
+ opts = catch(:warden) do
10
+ block.call
11
+ end
12
+ if opts
13
+ opts
14
+ else
15
+ fail ":warden not thrown (or thrown without options)"
16
+ end
17
+ end
18
+
19
+ before do
20
+ @user = Aker::User.new("jo")
21
+ @user.portals << :ENU
22
+ @user.default_portal = :ENU
23
+ @user.group_memberships << Aker::GroupMembership.new(Aker::Group.new("User"))
24
+
25
+ @config = Aker::Configuration.new {
26
+ portal :ENU
27
+ }
28
+
29
+ @with_user = Facade.new(@config, @user)
30
+ @without_user = Facade.new(@config, nil)
31
+ end
32
+
33
+ describe "#authentication_required!" do
34
+ it "throws to warden if there's no user" do
35
+ catch_warden_throw {
36
+ @without_user.authentication_required!
37
+ }.should == { :login_required => true }
38
+ end
39
+
40
+ describe "with a user" do
41
+ it "does not throw to warden if the user is authenticated and in the proper portal" do
42
+ lambda { @with_user.authentication_required! }.should_not raise_error
43
+ end
44
+
45
+ it "throws to warden if the user isn't permitted to access the configured portal" do
46
+ @config.portal = :NOTIS
47
+ catch_warden_throw {
48
+ @with_user.authentication_required!
49
+ }.should == { :portal_required => :NOTIS }
50
+ end
51
+
52
+ it "does not throw to warden if there's no configured portal" do
53
+ @config.portal = nil
54
+ lambda { @with_user.authentication_required! }.should_not raise_error
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "#authenticated?" do
60
+ it "returns false if there's not a user" do
61
+ @without_user.should_not be_authenticated
62
+ end
63
+
64
+ describe "with a user" do
65
+ it "returns true if the user is in the configured portal" do
66
+ @with_user.should be_authenticated
67
+ end
68
+
69
+ it "returns false if the user is not in the configured portal" do
70
+ @config.portal = :NOTIS
71
+ @with_user.should_not be_authenticated
72
+ end
73
+
74
+ it "returns true if there is no configured portal" do
75
+ @config.portal = nil
76
+ @with_user.should be_authenticated
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "#permit?" do
82
+ describe "without a block" do
83
+ it "returns true if the facade user is in the group" do
84
+ @with_user.permit?(:User).should be_true
85
+ end
86
+
87
+ it "returns false if the user is not in the group" do
88
+ @with_user.permit?(:Admin).should be_false
89
+ end
90
+
91
+ it "returns false without a user" do
92
+ @without_user.permit?(:User).should be_false
93
+ end
94
+ end
95
+
96
+ describe "with a block" do
97
+ it "evaluates the block if the facade user is in the group" do
98
+ executed = false
99
+ @with_user.permit?(:User) do
100
+ executed = true
101
+ end
102
+
103
+ executed.should be_true
104
+ end
105
+
106
+ it "does not evaluate the block if the facade user is not in the group" do
107
+ executed = false
108
+ @with_user.permit?(:Admin) do
109
+ executed = true
110
+ end
111
+
112
+ executed.should be_false
113
+ end
114
+
115
+ it "does not evaluate the block if there is no user" do
116
+ executed = false
117
+ @without_user.permit?(:User) do
118
+ executed = true
119
+ end
120
+
121
+ executed.should be_false
122
+ end
123
+ end
124
+
125
+ it "is aliased as permit (without the question mark)" do
126
+ @with_user.permit(:User).should be_true
127
+ end
128
+ end
129
+
130
+ describe "#permit!" do
131
+ it "tells warden authentication is required if there's no user" do
132
+ catch_warden_throw {
133
+ @without_user.permit!(:User)
134
+ }.should == { :login_required => true }
135
+ end
136
+
137
+ it "tells warden that particular groups are required if the user isn't in any of them" do
138
+ catch_warden_throw {
139
+ @with_user.permit!(:Developer, :Admin)
140
+ }.should == { :groups_required => [:Developer, :Admin] }
141
+ end
142
+ end
143
+
144
+ describe "#user" do
145
+ it "returns the user if there's a user" do
146
+ @with_user.user.username.should == "jo"
147
+ end
148
+
149
+ it "returns nil if there's no user" do
150
+ @without_user.user.should be_nil
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,151 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ require 'rack/mock'
4
+
5
+ module Aker::Rack
6
+ describe Failure do
7
+ before do
8
+ @config = Aker::Configuration.new
9
+ @config.logger = spec_logger
10
+ @env = ::Rack::MockRequest.env_for("/", "aker.configuration" => @config)
11
+ @app = Failure.new
12
+ end
13
+
14
+ after do
15
+ Warden::Strategies.clear!
16
+ end
17
+
18
+ def call
19
+ @app.call(@env)
20
+ end
21
+
22
+ def actual_code
23
+ call[0]
24
+ end
25
+
26
+ def actual_headers
27
+ call[1]
28
+ end
29
+
30
+ def actual_body
31
+ actual_lines = []
32
+ call[2].each { |l| actual_lines << l }
33
+ actual_lines.join
34
+ end
35
+
36
+ describe "of authorization" do
37
+ before do
38
+ @env['aker.check'] = Facade.new(@env["aker.configuration"], Aker::User.new("jo"))
39
+ end
40
+
41
+ shared_examples_for "an authorization failure" do
42
+ it "403s" do
43
+ actual_code.should == 403
44
+ end
45
+
46
+ it "returns HTML" do
47
+ actual_headers["Content-Type"].should == "text/html"
48
+ end
49
+
50
+ it "returns a somewhat friendly message" do
51
+ actual_body.should ==
52
+ "<html><head><title>Authorization denied</title></head><body>jo may not use this page.</body></html>"
53
+ end
54
+ end
55
+
56
+ describe "at the portal level" do
57
+ before do
58
+ @env['warden.options'] = { :portal_required => :ENU }
59
+ end
60
+
61
+ it_should_behave_like "an authorization failure"
62
+
63
+ it "logs the failure appropriately" do
64
+ call
65
+ actual_log.should =~ /Resource authorization failure: User "jo" is not in the :ENU portal./
66
+ end
67
+ end
68
+
69
+ describe "at the group level" do
70
+ before do
71
+ @env['warden.options'] = { :groups_required => [:Admin, :Developer] }
72
+ end
73
+
74
+ it_should_behave_like "an authorization failure"
75
+
76
+ it "logs the failure appropriately" do
77
+ call
78
+ actual_log.should =~ /Resource authorization failure: User "jo" is not in any of the required groups \[:Admin, :Developer\]./
79
+ end
80
+ end
81
+ end
82
+
83
+ describe "of authentication" do
84
+ before do
85
+ @env['warden.options'] = { :login_required => true }
86
+ end
87
+
88
+ describe "when interactive" do
89
+ before do
90
+ Warden::Strategies.add(:fake_ui) do
91
+ def authenticate!; nil; end
92
+ def on_ui_failure
93
+ ::Rack::Response.new(["UI failed!"], 403, {})
94
+ end
95
+ end
96
+
97
+ @env['aker.interactive'] = true
98
+ @env['aker.configuration'].ui_mode = :fake_ui
99
+ end
100
+
101
+ it "invokes #on_ui_failure on the appropriate mode" do
102
+ actual_code.should == 403
103
+ actual_body.should == "UI failed!"
104
+ end
105
+ end
106
+
107
+ describe "when not interactive" do
108
+ before do
109
+ @env['aker.interactive'] = false
110
+
111
+ %w(Alpha Beta).each do |n|
112
+ cls = Class.new(Aker::Modes::Base)
113
+ cls.class_eval <<-RUBY
114
+ include Aker::Modes::Support::Rfc2617
115
+ def authenticate!; nil; end
116
+ def scheme; #{n.inspect}; end
117
+ RUBY
118
+ Warden::Strategies.add(n.downcase.to_sym, cls)
119
+ end
120
+ end
121
+
122
+ it "responds with a challenge" do
123
+ @env['aker.configuration'].api_mode = :beta
124
+
125
+ actual = call
126
+ actual[0].should == 401
127
+ actual[1]["WWW-Authenticate"].should == 'Beta realm="Aker"'
128
+ end
129
+
130
+ it "responds for with challenges for all modes" do
131
+ @env['aker.configuration'].api_mode = [:beta, :alpha]
132
+
133
+ actual_headers["WWW-Authenticate"].should == %Q{Beta realm="Aker"\nAlpha realm="Aker"}
134
+ end
135
+
136
+ it "uses the portal as the realm if it is set" do
137
+ @env['aker.configuration'].portal = :ENU
138
+ @env['aker.configuration'].api_mode = [:alpha]
139
+
140
+ actual_headers["WWW-Authenticate"].should == %Q{Alpha realm="ENU"}
141
+ end
142
+
143
+ it "gives a human-readable message in the body for debugging" do
144
+ @env['aker.configuration'].api_mode = :beta
145
+ actual_headers["Content-Type"].should == "text/plain"
146
+ actual_body.should == "Authentication required"
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,63 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+ require 'rack/test'
3
+
4
+ module Aker::Rack
5
+ describe Logout do
6
+ include Rack::Test::Methods
7
+
8
+ let(:path) { '/auth/logout' }
9
+
10
+ let(:app) do
11
+ Rack::Builder.new do
12
+ use Aker::Rack::Logout
13
+ run lambda { |env| [200, {'Content-Type' => 'text/html'}, ['from the app']] }
14
+ end
15
+ end
16
+
17
+ let(:warden) { stub.as_null_object }
18
+
19
+ let(:config) do
20
+ p = path
21
+ Aker::Configuration.new {
22
+ rack_parameters :logout_path => p
23
+ }
24
+ end
25
+
26
+ let(:env) do
27
+ {
28
+ 'warden' => warden,
29
+ 'aker.configuration' => config
30
+ }
31
+ end
32
+
33
+ describe '#call' do
34
+ context 'given GET {the configured path}' do
35
+ it 'instructs Warden to log out' do
36
+ warden.should_receive(:logout)
37
+
38
+ get path, {}, env
39
+ end
40
+
41
+ it 'passes control to the rest of the app' do
42
+ get path, {}, env
43
+
44
+ last_response.body.should == 'from the app'
45
+ end
46
+ end
47
+
48
+ context 'given GET (some other path)' do
49
+ it 'does not instruct Warden to log out' do
50
+ warden.should_receive(:logout).never
51
+
52
+ get '/', {}, env
53
+ end
54
+
55
+ it 'passes control to the rest of the app' do
56
+ get '/', {}, env
57
+
58
+ last_response.body.should == 'from the app'
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ require 'rack'
4
+
5
+ module Aker::Rack
6
+ describe RequestExt do
7
+ let(:request_class) do
8
+ Class.new(Rack::Request) do
9
+ include RequestExt
10
+ end
11
+ end
12
+
13
+ let(:request) { request_class.new({}) }
14
+
15
+ describe '#interactive?' do
16
+ it 'returns true if the request is interactive' do
17
+ request.env['aker.interactive'] = true
18
+
19
+ request.should be_interactive
20
+ end
21
+
22
+ it 'returns false if the request is non-interactive' do
23
+ request.env['aker.interactive'] = false
24
+
25
+ request.should_not be_interactive
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,134 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+ require 'rack/test'
3
+
4
+ module Aker::Rack
5
+ describe SessionTimer do
6
+ let(:app) { stub.as_null_object }
7
+ let(:configuration) { Aker::Configuration.new { rack_parameters :logout_path => '/a/logout' } }
8
+ let(:env) {
9
+ {
10
+ 'aker.configuration' => configuration,
11
+ 'rack.session' => session,
12
+ 'warden' => warden
13
+ }
14
+ }
15
+ let(:expected_timeout) { 600 }
16
+ let(:session) { {} }
17
+ let(:timer) { SessionTimer.new(app) }
18
+ let(:warden) { mock }
19
+
20
+ before do
21
+ configuration.add_parameters_for(:policy, %s(session-timeout-seconds) => expected_timeout)
22
+ end
23
+
24
+ describe "#call" do
25
+ let(:current_request_time) { 1234567890 }
26
+
27
+ before do
28
+ Time.stub!(:now => Time.at(current_request_time))
29
+ end
30
+
31
+ it "sets aker.timeout_at" do
32
+ timer.call(env)
33
+
34
+ env['aker.timeout_at'].should == current_request_time + expected_timeout
35
+ end
36
+
37
+ context 'if no session timeout is given' do
38
+ before do
39
+ configuration.add_parameters_for(:policy, %s(session-timeout-seconds) => nil)
40
+ end
41
+
42
+ it 'passes control down the Rack stack' do
43
+ app.should_receive(:call)
44
+
45
+ timer.call(env)
46
+ end
47
+ end
48
+
49
+ context 'if no last request timestamp is present' do
50
+ before do
51
+ session['aker.last_request_at'] = nil
52
+ end
53
+
54
+ it 'sets last request time to the current request time' do
55
+ timer.call(env)
56
+
57
+ session['aker.last_request_at'].should == current_request_time
58
+ end
59
+
60
+ it 'passes control down the Rack stack' do
61
+ app.should_receive(:call)
62
+
63
+ timer.call(env)
64
+ end
65
+ end
66
+
67
+ context 'if a last request timestamp is present' do
68
+ context 'and the current request is within the timeout window' do
69
+ before do
70
+ #
71
+ # The below calculation places the current request time in the
72
+ # middle of the session timeout window:
73
+ #
74
+ # prv cur
75
+ # | |
76
+ # |------|
77
+ # |e.t./2|
78
+ # |------------
79
+ # | e.t.
80
+ #
81
+ session['aker.last_request_at'] = current_request_time - (expected_timeout / 2)
82
+ end
83
+
84
+ it 'sets the last request timestamp' do
85
+ timer.call(env)
86
+
87
+ session['aker.last_request_at'].should == current_request_time
88
+ end
89
+
90
+ it 'passes control down the Rack stack' do
91
+ app.should_receive(:call)
92
+
93
+ timer.call(env)
94
+ end
95
+ end
96
+
97
+ context 'and the current request is outside the timeout window' do
98
+ before do
99
+ #
100
+ # The below calculation places the current request time at the edge
101
+ # of the session timeout window:
102
+ #
103
+ # prv cur
104
+ # | |
105
+ # |------------|
106
+ # | e.t. |
107
+ #
108
+ session['aker.last_request_at'] = current_request_time - expected_timeout
109
+
110
+ warden.stub!(:logout)
111
+ end
112
+
113
+ it 'passes control down the Rack stack' do
114
+ app.should_receive(:call)
115
+
116
+ timer.call(env)
117
+ end
118
+
119
+ it 'resets the session' do
120
+ warden.should_receive(:logout)
121
+
122
+ timer.call(env)
123
+ end
124
+
125
+ it 'sets the session expired flag in the environment' do
126
+ timer.call(env)
127
+
128
+ env['aker.session_expired'].should == true
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,87 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ module Aker::Rack
4
+ describe Setup do
5
+ let(:app) { lambda { |x| x } }
6
+ let(:configuration) { Aker::Configuration.new }
7
+ let(:middleware) { Setup.new(app, configuration) }
8
+
9
+ def call(env = {})
10
+ middleware.call(env)
11
+ end
12
+
13
+ describe "env['aker.configuration']" do
14
+ it "is the configuration provided in its constructor" do
15
+ env = call
16
+
17
+ env['aker.configuration'].should == configuration
18
+ end
19
+ end
20
+
21
+ describe "env['aker.authority']" do
22
+ it "is the authority from the configuration" do
23
+ authority = stub
24
+ configuration.stub!(:composite_authority => authority)
25
+
26
+ env = call
27
+
28
+ env['aker.authority'].should == authority
29
+ end
30
+ end
31
+
32
+ describe "env['aker.interactive']" do
33
+ it "is true if the Accept header includes text/html" do
34
+ env = call("HTTP_ACCEPT" =>
35
+ "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5")
36
+
37
+ env['aker.interactive'].should be_true
38
+ end
39
+
40
+ describe "when there are any API modes" do
41
+ let(:configuration) do
42
+ Aker::Configuration.new do
43
+ api_mode :http_basic
44
+ end
45
+ end
46
+
47
+ it "is false if the Accept header does not include text/html" do
48
+ env = call("HTTP_ACCEPT" => "*/*")
49
+
50
+ env['aker.interactive'].should be_false
51
+ end
52
+
53
+ it "is false if there is no Accept header" do
54
+ env = call
55
+
56
+ env['aker.interactive'].should be_false
57
+ end
58
+
59
+ it "is true if the User-Agent header contains 'Mozilla'" do
60
+ env = call("HTTP_USER_AGENT" => "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)")
61
+
62
+ env['aker.interactive'].should be_true
63
+ end
64
+ end
65
+
66
+ describe "when there are no API modes" do
67
+ it "is true if the Accept header does not include text/html" do
68
+ env = call("HTTP_ACCEPT" => "*/*")
69
+
70
+ env['aker.interactive'].should be_true
71
+ end
72
+
73
+ it "is true if there is no Accept header" do
74
+ env = call
75
+
76
+ env['aker.interactive'].should be_true
77
+ end
78
+ end
79
+ end
80
+
81
+ it "always invokes the app" do
82
+ app.should_receive(:call)
83
+
84
+ middleware.call({})
85
+ end
86
+ end
87
+ end