sparkly-auth 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (243) hide show
  1. data/.document +5 -0
  2. data/.gitignore +25 -0
  3. data/HISTORY.txt +7 -0
  4. data/README.rdoc +127 -1
  5. data/Rakefile +45 -13
  6. data/TODO +4 -0
  7. data/VERSION +1 -1
  8. data/app/controllers/sparkly_accounts_controller.rb +20 -13
  9. data/app/controllers/sparkly_controller.rb +5 -4
  10. data/app/controllers/sparkly_sessions_controller.rb +16 -9
  11. data/app/helpers/sparkly_accounts_helper.rb +2 -0
  12. data/app/helpers/sparkly_helper.rb +2 -0
  13. data/app/helpers/sparkly_sessions_helper.rb +2 -0
  14. data/app/models/remembrance_token.rb +3 -1
  15. data/app/views/sparkly_accounts/_rails2_form.html.erb +24 -0
  16. data/app/views/sparkly_accounts/_rails3_form.html.erb +26 -0
  17. data/app/views/sparkly_accounts/edit.html.erb +5 -23
  18. data/app/views/sparkly_accounts/new.html.erb +4 -23
  19. data/app/views/sparkly_sessions/_rails2_form.html.erb +22 -0
  20. data/app/views/sparkly_sessions/_rails3_form.html.erb +22 -0
  21. data/app/views/sparkly_sessions/new.html.erb +4 -21
  22. data/features/create_sparkly_account.feature +12 -0
  23. data/features/delete_sparkly_account.feature +12 -0
  24. data/features/edit_sparkly_account.feature +54 -0
  25. data/features/lock_abused_sparkly_account.feature +7 -0
  26. data/features/login_sparkly_session.feature +43 -0
  27. data/features/logout_sparkly_session.feature +16 -0
  28. data/features/setup/sparkly.rb +4 -0
  29. data/features/show_sparkly_account.feature +13 -0
  30. data/features/sparkly_session_timeout.feature +6 -0
  31. data/features/step_definitions/account/account_steps.rb +16 -0
  32. data/features/step_definitions/account/brief_steps.rb +9 -0
  33. data/features/step_definitions/debug_steps.rb +3 -0
  34. data/features/step_definitions/email_steps.rb +182 -0
  35. data/features/step_definitions/session/brief_steps.rb +0 -0
  36. data/features/step_definitions/session/logged_in_steps.rb +42 -0
  37. data/features/step_definitions/session/login_steps.rb +37 -0
  38. data/features/step_definitions/session/logout_steps.rb +5 -0
  39. data/features/step_definitions/session_steps.rb +16 -0
  40. data/features/step_definitions/sparkly_auth_steps.rb +0 -0
  41. data/features/step_definitions/web_steps.rb +287 -0
  42. data/features/support/env.rb +10 -0
  43. data/features/support/paths.rb +35 -0
  44. data/features/support/sparkly_helpers.rb +42 -0
  45. data/generators/sparkly/rails2.rb +79 -0
  46. data/generators/sparkly/rails3.rb +89 -0
  47. data/generators/sparkly/sparkly_generator.rb +4 -75
  48. data/generators/sparkly/templates/accounts_controller.rb +14 -13
  49. data/generators/sparkly/templates/accounts_helper.rb +1 -1
  50. data/generators/sparkly/templates/sessions_controller.rb +26 -12
  51. data/generators/sparkly/templates/sessions_helper.rb +1 -1
  52. data/generators/sparkly/templates/views/sparkly_accounts/_rails2_form.html.erb +24 -0
  53. data/generators/sparkly/templates/views/sparkly_accounts/_rails3_form.html.erb +26 -0
  54. data/generators/sparkly/templates/views/sparkly_accounts/edit.html.erb +5 -23
  55. data/generators/sparkly/templates/views/sparkly_accounts/new.html.erb +4 -23
  56. data/generators/sparkly/templates/views/sparkly_sessions/_rails2_form.html.erb +22 -0
  57. data/generators/sparkly/templates/views/sparkly_sessions/_rails3_form.html.erb +22 -0
  58. data/generators/sparkly/templates/views/sparkly_sessions/new.html.erb +4 -21
  59. data/lib/auth.rb +22 -1
  60. data/lib/auth/behavior/base.rb +25 -18
  61. data/lib/auth/behavior/base/configuration.rb +37 -0
  62. data/lib/auth/behavior/core.rb +22 -14
  63. data/lib/auth/behavior/core/authenticated_model_methods.rb +9 -1
  64. data/lib/auth/behavior/core/controller_extensions.rb +2 -2
  65. data/lib/auth/behavior/core/controller_extensions/class_methods.rb +1 -1
  66. data/lib/auth/behavior/core/password_methods.rb +5 -5
  67. data/lib/auth/behavior/remember_me.rb +7 -3
  68. data/lib/auth/behavior/remember_me/configuration.rb +8 -11
  69. data/lib/auth/behavior/remember_me/controller_extensions.rb +1 -1
  70. data/lib/auth/behavior_lookup.rb +4 -4
  71. data/lib/auth/builtin_behaviors.rb +3 -0
  72. data/lib/auth/configuration.rb +71 -25
  73. data/lib/auth/configuration/keys.rb +50 -0
  74. data/lib/auth/engine.rb +33 -0
  75. data/lib/auth/generators/views_generator.rb +13 -4
  76. data/lib/auth/model.rb +52 -22
  77. data/{init.rb → rails/hacks/rails2.rb} +1 -14
  78. data/rails/hacks/rails3.rb +22 -0
  79. data/rails/init.rb +7 -17
  80. data/rails/init_rails2.rb +39 -0
  81. data/rails/init_rails3.rb +2 -0
  82. data/rails/routes_rails3.rb +37 -0
  83. data/rake3 +1 -0
  84. data/rerun.txt +1 -0
  85. data/run_all_tests +1 -0
  86. data/sparkly-auth.gemspec +481 -23
  87. data/spec/behaviors/core/controller_extensions_spec.rb +49 -0
  88. data/spec/{lib/auth/behavior → behaviors}/core_spec.rb +29 -12
  89. data/spec/behaviors/remember_me/configuration_spec.rb +16 -0
  90. data/spec/behaviors/remember_me_spec.rb +167 -0
  91. data/spec/generators/sanity_checks_spec.rb +58 -0
  92. data/spec/lib/auth/configuration_spec.rb +61 -0
  93. data/spec/lib/auth/model_spec.rb +6 -9
  94. data/spec/lib/auth_spec.rb +2 -2
  95. data/spec/lib/hacks/rename_attributes_spec.rb +49 -0
  96. data/spec/routes_spec.rb +8 -2
  97. data/spec/spec2_helper.rb +52 -0
  98. data/spec/spec3_helper.rb +72 -0
  99. data/spec/spec_helper.rb +109 -49
  100. data/spec_env/rails2/README.1ST +23 -0
  101. data/spec_env/rails2/Rakefile +10 -0
  102. data/spec_env/rails2/app/controllers/application_controller.rb +13 -0
  103. data/spec_env/rails2/app/helpers/application_helper.rb +3 -0
  104. data/spec_env/rails2/app/models/user.rb +2 -0
  105. data/spec_env/rails2/app/views/application/not_found.html.erb +9 -0
  106. data/spec_env/rails2/app/views/layouts/application.html.erb +9 -0
  107. data/spec_env/rails2/config/boot.rb +110 -0
  108. data/spec_env/rails2/config/cucumber.yml +7 -0
  109. data/spec_env/rails2/config/database.yml +25 -0
  110. data/spec_env/rails2/config/environment.rb +46 -0
  111. data/spec_env/rails2/config/environments/cucumber.rb +35 -0
  112. data/spec_env/rails2/config/environments/development.rb +17 -0
  113. data/spec_env/rails2/config/environments/production.rb +28 -0
  114. data/spec_env/rails2/config/environments/test.rb +31 -0
  115. data/spec_env/rails2/config/initializers/backtrace_silencers.rb +7 -0
  116. data/spec_env/rails2/config/initializers/inflections.rb +10 -0
  117. data/spec_env/rails2/config/initializers/mime_types.rb +5 -0
  118. data/spec_env/rails2/config/initializers/new_rails_defaults.rb +21 -0
  119. data/spec_env/rails2/config/initializers/session_store.rb +15 -0
  120. data/spec_env/rails2/config/initializers/sparkly_authentication.rb +30 -0
  121. data/spec_env/rails2/config/locales/en.yml +5 -0
  122. data/spec_env/rails2/config/routes.rb +46 -0
  123. data/spec_env/rails2/db/development.sqlite3 +0 -0
  124. data/spec_env/rails2/db/migrate/001_create_sparkly_passwords.rb +19 -0
  125. data/spec_env/rails2/db/migrate/002_create_sparkly_remembered_tokens.rb +15 -0
  126. data/spec_env/rails2/db/migrate/003_add_confirmed_to_sparkly_passwords.rb +9 -0
  127. data/spec_env/rails2/db/migrate/20100607103543_create_users.rb +12 -0
  128. data/spec_env/rails2/db/migrate/20100609152058_add_email_to_users.rb +9 -0
  129. data/spec_env/rails2/db/schema.rb +42 -0
  130. data/spec_env/rails2/db/seeds.rb +7 -0
  131. data/spec_env/rails2/db/test.sqlite3 +0 -0
  132. data/spec_env/rails2/doc/README_FOR_APP +2 -0
  133. data/spec_env/rails2/doc/sparkly_authentication.txt +56 -0
  134. data/spec_env/rails2/features/support/env.rb +58 -0
  135. data/spec_env/rails2/lib/tasks/cucumber.rake +47 -0
  136. data/spec_env/rails2/lib/tasks/rspec.rake +144 -0
  137. data/spec_env/rails2/lib/tasks/sparkly_migration.rb +1 -0
  138. data/spec_env/rails2/log/cucumber.log +8412 -0
  139. data/spec_env/rails2/log/development.log +317 -0
  140. data/spec_env/rails2/log/test.log +32053 -0
  141. data/spec_env/rails2/public/404.html +30 -0
  142. data/spec_env/rails2/public/422.html +30 -0
  143. data/spec_env/rails2/public/500.html +30 -0
  144. data/spec_env/rails2/public/favicon.ico +0 -0
  145. data/spec_env/rails2/public/images/rails.png +0 -0
  146. data/spec_env/rails2/public/javascripts/application.js +2 -0
  147. data/spec_env/rails2/public/javascripts/controls.js +963 -0
  148. data/spec_env/rails2/public/javascripts/dragdrop.js +973 -0
  149. data/spec_env/rails2/public/javascripts/effects.js +1128 -0
  150. data/spec_env/rails2/public/javascripts/prototype.js +4320 -0
  151. data/spec_env/rails2/public/robots.txt +5 -0
  152. data/spec_env/rails2/rerun.txt +1 -0
  153. data/spec_env/rails2/script/about +4 -0
  154. data/spec_env/rails2/script/autospec +6 -0
  155. data/spec_env/rails2/script/console +3 -0
  156. data/spec_env/rails2/script/cucumber +10 -0
  157. data/spec_env/rails2/script/dbconsole +3 -0
  158. data/spec_env/rails2/script/destroy +3 -0
  159. data/spec_env/rails2/script/generate +3 -0
  160. data/spec_env/rails2/script/performance/benchmarker +3 -0
  161. data/spec_env/rails2/script/performance/profiler +3 -0
  162. data/spec_env/rails2/script/plugin +3 -0
  163. data/spec_env/rails2/script/runner +3 -0
  164. data/spec_env/rails2/script/server +3 -0
  165. data/spec_env/rails2/script/spec +10 -0
  166. data/spec_env/rails2/spec/controllers/sparkly_user_sessions_controller_spec.rb +10 -0
  167. data/spec_env/rails2/spec/rcov.opts +2 -0
  168. data/spec_env/rails2/spec/spec.opts +4 -0
  169. data/spec_env/rails2/spec/spec_helper.rb +54 -0
  170. data/spec_env/rails2/test/fixtures/users.yml +7 -0
  171. data/spec_env/rails2/test/performance/browsing_test.rb +9 -0
  172. data/spec_env/rails2/test/test_helper.rb +38 -0
  173. data/spec_env/rails2/test/unit/user_test.rb +8 -0
  174. data/spec_env/rails2/vendor/gems/sparkly-auth-bootstrap-1.0.0/.specification +63 -0
  175. data/spec_env/rails2/vendor/gems/sparkly-auth-bootstrap-1.0.0/generators/sparkly/sparkly_generator.rb +1 -0
  176. data/spec_env/rails2/vendor/gems/sparkly-auth-bootstrap-1.0.0/lib/sparkly-auth-bootstrap.rb +6 -0
  177. data/spec_env/rails2/vendor/gems/sparkly-auth-bootstrap-1.0.0/rails/init.rb +1 -0
  178. data/spec_env/rails2/vendor/gems/sparkly-auth-bootstrap-1.0.0/sparkly-auth-bootstrap.gemspec +55 -0
  179. data/spec_env/rails3/.gitignore +4 -0
  180. data/spec_env/rails3/Gemfile +43 -0
  181. data/spec_env/rails3/Gemfile.lock +124 -0
  182. data/spec_env/rails3/README +256 -0
  183. data/spec_env/rails3/Rakefile +7 -0
  184. data/spec_env/rails3/app/controllers/application_controller.rb +6 -0
  185. data/spec_env/rails3/app/helpers/application_helper.rb +2 -0
  186. data/spec_env/rails3/app/models/user.rb +3 -0
  187. data/spec_env/rails3/app/views/application/not_found.html.erb +9 -0
  188. data/spec_env/rails3/app/views/layouts/application.html.erb +22 -0
  189. data/spec_env/rails3/config.ru +4 -0
  190. data/spec_env/rails3/config/application.rb +47 -0
  191. data/spec_env/rails3/config/boot.rb +13 -0
  192. data/spec_env/rails3/config/cucumber.yml +8 -0
  193. data/spec_env/rails3/config/database.yml +28 -0
  194. data/spec_env/rails3/config/environment.rb +5 -0
  195. data/spec_env/rails3/config/environments/development.rb +22 -0
  196. data/spec_env/rails3/config/environments/production.rb +49 -0
  197. data/spec_env/rails3/config/environments/spec.rb +35 -0
  198. data/spec_env/rails3/config/environments/test.rb +43 -0
  199. data/spec_env/rails3/config/initializers/backtrace_silencers.rb +7 -0
  200. data/spec_env/rails3/config/initializers/inflections.rb +10 -0
  201. data/spec_env/rails3/config/initializers/mime_types.rb +5 -0
  202. data/spec_env/rails3/config/initializers/secret_token.rb +7 -0
  203. data/spec_env/rails3/config/initializers/session_store.rb +8 -0
  204. data/spec_env/rails3/config/initializers/sparkly_authentication.rb +30 -0
  205. data/spec_env/rails3/config/locales/en.yml +5 -0
  206. data/spec_env/rails3/config/routes.rb +61 -0
  207. data/spec_env/rails3/db/migrate/001_create_sparkly_passwords.rb +19 -0
  208. data/spec_env/rails3/db/migrate/002_create_sparkly_remembered_tokens.rb +15 -0
  209. data/spec_env/rails3/db/migrate/20100810132843_create_users.rb +13 -0
  210. data/spec_env/rails3/db/schema.rb +42 -0
  211. data/spec_env/rails3/db/seeds.rb +7 -0
  212. data/spec_env/rails3/doc/README_FOR_APP +2 -0
  213. data/spec_env/rails3/doc/sparkly_authentication.txt +56 -0
  214. data/spec_env/rails3/features/support/env.rb +62 -0
  215. data/spec_env/rails3/lib/sparkly/bootstrap.rb +1 -0
  216. data/spec_env/rails3/lib/tasks/.gitkeep +0 -0
  217. data/spec_env/rails3/lib/tasks/cucumber.rake +53 -0
  218. data/spec_env/rails3/lib/tasks/sparkly_migration.rb +1 -0
  219. data/spec_env/rails3/public/404.html +26 -0
  220. data/spec_env/rails3/public/422.html +26 -0
  221. data/spec_env/rails3/public/500.html +26 -0
  222. data/spec_env/rails3/public/favicon.ico +0 -0
  223. data/spec_env/rails3/public/images/rails.png +0 -0
  224. data/spec_env/rails3/public/javascripts/application.js +2 -0
  225. data/spec_env/rails3/public/javascripts/controls.js +965 -0
  226. data/spec_env/rails3/public/javascripts/dragdrop.js +974 -0
  227. data/spec_env/rails3/public/javascripts/effects.js +1123 -0
  228. data/spec_env/rails3/public/javascripts/prototype.js +6001 -0
  229. data/spec_env/rails3/public/javascripts/rails.js +175 -0
  230. data/spec_env/rails3/public/robots.txt +5 -0
  231. data/spec_env/rails3/public/stylesheets/.gitkeep +0 -0
  232. data/spec_env/rails3/script/cucumber +10 -0
  233. data/spec_env/rails3/script/rails +6 -0
  234. data/spec_env/rails3/test/fixtures/users.yml +7 -0
  235. data/spec_env/rails3/test/performance/browsing_test.rb +9 -0
  236. data/spec_env/rails3/test/test_helper.rb +13 -0
  237. data/spec_env/rails3/test/unit/user_test.rb +8 -0
  238. data/spec_env/rails3/vendor/plugins/.gitkeep +0 -0
  239. data/spec_env/rails3/webrat.log +5 -0
  240. metadata +393 -15
  241. data/dependencies.rb +0 -1
  242. data/spec/lib/auth/behavior/remember_me_spec.rb +0 -127
  243. data/spec/lib/auth/extensions/controller_spec.rb +0 -32
@@ -1,20 +1,17 @@
1
- class Auth::Behavior::RememberMe::Configuration
1
+ class Auth::Behavior::RememberMe::Configuration < Auth::Behavior::Base::Configuration
2
2
  # Message to be displayed in flash[:error] when a likely theft of the remember token has been detected.
3
+ #
4
+ # Default:
5
+ # "Your account may have been hijacked recently! Verify that all settings are correct."
3
6
  attr_accessor :token_theft_message
4
7
 
5
8
  # How long can a user stay logged in?
9
+ #
10
+ # Default:
11
+ # 6.months
6
12
  attr_accessor :duration
7
13
 
8
- # Provides a handle back to the root configuration object.
9
- attr_reader :configuration
10
-
11
- # Returns true if the root configuration object's behaviors include :remember_me.
12
- def enabled?
13
- configuration.behaviors.include? :remember_me
14
- end
15
-
16
- def initialize(configuration)
17
- @configuration = configuration
14
+ def defaults!
18
15
  @token_theft_message = "Your account may have been hijacked recently! Verify that all settings are correct."
19
16
  @duration = 6.months
20
17
  end
@@ -55,7 +55,7 @@ module Auth::Behavior::RememberMe::ControllerExtensions
55
55
  :authenticate_current_user_with_remembrance, :authenticate_with_remembrance_token,
56
56
  :set_remembrance_token_cookie, :handle_remembrance_token_theft, :logout_with_remembrance!,
57
57
  :logout_without_remembrance!
58
-
58
+
59
59
  unless method_defined?(:login_without_remembrance!)
60
60
  alias_method_chain :login!, :remembrance
61
61
  alias_method_chain :logout!, :remembrance
@@ -1,10 +1,10 @@
1
1
  module Auth::BehaviorLookup
2
2
  def lookup_behavior(behavior)
3
- name = behavior.to_s.underscore
4
- if name[/^auth\/behavior\//]
5
- behavior.to_s.camelize.constantize
3
+ name = behavior.to_s.camelize
4
+ if name[/^Auth::Behavior::/]
5
+ name.constantize
6
6
  else
7
- "auth/behavior/#{name}".camelize.constantize
7
+ "Auth::Behavior::#{name}".constantize
8
8
  end
9
9
  end
10
10
  end
@@ -0,0 +1,3 @@
1
+ # Registers built-in behaviors
2
+
3
+ Auth::Configuration.register_behavior('remember_me', Auth::Behavior::RememberMe)
@@ -1,35 +1,68 @@
1
1
  module Auth
2
2
  class Configuration
3
3
  include Auth::BehaviorLookup
4
+ delegate :configuration_keys, :to => 'self.class'
4
5
 
6
+ # The array of Auth::Model instances which represent the models which will be authenticated.
7
+ # See also #authenticate
8
+ attr_accessor :authenticated_models
9
+
10
+ include Auth::Configuration::Keys
11
+
5
12
  class << self
6
13
  include Auth::BehaviorLookup
7
14
 
15
+ def add_option_delegator_for(key)
16
+ define_method :"#{key}_with_option_delegation=" do |value|
17
+ res = send("#{key}_without_option_delegation=", value)
18
+ authenticated_models.each { |model| model.set_default_option(key, value) }
19
+ res
20
+ end
21
+
22
+ alias_method_chain :"#{key}=", :option_delegation
23
+ end
24
+
25
+ def add_configuration_key_with_delegation(*keys)
26
+ keys = keys.flatten
27
+ eig = class << Auth; self; end
28
+ eig.instance_eval { delegate *[keys, {:to => :configuration}].flatten }
29
+ add_configuration_key_without_delegation(*keys)
30
+ end
31
+
32
+ def attr_accessor_with_delegator(*keys)
33
+ result = attr_accessor_without_delegator(*keys)
34
+ keys.flatten.each { |key| add_option_delegator_for(key) }
35
+ result
36
+ end
37
+
38
+ def attr_writer_with_delegator(*keys)
39
+ result = attr_writer_without_delegator(*keys)
40
+ keys.flatten.each { |key| add_option_delegator_for(key) }
41
+ result
42
+ end
43
+
44
+ alias_method_chain :add_configuration_key, :delegation
45
+ alias_method_chain :attr_writer, :delegator
46
+ alias_method_chain :attr_accessor, :delegator
47
+
8
48
  def behavior_configs
9
49
  @behavior_configs ||= []
50
+ @behavior_configs
10
51
  end
11
52
 
12
- def register_behavior(name)
13
- behavior_class = lookup_behavior(name)
53
+ def register_behavior(name, behavior_class = lookup_behavior(name))
14
54
  # If the behavior has a configuration, add it to self.
15
55
  accessor_name = name
16
56
  name = "#{behavior_class.name}::Configuration"
17
- behavior_configs << [ accessor_name, name.constantize ]
57
+ # we do this so that we can raise NameError now, not later.
58
+ behavior_configs << [ accessor_name, name.constantize.name ]
18
59
  # eg Auth.remember_me.something = 5
19
60
  Auth.class.delegate accessor_name, :to => :configuration
20
61
  rescue NameError
21
62
  # Presumably, the behavior does not have a configuration.
22
63
  end
23
64
  end
24
-
25
- # IS there a better way to do this?? I'm dying to find it...
26
- Dir[File.join(File.dirname(__FILE__), "behavior/*.rb")].each do |fi|
27
- unless fi[/\/base.rb$/]
28
- const_name = fi.gsub(/^#{Regexp::escape File.dirname(__FILE__)}\/behavior\/(.*)\.rb$/, '\1')
29
- register_behavior(const_name)
30
- end
31
- end
32
-
65
+
33
66
  # The message to display when the user creates an account.
34
67
  #
35
68
  # Default:
@@ -60,10 +93,6 @@ module Auth
60
93
  # "Account is locked due to too many invalid attempts."
61
94
  attr_accessor :account_locked_message
62
95
 
63
- # The array of Auth::Model instances which represent the models which will be authenticated.
64
- # See also #authenticate
65
- attr_accessor :authenticated_models
66
-
67
96
  # The NAME of the controller to use as a base controller. All Sparkly controllers will subclass
68
97
  # this, and methods such as current_user will be added to it. Defaults to 'application'.
69
98
  #
@@ -211,6 +240,10 @@ module Auth
211
240
  # "You have been signed out due to inactivity. Please sign in again."
212
241
  attr_accessor :session_timeout_message
213
242
 
243
+ def behavior=(*args, &block) #:nodoc:
244
+ send(:behaviors=, *args, &block)
245
+ end
246
+
214
247
  # Finds the controller with the same name as #base_controller_name and returns it.
215
248
  def base_controller
216
249
  "#{base_controller_name.to_s.camelize}Controller".constantize
@@ -218,6 +251,8 @@ module Auth
218
251
  begin
219
252
  base_controller_name.to_s.camelize.constantize
220
253
  rescue NameError
254
+ # reraise the original error because '_controller' should have been omitted by convention. Also,
255
+ # the backtrace will be more useful.
221
256
  raise err
222
257
  end
223
258
  end
@@ -239,8 +274,14 @@ module Auth
239
274
  @generate_routes
240
275
  end
241
276
 
277
+ # this was documented as an accessor, but is expected to always be an Array.
278
+ def behaviors_with_conversion_to_array=(*args) #:nodoc:
279
+ self.behaviors_without_conversion_to_array = args.flatten
280
+ end
281
+ alias_method_chain :behaviors=, :conversion_to_array
282
+
242
283
  def initialize
243
- @password_format = /(^(?=.*\d)(?=.*[a-zA-Z]).{7,}$)/
284
+ @password_format = /(?=[-_a-zA-Z0-9]*?[A-Z])(?=[-_a-zA-Z0-9]*?[a-z])(?=[-_a-zA-Z0-9]*?[0-9])[-_a-zA-Z0-9]{7,}/
244
285
  @password_format_message = "must contain at least 1 uppercase, 1 lowercase and 1 number"
245
286
  @minimum_password_length = 7
246
287
  @path = File.expand_path(File.join(File.dirname(__FILE__), '..'))
@@ -272,25 +313,30 @@ module Auth
272
313
  @login_after_signup = false
273
314
 
274
315
  self.class.behavior_configs.each do |accessor_name, config_klass|
275
- instance_variable_set("@#{accessor_name}", config_klass.new(self))
316
+ instance_variable_set("@#{accessor_name}", config_klass.constantize.new(self))
276
317
  singleton = (class << self; self; end)
277
318
  singleton.send(:define_method, accessor_name) { instance_variable_get("@#{accessor_name}") }
278
319
  end
279
320
  end
280
321
 
281
322
  def apply!
282
- # Apply behaviors to controllers
283
- behaviors.each do |behavior_name|
284
- behavior = lookup_behavior(behavior_name)
285
- behavior.apply_to_controllers
286
- end
287
-
323
+ # all configurations are now applied through Auth::Model. If no models are being authenticated,
324
+ # then no authentication should be possible -- so what is there to apply?
325
+
288
326
  # Apply options to authenticated models
289
327
  authenticated_models.each do |model|
290
328
  model.apply_options!
291
329
  end
292
330
  end
293
331
 
332
+ def to_hash_with_subconfigs #:nodoc:
333
+ self.class.behavior_configs.inject(to_hash_without_subconfigs) do |hash, (accessor_name, constant_name)|
334
+ hash[accessor_name.to_sym] = send(accessor_name)
335
+ hash
336
+ end
337
+ end
338
+ alias_method_chain :to_hash, :subconfigs
339
+
294
340
  # Accepts a list of model names (or the models themselves) and an optional set of options which
295
341
  # govern how the models will be authenticated.
296
342
  #
@@ -311,7 +357,7 @@ module Auth
311
357
  if model = authenticated_models.find(name)
312
358
  model.merge_options! options
313
359
  else
314
- authenticated_models << Auth::Model.new(name, options)
360
+ authenticated_models << Auth::Model.new(name, options, to_hash)
315
361
  end
316
362
  end
317
363
  end
@@ -0,0 +1,50 @@
1
+ module Auth
2
+ class Configuration
3
+ # When included by a configuration object, the Keys module will override #attr_reader, #attr_writer and
4
+ # #attr_accessor to add configuration keys for each. A #to_hash instance method is generated which will
5
+ # this object into a Hash containing only the registered keys.
6
+ #
7
+ module Keys
8
+ # Returns this configuration as a Hash
9
+ def to_hash
10
+ configuration_keys.inject({}) do |hash, key|
11
+ hash[key] = send(key)
12
+ hash
13
+ end
14
+ end
15
+
16
+ def configuration_keys
17
+ self.class.configuration_keys
18
+ end
19
+
20
+ def self.included(base)
21
+ base.class_eval do
22
+ class << self
23
+ def configuration_keys
24
+ @configuration_keys ||= []
25
+ end
26
+
27
+ def add_configuration_key(*keys)
28
+ configuration_keys.concat keys.flatten
29
+ end
30
+
31
+ def attr_reader(*args) #:nodoc:
32
+ add_configuration_key(*args)
33
+ super
34
+ end
35
+
36
+ def attr_writer(*args) #:nodoc:
37
+ add_configuration_key(*args)
38
+ super
39
+ end
40
+
41
+ def attr_accessor(*args) #:nodoc:
42
+ add_configuration_key(*args)
43
+ super
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,33 @@
1
+ require 'rails'
2
+ require 'sc-core-ext'
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '../auth'))
4
+
5
+ module Auth
6
+ class Engine < Rails::Engine
7
+ paths.lib << File.join(Auth.path)
8
+ paths.app.controllers << File.join(Auth.path, "../app/controllers")
9
+ paths.app.helpers << File.join(Auth.path, '../app/helpers')
10
+ paths.app.models << File.join(Auth.path, "../app/models")
11
+ paths.app.views << File.join(Auth.path, "../app/views")
12
+ paths.config.routes << File.join(Auth.path, "../rails/routes_rails3.rb")
13
+
14
+ config.autoload_paths << Auth.path
15
+ config.autoload_once_paths << Auth.path
16
+
17
+ generators do
18
+ require File.join(File.dirname(__FILE__), '../../generators/sparkly/sparkly_generator')
19
+ end
20
+
21
+ rake_tasks do
22
+ load File.join(File.dirname(__FILE__), 'tasks/migrations.rb')
23
+ end
24
+
25
+ config.before_initialize do
26
+ require_dependency File.join(File.dirname(__FILE__), "builtin_behaviors")
27
+ end
28
+
29
+ config.to_prepare do
30
+ Auth.kick! unless Auth.defer_kickstart?
31
+ end
32
+ end
33
+ end
@@ -12,11 +12,20 @@ class Auth::Generators::ViewsGenerator < Rails::Generator::NamedBase
12
12
  m.directory resource_directory = File.join("app/views", model.accounts_controller.underscore)
13
13
  m.directory sessions_directory = File.join("app/views", model.sessions_controller.underscore)
14
14
 
15
- %w(edit new show).each do |f|
16
- m.file "views/sparkly_accounts/#{f}.html.erb", File.join(resource_directory, "#{f}.html.erb")
17
- end
15
+ resource_directory = File.join("app/views", model.accounts_controller.underscore)
16
+ sessions_directory = File.join("app/views", model.sessions_controller.underscore)
18
17
 
19
- m.file "views/sparkly_sessions/new.html.erb", File.join(sessions_directory, "new.html.erb")
18
+ base = File.join(source_root, "views/sparkly_accounts")
19
+ Dir[File.join(base, "**/*")].each do |fi|
20
+ fi.gsub!(/^#{Regexp::escape base}/, '')
21
+ m.file(File.join("views/sparkly_accounts", fi), File.join(resource_directory, fi))
22
+ end
23
+
24
+ base = File.join(source_root, "views/sparkly_sessions")
25
+ Dir[File.join(base, "**/*")].each do |fi|
26
+ fi.gsub!(/^#{Regexp::escape base}/, '')
27
+ m.file(File.join("views/sparkly_sessions", fi), File.join(sessions_directory, fi))
28
+ end
20
29
  end
21
30
  end
22
31
 
data/lib/auth/model.rb CHANGED
@@ -1,25 +1,46 @@
1
1
  class Auth::Model
2
2
  module Authenticated
3
3
  def self.included(base)
4
- base.send(:cattr_accessor, :sparkly_config)
4
+ base.instance_eval do
5
+ cattr_accessor :sparkly_config
6
+ alias auth_config sparkly_config
7
+ end
5
8
  end
6
9
  end
7
10
 
8
-
9
11
  def self.option(name, default = name)
10
12
  define_method(name) do
11
- self.options[name] ||= Auth.configuration.send(default)
13
+ self.options[name] ||= send(default)
14
+ end
15
+ end
16
+
17
+ # check missing methods to see if they're looking for configuration options
18
+ def method_missing(name, *args, &block) #:nodoc:
19
+ option_name, assignment = (name.to_s.gsub(/\=$/, '')), $~ # lose the equals sign, and remember if it existed
20
+
21
+ if (_options = options).keys.select { |key| key.to_s == option_name }.empty?
22
+ super
23
+ else
24
+ if assignment
25
+ _options[option_name.to_sym] = args.flatten
26
+ else
27
+ _options[option_name.to_sym]
28
+ end
12
29
  end
13
30
  end
14
31
 
15
32
  include Auth::BehaviorLookup
16
- attr_reader :options
17
- option :behaviors
18
- option :password_update_frequency
33
+ # attr_reader :options
34
+ # option :behaviors
35
+ # option :password_update_frequency
19
36
  option :accounts_controller, :default_accounts_controller_name
20
37
  option :sessions_controller, :default_sessions_controller_name
21
38
  delegate :name, :table_name, :to => :target
22
39
 
40
+ def options
41
+ @options.reverse_merge(default_options)
42
+ end
43
+
23
44
  # Options include:
24
45
  # :behaviors => an array of behaviors to override Auth.configuration.behaviors
25
46
  # :password_update_frequency => a time (ie 30.days) to override Auth.configuration.password_update_frequency
@@ -29,7 +50,10 @@ class Auth::Model
29
50
  # :accounts_controller => the name of the controller to route to for creating accounts, deleting them, etc.
30
51
  # :sessions_controller => the name of the controller to route to for logging in, logging out, etc.
31
52
  #
32
- def initialize(name_or_constant, options = {})
53
+ def initialize(name_or_constant, options = {}, default_options = {})
54
+ @options = (options || {}).dup
55
+ send(:default_options).merge! default_options
56
+
33
57
  begin
34
58
  @target = resolve(name_or_constant).name
35
59
  rescue NameError
@@ -37,17 +61,15 @@ class Auth::Model
37
61
  # to do it now.
38
62
  @target = name_or_constant.to_s.camelize
39
63
  end
40
-
41
- @options = options.reverse_merge(default_options)
42
64
  end
43
65
 
44
66
  def target
45
- returning @target.constantize do |klass|
46
- unless klass.include?(Auth::Model::Authenticated)
47
- klass.send(:include, Auth::Model::Authenticated)
48
- klass.sparkly_config = self
49
- end
67
+ klass = @target.constantize
68
+ unless klass.include?(Auth::Model::Authenticated)
69
+ klass.send(:include, Auth::Model::Authenticated)
70
+ klass.sparkly_config = self
50
71
  end
72
+ klass
51
73
  end
52
74
 
53
75
  # Returns true if the specified String, Symbol or constant resolves to the same constant affected by this Model.
@@ -62,13 +84,28 @@ class Auth::Model
62
84
 
63
85
  # Merges the specified hash of options with this Model's hash of options. Same as model.options.merge!(options)
64
86
  def merge_options!(options)
65
- self.options.merge! options
87
+ @options.merge! options
66
88
  end
67
89
 
68
90
  def apply_options!
69
91
  apply_behaviors!
70
92
  end
71
93
 
94
+ def default_options
95
+ @default_options ||= {
96
+ :key => :email,
97
+ :with => :password
98
+ }.merge(Auth.configuration.to_hash)
99
+ end
100
+
101
+ def default_options=(hash)
102
+ default_options.merge!(hash)
103
+ end
104
+
105
+ def set_default_option(key, value)
106
+ default_options[key] = value
107
+ end
108
+
72
109
  private
73
110
  def apply_behaviors!
74
111
  behaviors.each do |behavior|
@@ -84,11 +121,4 @@ class Auth::Model
84
121
  else name_or_constant
85
122
  end
86
123
  end
87
-
88
- def default_options
89
- {
90
- :key => :email,
91
- :with => :password
92
- }
93
- end
94
124
  end