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
data/lib/aker/rack.rb ADDED
@@ -0,0 +1,107 @@
1
+ require 'aker'
2
+ require 'warden'
3
+
4
+ ##
5
+ # Integration of Aker with {http://rack.rubyforge.org/ Rack}.
6
+ module Aker::Rack
7
+ autoload :Authenticate, 'aker/rack/authenticate'
8
+ autoload :ConfigurationHelper, 'aker/rack/configuration_helper'
9
+ autoload :DefaultLogoutResponder, 'aker/rack/default_logout_responder'
10
+ autoload :EnvironmentHelper, 'aker/rack/environment_helper'
11
+ autoload :Facade, 'aker/rack/facade'
12
+ autoload :Failure, 'aker/rack/failure'
13
+ autoload :Logout, 'aker/rack/logout'
14
+ autoload :RequestExt, 'aker/rack/request_ext'
15
+ autoload :SessionTimer, 'aker/rack/session_timer'
16
+ autoload :Setup, 'aker/rack/setup'
17
+
18
+ class << self
19
+ ##
20
+ # Configures all the necessary middleware for Aker into the given
21
+ # rack application stack. With `Rack::Builder`:
22
+ #
23
+ # Rack::Builder.new do
24
+ # Aker::Rack.use_in(self) # self is the builder instance
25
+ # end
26
+ #
27
+ # Aker's middleware stack relies on the existence of a session,
28
+ # so the session-enabling middleware must be higher in the
29
+ # application stack than Aker.
30
+ #
31
+ # @param [#use] builder the target application builder. This
32
+ # could be a `Rack::Builder` object or something that acts like
33
+ # one.
34
+ # @param [Aker::Configuration,nil] configuration the
35
+ # configuration to apply to this use. If nil, uses the global
36
+ # configuration ({Aker.configuration}).
37
+ # @return [void]
38
+ def use_in(builder, configuration=nil)
39
+ effective_configuration = configuration || Aker.configuration
40
+ unless effective_configuration
41
+ fail "No configuration was provided and there's no global configuration. " <<
42
+ "Please set one or the other before calling use_in."
43
+ end
44
+
45
+ install_modes(effective_configuration)
46
+
47
+ builder.use Setup, effective_configuration
48
+
49
+ with_mode_middlewares(builder, effective_configuration) do
50
+ effective_configuration.install_middleware(:before_authentication, builder)
51
+ builder.use Warden::Manager do |manager|
52
+ manager.failure_app = Aker::Rack::Failure.new
53
+ end
54
+ builder.use SessionTimer
55
+ builder.use Authenticate
56
+ effective_configuration.install_middleware(:after_authentication, builder)
57
+ builder.use Logout
58
+ end
59
+
60
+ builder.use DefaultLogoutResponder
61
+ end
62
+
63
+ private
64
+
65
+ ##
66
+ # @return [void]
67
+ def install_modes(configuration)
68
+ configuration.registered_modes.each do |mode|
69
+ Warden::Strategies.add(mode.key, mode)
70
+ end
71
+ end
72
+
73
+ ##
74
+ # @return [void]
75
+ def with_mode_middlewares(builder, conf)
76
+ mode_classes(conf).each { |m| m.prepend_middleware(builder) if m.respond_to?(:prepend_middleware) }
77
+ yield
78
+ mode_classes(conf).each { |m| m.append_middleware(builder) if m.respond_to?(:append_middleware) }
79
+ end
80
+
81
+ def mode_classes(configuration)
82
+ return [] unless configuration
83
+
84
+ [configuration.ui_mode, configuration.api_modes].flatten.map do |key|
85
+ Warden::Strategies[key]
86
+ end
87
+ end
88
+
89
+ def logout_path(configuration)
90
+ configuration.parameters_for(:rack)[:logout_path]
91
+ end
92
+ end
93
+
94
+ ##
95
+ # @private
96
+ class Slice < Aker::Configuration::Slice
97
+ def initialize
98
+ super do
99
+ rack_parameters :login_path => '/login', :logout_path => '/logout'
100
+
101
+ policy_parameters :'session-timeout-seconds' => 1800
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ Aker::Configuration.add_default_slice(Aker::Rack::Slice.new)
@@ -0,0 +1,22 @@
1
+ require File.join(File.dirname(__FILE__), %w(.. test))
2
+
3
+ ##
4
+ # Contains helpers for writing tests on aker-protected code.
5
+ module Aker::Test::Helpers
6
+ ##
7
+ # Generates an environment hash that marks `user` as logged in. You can use
8
+ # the generated hash in pre-existing requests, merge the hash with the
9
+ # environment generated by `Rack::MockRequest.env_for`, etc.
10
+ #
11
+ # @param [String,Aker::User] user
12
+ # a user's username or a {Aker::User} object. Your Aker configuration
13
+ # must use an authority that implements `find_user` for username lookup to
14
+ # work.
15
+ # @return [Hash<String, Aker::Rack::Facade>] a Hash of the form
16
+ # `{'aker' => (a Aker::Rack::Facade)}`
17
+ def login_env(user)
18
+ u = Aker::User === user ? user : Aker.authority.find_user(user)
19
+
20
+ { 'aker.check' => Aker::Rack::Facade.new(Aker.configuration, u) }
21
+ end
22
+ end
data/lib/aker/test.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'aker'
2
+
3
+ ##
4
+ # Code useful for testing aker-protected applications can be found in this
5
+ # namespace.
6
+ module Aker::Test
7
+ autoload :Helpers, 'aker/test/helpers'
8
+ end
data/lib/aker/user.rb ADDED
@@ -0,0 +1,231 @@
1
+ require 'aker'
2
+
3
+ module Aker
4
+ ##
5
+ # @private
6
+ module DeprecatedUser
7
+ [:nu_employee_id, :personnel_id].each do |deprec_id|
8
+ define_method deprec_id do
9
+ Deprecation.notify(
10
+ "#{deprec_id} is deprecated. Use identifiers[#{deprec_id.inspect}] instead.", "3.0")
11
+ identifiers[deprec_id]
12
+ end
13
+
14
+ define_method "#{deprec_id}=" do |value|
15
+ Deprecation.notify(
16
+ "#{deprec_id} is deprecated. Use identifiers[#{deprec_id.inspect}] instead.", "3.0")
17
+ identifiers[deprec_id] = value
18
+ end
19
+ end
20
+ end
21
+
22
+ class User
23
+ include DeprecatedUser
24
+
25
+ ATTRIBUTES = :username, :first_name, :middle_name, :last_name,
26
+ :title, :business_phone, :fax, :email, :address, :city, :state, :country
27
+
28
+ attr_accessor *ATTRIBUTES
29
+
30
+ ##
31
+ # Specifies a default portal to use for subsequent calls which
32
+ # take a portal as a parameter.
33
+ #
34
+ # @return [Symbol, nil]
35
+ attr_accessor :default_portal
36
+
37
+ ##
38
+ # The portals to which this user has access.
39
+ #
40
+ # @return [Array<Symbol>]
41
+ # @see #may_access?
42
+ attr_accessor :portals
43
+
44
+ ##
45
+ # Creates a new instance.
46
+ #
47
+ # @param [String] username the username for this new user
48
+ # @param [Array<Symbol>] portals the portals to which this user
49
+ # has access.
50
+ def initialize(username, portals=[])
51
+ @username = username
52
+ @portals = [*portals]
53
+ end
54
+
55
+ ##
56
+ # @param [#to_sym,nil] portal the portal in question. If nil,
57
+ # uses {#default_portal}.
58
+ # @return [Boolean] true if the user has access, otherwise false.
59
+ def may_access?(portal=nil)
60
+ portals.include?((portal || required_default_portal).to_sym)
61
+ end
62
+
63
+ ##
64
+ # @overload permit?(*groups, options={})
65
+ # Determines whether this user has access to any of the given
66
+ # groups.
67
+ # @param [Array<#to_sym>] groups the names of the groups to query
68
+ # @param [Hash] options additional constraints on the query
69
+ # @option options [#to_sym] :portal (#default_portal) the portal
70
+ # within which to do the group check
71
+ # @return [Boolean]
72
+ #
73
+ # @overload permit?(*groups, options={}, &block)
74
+ # Evaluates the given block if the user is in any of the given
75
+ # groups.
76
+ # @param [Array<#to_sym>] groups the names of the groups to use
77
+ # as the condition
78
+ # @param [Hash] options additional constraints on the condition
79
+ # @option options [#to_sym] :portal (#default_portal) the portal
80
+ # within which to do the group check
81
+ # @return [Object,nil] the value of the block if it is
82
+ # executed; otherwise nil
83
+ def permit?(*args)
84
+ options = args.last.is_a?(Hash) ? args.pop : { }
85
+ portal = options[:portal] || default_portal
86
+
87
+ permitted =
88
+ if args.empty?
89
+ may_access?(portal)
90
+ else
91
+ args.detect { |group| group_memberships(portal).include?(group.to_sym) }
92
+ end
93
+
94
+ if block_given?
95
+ permitted ? yield : nil
96
+ else
97
+ permitted
98
+ end
99
+ end
100
+
101
+ ##
102
+ # A display-friendly name for this user. Uses `first_name` and
103
+ # `last_name` if available, otherwise it just uses the username.
104
+ #
105
+ # @return [String]
106
+ def full_name
107
+ display_name_parts = [first_name, last_name].compact
108
+ if display_name_parts.empty?
109
+ username
110
+ else
111
+ display_name_parts.join(' ')
112
+ end
113
+ end
114
+
115
+ ##
116
+ # A mapping of identifers that apply to this user. The values that
117
+ # might be set in this hash are defined by authorities.
118
+ #
119
+ # @since 2.2.0
120
+ # @return [Hash<Symbol, Object>] the identifiers for this user.
121
+ def identifiers
122
+ @identifiers ||= {}
123
+ end
124
+
125
+ def portals
126
+ @portals ||= []
127
+ end
128
+
129
+ ##
130
+ # Exposes the {GroupMemberships group memberships} for a
131
+ # this user on a particular portal.
132
+ #
133
+ # This method never returns `nil`. Therefore, its return value
134
+ # should not be used to determine if a user has access to a portal
135
+ # &mdash; only for groups. Use {#may_access?} to determine portal
136
+ # access.
137
+ #
138
+ # @param [#to_sym,nil] portal the portal to get the memberships
139
+ # for. If nil, uses {#default_portal}.
140
+ #
141
+ # @return [GroupMemberships] for a particular portal
142
+ #
143
+ # @see GroupMemberships#include?
144
+ def group_memberships(portal=nil)
145
+ portal = (portal || required_default_portal).to_sym
146
+ all_group_memberships[portal] ||= GroupMemberships.new(portal)
147
+ end
148
+
149
+ ##
150
+ # Exposes all the group memberships that this instance knows
151
+ # about. In general, {#group_memberships} is preferred unless you
152
+ # really need to iterate over everything.
153
+ #
154
+ # @return [Hash<Symbol, GroupMemberships>]
155
+ def all_group_memberships
156
+ @gms ||= {}
157
+ end
158
+
159
+ def default_portal=(val)
160
+ @default_portal = val.nil? ? nil : val.to_sym
161
+ end
162
+
163
+ ##
164
+ # Modifies this user record in place, adding attributes from the
165
+ # other user. Merge rules:
166
+ #
167
+ # * For portals: the resulting portal list is a union of the
168
+ # portal list for this and the _other_ user.
169
+ # * For group memberships: group memberships are added from
170
+ # the _other_ user for all portals which this user doesn't
171
+ # already have group memberships. (That is, the group
172
+ # membership lists for a particular portal are not merged.)
173
+ # This rule is to prevent ambiguity if different
174
+ # authorities have different group hierarchies. In
175
+ # practice only one authority is providing authorization
176
+ # information for a portal, so this shouldn't matter.
177
+ # * For identifiers: any identifier in the _other_ user that is
178
+ # not already set in this user is copied over.
179
+ # * For all other attributes: an attribute is copied from
180
+ # _other_ if that attribute is not already set in this
181
+ # user.
182
+ #
183
+ # Note that these semantics are different from the semantics of
184
+ # `Hash#merge!` in the ruby standard library.
185
+ #
186
+ # @param [Aker::User] other the user from which to take attribute
187
+ # values
188
+ #
189
+ # @return [Aker::User] self
190
+ def merge!(other)
191
+ ATTRIBUTES.each do |getter|
192
+ already_set =
193
+ begin
194
+ self.send(getter)
195
+ rescue
196
+ false
197
+ end
198
+ unless already_set
199
+ setter = :"#{getter}="
200
+ value =
201
+ begin
202
+ other.send(getter)
203
+ rescue
204
+ nil # skip inaccessible attributes
205
+ end
206
+ self.send setter, value
207
+ end
208
+ end
209
+
210
+ self.default_portal ||= other.default_portal
211
+ self.portals |= other.portals
212
+ other.all_group_memberships.keys.each do |other_portal|
213
+ if self.group_memberships(other_portal).empty?
214
+ self.group_memberships(other_portal).concat(other.group_memberships(other_portal))
215
+ end
216
+ end
217
+ other.identifiers.each do |ident, value|
218
+ identifiers[ident] ||= value
219
+ end
220
+
221
+ self
222
+ end
223
+
224
+ protected
225
+
226
+ def required_default_portal
227
+ default_portal or raise "No default portal set. Please specify one explicitly."
228
+ end
229
+ end
230
+ end
231
+
@@ -0,0 +1,3 @@
1
+ module Aker
2
+ VERSION = "3.0.0.pre"
3
+ end
data/lib/aker.rb ADDED
@@ -0,0 +1,51 @@
1
+ module Aker
2
+ autoload :CentralParameters, 'aker/central_parameters'
3
+ autoload :Configuration, 'aker/configuration'
4
+ autoload :Deprecation, 'aker/deprecation'
5
+ autoload :Group, 'aker/group'
6
+ autoload :GroupMemberships, 'aker/group_membership'
7
+ autoload :GroupMembership, 'aker/group_membership'
8
+ autoload :User, 'aker/user'
9
+ autoload :Test, 'aker/test'
10
+ autoload :VERSION, 'aker/version'
11
+
12
+ class << self
13
+ ##
14
+ # @return [Configuration,nil] the single configuration for the
15
+ # system using aker. Created/updated using {.configure
16
+ # configure}.
17
+ attr_accessor :configuration
18
+
19
+ ##
20
+ # @return [Object,nil] a single authentication/authorization entry
21
+ # point conforming to the authority protocol as defined by
22
+ # {Aker::Authorities::Composite}. By default, it is
23
+ # automatically derived from the {.configuration configuration}.
24
+ # @see Aker::Configuration#composite_authority
25
+ attr_accessor :authority
26
+
27
+ ##
28
+ # Create/update the global aker configuration. Accepts a block
29
+ # containing expressions in the {Configuration} DSL.
30
+ #
31
+ # @see Aker.configuration
32
+ # @return [Configuration]
33
+ def configure(&block)
34
+ @configuration ||= Aker::Configuration.new
35
+ @configuration.enhance(&block)
36
+ end
37
+
38
+ def authority
39
+ @authority || (@configuration && @configuration.composite_authority)
40
+ end
41
+ end
42
+ end
43
+
44
+ # These files are required instead of autoloaded so that their
45
+ # configuration slices are installed immediately.
46
+ require 'aker/authorities'
47
+ require 'aker/cas'
48
+ require 'aker/form'
49
+ require 'aker/ldap'
50
+ require 'aker/modes'
51
+ require 'aker/rack'
@@ -0,0 +1,11 @@
1
+ netid:
2
+ user: cn=foo
3
+ cc_pers:
4
+ user: cc_pers_foo
5
+ password: secret
6
+ cas:
7
+ base_url: https://cas.example.edu
8
+ proxy_retrieval_url: https://cas.example.edu/retrieve_pgt
9
+ proxy_callback_url: https://cas.example.edu/receive_pgt
10
+ foo:
11
+ bar: baz
@@ -0,0 +1,52 @@
1
+ require File.expand_path("../../../spec_helper", __FILE__)
2
+
3
+ module Aker::Authorities
4
+ describe AutomaticAccess do
5
+ describe "initialization" do
6
+ it "fails if the configuration has no portal" do
7
+ lambda { AutomaticAccess.new(Aker::Configuration.new) }.should raise_error(
8
+ "AutomaticAccess is unnecessary if you don't have a portal configured.")
9
+ end
10
+ end
11
+
12
+ describe "#amplify!" do
13
+ before do
14
+ @authority = AutomaticAccess.new(Aker::Configuration.new { portal :ENU })
15
+ @user = Aker::User.new('jo')
16
+ end
17
+
18
+ it "adds the configured portal to the portal list" do
19
+ @authority.amplify!(@user)
20
+ @user.portals.should include(:ENU)
21
+ end
22
+
23
+ it "does not add the portal if it is already there" do
24
+ @user.portals << :ENU
25
+ @authority.amplify!(@user)
26
+ @user.portals.size.should == 1
27
+ end
28
+
29
+ it "sets the default portal if it isn't already set" do
30
+ @authority.amplify!(@user)
31
+ @user.default_portal.should == :ENU
32
+ end
33
+
34
+ it "leaves an existing default portal alone" do
35
+ @user.default_portal = :NOTIS
36
+ @authority.amplify!(@user)
37
+ @user.default_portal.should == :NOTIS
38
+ end
39
+
40
+ it "returns the user" do
41
+ @authority.amplify!(@user).should === @user
42
+ end
43
+
44
+ it "grants the user access" do
45
+ @user.may_access?(:ENU).should be_false
46
+ @authority.amplify!(@user)
47
+ @user.may_access?(:ENU).should be_true
48
+ @user.may_access?.should be_true
49
+ end
50
+ end
51
+ end
52
+ end