sorcery 0.6.1 → 0.7.1

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 (185) hide show
  1. data/Gemfile +1 -0
  2. data/Gemfile.lock +52 -45
  3. data/README.rdoc +26 -54
  4. data/Rakefile +26 -0
  5. data/VERSION +1 -1
  6. data/lib/generators/sorcery/USAGE +22 -0
  7. data/lib/generators/sorcery/install_generator.rb +71 -0
  8. data/lib/{sorcery/initializers → generators/sorcery/templates}/initializer.rb +82 -61
  9. data/lib/generators/sorcery/templates/migration/activity_logging.rb +17 -0
  10. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +11 -0
  11. data/lib/generators/{sorcery_migration/templates → sorcery/templates/migration}/core.rb +3 -3
  12. data/lib/generators/{sorcery_migration/templates → sorcery/templates/migration}/external.rb +1 -1
  13. data/lib/generators/sorcery/templates/migration/remember_me.rb +15 -0
  14. data/lib/generators/sorcery/templates/migration/reset_password.rb +17 -0
  15. data/lib/generators/sorcery/templates/migration/user_activation.rb +17 -0
  16. data/lib/sorcery/controller/submodules/activity_logging.rb +23 -9
  17. data/lib/sorcery/controller/submodules/brute_force_protection.rb +2 -1
  18. data/lib/sorcery/controller/submodules/external/protocols/certs/ca-bundle.crt +5182 -0
  19. data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +27 -8
  20. data/lib/sorcery/controller/submodules/external/providers/github.rb +80 -0
  21. data/lib/sorcery/controller/submodules/external/providers/twitter.rb +5 -0
  22. data/lib/sorcery/controller/submodules/external.rb +10 -3
  23. data/lib/sorcery/controller/submodules/http_basic_auth.rb +1 -1
  24. data/lib/sorcery/controller/submodules/remember_me.rb +15 -5
  25. data/lib/sorcery/controller/submodules/session_timeout.rb +1 -1
  26. data/lib/sorcery/controller.rb +59 -38
  27. data/lib/sorcery/crypto_providers/aes256.rb +7 -3
  28. data/lib/sorcery/engine.rb +1 -0
  29. data/lib/sorcery/model/adapters/active_record.rb +2 -1
  30. data/lib/sorcery/model/adapters/mongo_mapper.rb +49 -0
  31. data/lib/sorcery/model/adapters/mongoid.rb +7 -2
  32. data/lib/sorcery/model/submodules/brute_force_protection.rb +13 -3
  33. data/lib/sorcery/model/submodules/remember_me.rb +9 -2
  34. data/lib/sorcery/model/submodules/reset_password.rb +11 -2
  35. data/lib/sorcery/model/submodules/user_activation.rb +13 -2
  36. data/lib/sorcery/model/temporary_token.rb +5 -0
  37. data/lib/sorcery/model.rb +34 -15
  38. data/lib/sorcery/test_helpers/internal/rails.rb +1 -1
  39. data/lib/sorcery/test_helpers/rails.rb +2 -2
  40. data/lib/sorcery.rb +6 -7
  41. data/sorcery.gemspec +86 -203
  42. data/spec/Gemfile.lock +23 -12
  43. data/spec/README.md +31 -0
  44. data/spec/rails3/Gemfile +3 -1
  45. data/spec/rails3/Gemfile.lock +45 -28
  46. data/spec/rails3/app/controllers/application_controller.rb +40 -22
  47. data/spec/rails3/app/views/application/index.html.erb +17 -0
  48. data/spec/rails3/spec/controller_activity_logging_spec.rb +23 -0
  49. data/spec/rails3/spec/controller_oauth2_spec.rb +59 -16
  50. data/spec/rails3/spec/controller_remember_me_spec.rb +37 -6
  51. data/spec/rails3/spec/controller_spec.rb +30 -0
  52. data/spec/rails3/spec/integration_spec.rb +23 -0
  53. data/spec/rails3/spec/spec_helper.rb +6 -5
  54. data/spec/rails3_mongo_mapper/.gitignore +4 -0
  55. data/spec/rails3_mongo_mapper/.rspec +1 -0
  56. data/spec/{sinatra_modular → rails3_mongo_mapper}/Gemfile +5 -5
  57. data/spec/rails3_mongo_mapper/Gemfile.lock +159 -0
  58. data/spec/{sinatra → rails3_mongo_mapper}/Rakefile +3 -3
  59. data/spec/rails3_mongo_mapper/app/controllers/application_controller.rb +108 -0
  60. data/spec/rails3_mongo_mapper/app/helpers/application_helper.rb +2 -0
  61. data/spec/rails3_mongo_mapper/app/models/authentication.rb +6 -0
  62. data/spec/rails3_mongo_mapper/app/models/user.rb +5 -0
  63. data/spec/rails3_mongo_mapper/app/views/layouts/application.html.erb +14 -0
  64. data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_email.html.erb +17 -0
  65. data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_email.text.erb +9 -0
  66. data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_success_email.html.erb +17 -0
  67. data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/activation_success_email.text.erb +9 -0
  68. data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/reset_password_email.html.erb +16 -0
  69. data/spec/rails3_mongo_mapper/app/views/sorcery_mailer/reset_password_email.text.erb +8 -0
  70. data/spec/rails3_mongo_mapper/config/application.rb +51 -0
  71. data/spec/rails3_mongo_mapper/config/boot.rb +13 -0
  72. data/spec/rails3_mongo_mapper/config/environment.rb +5 -0
  73. data/spec/rails3_mongo_mapper/config/environments/development.rb +30 -0
  74. data/spec/rails3_mongo_mapper/config/environments/in_memory.rb +0 -0
  75. data/spec/rails3_mongo_mapper/config/environments/production.rb +49 -0
  76. data/spec/rails3_mongo_mapper/config/environments/test.rb +35 -0
  77. data/spec/rails3_mongo_mapper/config/initializers/backtrace_silencers.rb +7 -0
  78. data/spec/rails3_mongo_mapper/config/initializers/inflections.rb +10 -0
  79. data/spec/rails3_mongo_mapper/config/initializers/mime_types.rb +5 -0
  80. data/spec/rails3_mongo_mapper/config/initializers/mongo.rb +2 -0
  81. data/spec/rails3_mongo_mapper/config/initializers/secret_token.rb +7 -0
  82. data/spec/rails3_mongo_mapper/config/initializers/session_store.rb +8 -0
  83. data/spec/rails3_mongo_mapper/config/locales/en.yml +5 -0
  84. data/spec/rails3_mongo_mapper/config/routes.rb +59 -0
  85. data/spec/rails3_mongo_mapper/config.ru +4 -0
  86. data/spec/rails3_mongo_mapper/db/schema.rb +23 -0
  87. data/spec/rails3_mongo_mapper/db/seeds.rb +7 -0
  88. data/spec/rails3_mongo_mapper/lib/tasks/.gitkeep +0 -0
  89. data/spec/rails3_mongo_mapper/public/404.html +26 -0
  90. data/spec/rails3_mongo_mapper/public/422.html +26 -0
  91. data/spec/rails3_mongo_mapper/public/500.html +26 -0
  92. data/spec/rails3_mongo_mapper/public/favicon.ico +0 -0
  93. data/spec/rails3_mongo_mapper/public/images/rails.png +0 -0
  94. data/spec/rails3_mongo_mapper/public/javascripts/application.js +2 -0
  95. data/spec/rails3_mongo_mapper/public/javascripts/controls.js +965 -0
  96. data/spec/rails3_mongo_mapper/public/javascripts/dragdrop.js +974 -0
  97. data/spec/rails3_mongo_mapper/public/javascripts/effects.js +1123 -0
  98. data/spec/rails3_mongo_mapper/public/javascripts/prototype.js +6001 -0
  99. data/spec/rails3_mongo_mapper/public/javascripts/rails.js +175 -0
  100. data/spec/rails3_mongo_mapper/public/robots.txt +5 -0
  101. data/spec/rails3_mongo_mapper/public/stylesheets/.gitkeep +0 -0
  102. data/spec/rails3_mongo_mapper/script/rails +6 -0
  103. data/spec/{sinatra → rails3_mongo_mapper}/spec/controller_spec.rb +51 -41
  104. data/spec/rails3_mongo_mapper/spec/spec_helper.orig.rb +27 -0
  105. data/spec/rails3_mongo_mapper/spec/spec_helper.rb +55 -0
  106. data/spec/rails3_mongo_mapper/spec/user_activation_spec.rb +9 -0
  107. data/spec/rails3_mongo_mapper/spec/user_activity_logging_spec.rb +8 -0
  108. data/spec/rails3_mongo_mapper/spec/user_brute_force_protection_spec.rb +8 -0
  109. data/spec/rails3_mongo_mapper/spec/user_oauth_spec.rb +8 -0
  110. data/spec/rails3_mongo_mapper/spec/user_remember_me_spec.rb +8 -0
  111. data/spec/rails3_mongo_mapper/spec/user_reset_password_spec.rb +8 -0
  112. data/spec/rails3_mongo_mapper/spec/user_spec.rb +37 -0
  113. data/spec/rails3_mongo_mapper/vendor/plugins/.gitkeep +0 -0
  114. data/spec/rails3_mongoid/Gemfile +1 -1
  115. data/spec/rails3_mongoid/Gemfile.lock +41 -34
  116. data/spec/rails3_mongoid/spec/controller_activity_logging_spec.rb +98 -0
  117. data/spec/rails3_mongoid/spec/controller_spec.rb +130 -0
  118. data/spec/rails3_mongoid/spec/user_spec.rb +1 -0
  119. data/spec/shared_examples/user_remember_me_shared_examples.rb +1 -0
  120. data/spec/shared_examples/user_shared_examples.rb +36 -8
  121. metadata +128 -234
  122. data/lib/generators/sorcery_migration/sorcery_migration_generator.rb +0 -24
  123. data/lib/generators/sorcery_migration/templates/activity_logging.rb +0 -17
  124. data/lib/generators/sorcery_migration/templates/brute_force_protection.rb +0 -11
  125. data/lib/generators/sorcery_migration/templates/remember_me.rb +0 -15
  126. data/lib/generators/sorcery_migration/templates/reset_password.rb +0 -13
  127. data/lib/generators/sorcery_migration/templates/user_activation.rb +0 -17
  128. data/lib/sorcery/controller/adapters/sinatra.rb +0 -104
  129. data/lib/sorcery/sinatra.rb +0 -4
  130. data/lib/sorcery/test_helpers/internal/sinatra.rb +0 -74
  131. data/lib/sorcery/test_helpers/internal/sinatra_modular.rb +0 -74
  132. data/lib/sorcery/test_helpers/sinatra.rb +0 -88
  133. data/spec/rails3/Rakefile.unused +0 -7
  134. data/spec/rails3/public/index.html +0 -239
  135. data/spec/sinatra/Gemfile +0 -15
  136. data/spec/sinatra/Gemfile.lock +0 -117
  137. data/spec/sinatra/authentication.rb +0 -3
  138. data/spec/sinatra/db/migrate/activation/20101224223622_add_activation_to_users.rb +0 -17
  139. data/spec/sinatra/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +0 -17
  140. data/spec/sinatra/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +0 -11
  141. data/spec/sinatra/db/migrate/core/20101224223620_create_users.rb +0 -16
  142. data/spec/sinatra/db/migrate/external/20101224223628_create_authentications.rb +0 -14
  143. data/spec/sinatra/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +0 -15
  144. data/spec/sinatra/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +0 -13
  145. data/spec/sinatra/filters.rb +0 -27
  146. data/spec/sinatra/modular.rb +0 -157
  147. data/spec/sinatra/myapp.rb +0 -133
  148. data/spec/sinatra/spec/controller_activity_logging_spec.rb +0 -85
  149. data/spec/sinatra/spec/controller_brute_force_protection_spec.rb +0 -70
  150. data/spec/sinatra/spec/controller_http_basic_auth_spec.rb +0 -53
  151. data/spec/sinatra/spec/controller_oauth2_spec.rb +0 -99
  152. data/spec/sinatra/spec/controller_oauth_spec.rb +0 -100
  153. data/spec/sinatra/spec/controller_remember_me_spec.rb +0 -64
  154. data/spec/sinatra/spec/controller_session_timeout_spec.rb +0 -57
  155. data/spec/sinatra/spec/spec_helper.rb +0 -45
  156. data/spec/sinatra/user.rb +0 -6
  157. data/spec/sinatra/views/test_login.erb +0 -4
  158. data/spec/sinatra_modular/Gemfile.lock +0 -117
  159. data/spec/sinatra_modular/Rakefile +0 -11
  160. data/spec/sinatra_modular/authentication.rb +0 -3
  161. data/spec/sinatra_modular/db/migrate/activation/20101224223622_add_activation_to_users.rb +0 -17
  162. data/spec/sinatra_modular/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +0 -17
  163. data/spec/sinatra_modular/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +0 -11
  164. data/spec/sinatra_modular/db/migrate/core/20101224223620_create_users.rb +0 -16
  165. data/spec/sinatra_modular/db/migrate/external/20101224223628_create_authentications.rb +0 -14
  166. data/spec/sinatra_modular/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +0 -15
  167. data/spec/sinatra_modular/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +0 -13
  168. data/spec/sinatra_modular/filters.rb +0 -27
  169. data/spec/sinatra_modular/modular.rb +0 -157
  170. data/spec/sinatra_modular/myapp.rb +0 -133
  171. data/spec/sinatra_modular/sorcery_mailer.rb +0 -25
  172. data/spec/sinatra_modular/spec_modular/controller_activity_logging_spec.rb +0 -85
  173. data/spec/sinatra_modular/spec_modular/controller_brute_force_protection_spec.rb +0 -70
  174. data/spec/sinatra_modular/spec_modular/controller_http_basic_auth_spec.rb +0 -53
  175. data/spec/sinatra_modular/spec_modular/controller_oauth2_spec.rb +0 -99
  176. data/spec/sinatra_modular/spec_modular/controller_oauth_spec.rb +0 -100
  177. data/spec/sinatra_modular/spec_modular/controller_remember_me_spec.rb +0 -64
  178. data/spec/sinatra_modular/spec_modular/controller_session_timeout_spec.rb +0 -57
  179. data/spec/sinatra_modular/spec_modular/controller_spec.rb +0 -116
  180. data/spec/sinatra_modular/spec_modular/spec.opts +0 -2
  181. data/spec/sinatra_modular/spec_modular/spec_helper.rb +0 -51
  182. data/spec/sinatra_modular/user.rb +0 -6
  183. data/spec/sinatra_modular/views/test_login.erb +0 -4
  184. /data/spec/{sinatra → rails3_mongo_mapper/app/mailers}/sorcery_mailer.rb +0 -0
  185. /data/spec/{sinatra → rails3_mongo_mapper}/spec/spec.opts +0 -0
@@ -8,19 +8,38 @@ module Sorcery
8
8
  def oauth_version
9
9
  "2.0"
10
10
  end
11
-
12
- def authorize_url(*args)
13
- client = ::OAuth2::Client.new(@key, @secret, :site => @site)
14
- client.web_server.authorize_url(:redirect_uri => @callback_url, :scope => @scope)
11
+
12
+ def authorize_url(options = {})
13
+ defaults = {
14
+ :site => @site,
15
+ :ssl => { :ca_file => Config.ca_file }
16
+ }
17
+ client = ::OAuth2::Client.new(
18
+ @key,
19
+ @secret,
20
+ defaults.merge!(options)
21
+ )
22
+ client.web_server.authorize_url(
23
+ :redirect_uri => @callback_url,
24
+ :scope => @scope
25
+ )
15
26
  end
16
-
27
+
17
28
  def get_access_token(args)
18
- client = ::OAuth2::Client.new(@key, @secret, :site => @site)
19
- client.web_server.get_access_token(args[:code], :redirect_uri => @callback_url)
29
+ client = ::OAuth2::Client.new(
30
+ @key,
31
+ @secret,
32
+ :site => @site,
33
+ :ssl => { :ca_file => Config.ca_file }
34
+ )
35
+ client.web_server.get_access_token(
36
+ args[:code],
37
+ :redirect_uri => @callback_url
38
+ )
20
39
  end
21
40
  end
22
41
  end
23
42
  end
24
43
  end
25
44
  end
26
- end
45
+ end
@@ -0,0 +1,80 @@
1
+ module Sorcery
2
+ module Controller
3
+ module Submodules
4
+ module External
5
+ module Providers
6
+ # This module adds support for OAuth with github.com.
7
+ # When included in the 'config.providers' option, it adds a new option, 'config.github'.
8
+ # Via this new option you can configure Github specific settings like your app's key and secret.
9
+ #
10
+ # config.github.key = <key>
11
+ # config.github.secret = <secret>
12
+ # ...
13
+ #
14
+ module Github
15
+ def self.included(base)
16
+ base.module_eval do
17
+ class << self
18
+ attr_reader :github # access to github_client.
19
+
20
+ def merge_github_defaults!
21
+ @defaults.merge!(:@github => GithubClient)
22
+ end
23
+ end
24
+ merge_github_defaults!
25
+ update!
26
+ end
27
+ end
28
+
29
+ module GithubClient
30
+ class << self
31
+ attr_accessor :key,
32
+ :secret,
33
+ :callback_url,
34
+ :site,
35
+ :user_info_path,
36
+ :user_info_mapping
37
+
38
+ include Protocols::Oauth2
39
+
40
+ def init
41
+ @site = "https://github.com/"
42
+ @user_info_path = "/api/v2/json/user/show"
43
+ @user_info_mapping = {}
44
+ end
45
+
46
+ def get_user_hash
47
+ user_hash = {}
48
+ response = @access_token.get(@user_info_path)
49
+ user_hash[:user_info] = JSON.parse(response)
50
+ user_hash[:uid] = user_hash[:user_info]['id']
51
+ user_hash
52
+ end
53
+
54
+ def has_callback?
55
+ true
56
+ end
57
+
58
+ # calculates and returns the url to which the user should be redirected,
59
+ # to get authenticated at the external provider's site.
60
+ def login_url(params,session)
61
+ self.authorize_url({:authorize_path => '/login/oauth/authorize'})
62
+ end
63
+
64
+ # tries to login the user from access token
65
+ def process_callback(params,session)
66
+ args = {}
67
+ args.merge!({:code => params[:code]}) if params[:code]
68
+ @access_token = self.get_access_token(args)
69
+ end
70
+
71
+ end
72
+ init
73
+ end
74
+
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -39,6 +39,11 @@ module Sorcery
39
39
  :user_info_mapping
40
40
 
41
41
  include Protocols::Oauth1
42
+
43
+ # Override included get_consumer method to provide authorize_path
44
+ def get_consumer
45
+ ::OAuth::Consumer.new(@key, @secret, :site => @site, :authorize_path => "/oauth/authenticate")
46
+ end
42
47
 
43
48
  def init
44
49
  @site = "https://api.twitter.com"
@@ -9,9 +9,11 @@ module Sorcery
9
9
  Config.module_eval do
10
10
  class << self
11
11
  attr_reader :external_providers # external providers like twitter.
12
+ attr_accessor :ca_file # path to ca_file. By default use a internal ca-bundle.crt.
12
13
 
13
14
  def merge_external_defaults!
14
- @defaults.merge!(:@external_providers => [])
15
+ @defaults.merge!(:@external_providers => [],
16
+ :@ca_file => File.join(File.expand_path(File.dirname(__FILE__)), 'external/protocols/certs/ca-bundle.crt'))
15
17
  end
16
18
 
17
19
  def external_providers=(providers)
@@ -45,7 +47,7 @@ module Sorcery
45
47
  @user_hash = @provider.get_user_hash
46
48
  if user = user_class.load_from_provider(provider,@user_hash[:uid])
47
49
  reset_session
48
- login_user(user)
50
+ auto_login(user)
49
51
  user
50
52
  end
51
53
  end
@@ -61,6 +63,7 @@ module Sorcery
61
63
  # {:username => "user/name"}
62
64
  #
63
65
  # And this will cause 'moishe' to be set as the value of :username field.
66
+ # Note: Be careful. This method skips validations model.
64
67
  def create_from(provider)
65
68
  provider = provider.to_sym
66
69
  @provider = Config.send(provider)
@@ -76,7 +79,11 @@ module Sorcery
76
79
  end
77
80
  end
78
81
  user_class.transaction do
79
- @user = user_class.create!(attrs)
82
+ @user = user_class.new()
83
+ attrs.each do |k,v|
84
+ @user.send(:"#{k}=", v)
85
+ end
86
+ @user.save(:validate => false)
80
87
  user_class.sorcery_config.authentications_class.create!({config.authentications_user_id_attribute_name => @user.id, config.provider_attribute_name => provider, config.provider_uid_attribute_name => @user_hash[:uid]})
81
88
  end
82
89
  @user
@@ -46,7 +46,7 @@ module Sorcery
46
46
  def login_from_basic_auth
47
47
  authenticate_with_http_basic do |username, password|
48
48
  @current_user = (user_class.authenticate(username, password) if session[:http_authentication_used]) || false
49
- login_user(@current_user) if @current_user
49
+ auto_login(@current_user) if @current_user
50
50
  @current_user
51
51
  end
52
52
  end
@@ -22,23 +22,31 @@ module Sorcery
22
22
 
23
23
  # Clears the cookie and clears the token from the db.
24
24
  def forget_me!
25
- current_user.forget_me!
25
+ @current_user.forget_me!
26
26
  cookies[:remember_me_token] = nil
27
27
  end
28
28
 
29
+ # Override.
30
+ # logins a user instance, and optionally remembers him.
31
+ def auto_login(user, should_remember = false)
32
+ session[:user_id] = user.id
33
+ @current_user = user
34
+ remember_me! if should_remember
35
+ end
36
+
29
37
  protected
30
38
 
31
39
  # calls remember_me! if a third credential was passed to the login method.
32
40
  # Runs as a hook after login.
33
41
  def remember_me_if_asked_to(user, credentials)
34
- remember_me! if credentials.size == 3 && credentials[2]
42
+ remember_me! if ( credentials.size == 3 && credentials[2] && credentials[2] != "0" )
35
43
  end
36
44
 
37
45
  # Checks the cookie for a remember me token, tried to find a user with that token
38
46
  # and logs the user in if found.
39
47
  # Runs as a login source. See 'current_user' method for how it is used.
40
48
  def login_from_cookie
41
- user = cookies[:remember_me_token] && user_class.find_by_remember_me_token(cookies[:remember_me_token])
49
+ user = cookies.signed[:remember_me_token] && user_class.find_by_remember_me_token(cookies.signed[:remember_me_token])
42
50
  if user && user.remember_me_token?
43
51
  set_remember_me_cookie!(user)
44
52
  @current_user = user
@@ -48,9 +56,11 @@ module Sorcery
48
56
  end
49
57
 
50
58
  def set_remember_me_cookie!(user)
51
- cookies[:remember_me_token] = {
59
+ cookies.signed[:remember_me_token] = {
52
60
  :value => user.send(user.sorcery_config.remember_me_token_attribute_name),
53
- :expires => user.send(user.sorcery_config.remember_me_token_expires_at_attribute_name)
61
+ :expires => user.send(user.sorcery_config.remember_me_token_expires_at_attribute_name),
62
+ :httponly => true,
63
+ :domain => Config.cookie_domain
54
64
  }
55
65
  end
56
66
  end
@@ -39,7 +39,7 @@ module Sorcery
39
39
  session_to_use = Config.session_timeout_from_last_action ? session[:last_action_time] : session[:login_time]
40
40
  if session_to_use && (Time.now.utc - session_to_use > Config.session_timeout)
41
41
  reset_session
42
- @current_user = false
42
+ @current_user = nil
43
43
  else
44
44
  session[:last_action_time] = Time.now.utc
45
45
  end
@@ -5,7 +5,7 @@ module Sorcery
5
5
  include InstanceMethods
6
6
  Config.submodules.each do |mod|
7
7
  begin
8
- include Submodules.const_get(mod.to_s.split("_").map {|p| p.capitalize}.join(""))
8
+ include Submodules.const_get(mod.to_s.split("_").map {|p| p.capitalize}.join(""))
9
9
  rescue NameError
10
10
  # don't stop on a missing submodule.
11
11
  end
@@ -14,7 +14,7 @@ module Sorcery
14
14
  Config.update!
15
15
  Config.configure!
16
16
  end
17
-
17
+
18
18
  module InstanceMethods
19
19
  # To be used as before_filter.
20
20
  # Will trigger auto-login attempts via the call to logged_in?
@@ -22,10 +22,10 @@ module Sorcery
22
22
  def require_login
23
23
  if !logged_in?
24
24
  session[:return_to_url] = request.url if Config.save_return_to_url
25
- self.send(Config.not_authenticated_action)
25
+ self.send(Config.not_authenticated_action)
26
26
  end
27
27
  end
28
-
28
+
29
29
  # Takes credentials and returns a user on successful authentication.
30
30
  # Runs hooks after login or failed login.
31
31
  def login(*credentials)
@@ -34,7 +34,7 @@ module Sorcery
34
34
  return_to_url = session[:return_to_url]
35
35
  reset_session # protect from session fixation attacks
36
36
  session[:return_to_url] = return_to_url
37
- login_user(user)
37
+ auto_login(user)
38
38
  after_login!(user, credentials)
39
39
  current_user
40
40
  else
@@ -42,41 +42,62 @@ module Sorcery
42
42
  nil
43
43
  end
44
44
  end
45
-
45
+
46
46
  # Resets the session and runs hooks before and after.
47
47
  def logout
48
48
  if logged_in?
49
49
  before_logout!(current_user)
50
50
  reset_session
51
51
  after_logout!
52
+ @current_user = nil
52
53
  end
53
54
  end
54
-
55
+
55
56
  def logged_in?
56
57
  !!current_user
57
58
  end
58
-
59
+
59
60
  # attempts to auto-login from the sources defined (session, basic_auth, cookie, etc.)
60
61
  # returns the logged in user if found, false if not (using old restful-authentication trick, nil != false).
61
62
  def current_user
62
63
  @current_user ||= login_from_session || login_from_other_sources unless @current_user == false
63
64
  end
64
-
65
- # used when a user tries to access a page while logged out, is asked to login,
65
+
66
+ def current_user=(user)
67
+ @current_user = user
68
+ end
69
+
70
+ # used when a user tries to access a page while logged out, is asked to login,
66
71
  # and we want to return him back to the page he originally wanted.
67
72
  def redirect_back_or_to(url, flash_hash = {})
68
73
  redirect_to(session[:return_to_url] || url, :flash => flash_hash)
69
74
  end
70
-
75
+
71
76
  # The default action for denying non-authenticated users.
72
77
  # You can override this method in your controllers,
73
78
  # or provide a different method in the configuration.
74
79
  def not_authenticated
75
80
  redirect_to root_path
76
81
  end
77
-
82
+
83
+ # login a user instance
84
+ #
85
+ # @param [<User-Model>] user the user instance.
86
+ # @return - do not depend on the return value.
87
+ def auto_login(user)
88
+ session[:user_id] = user.id
89
+ @current_user = user
90
+ end
91
+
92
+ # Overwrite Rails' handle unverified request
93
+ def handle_unverified_request
94
+ cookies[:remember_me_token] = nil
95
+ @current_user = nil
96
+ super # call the default behaviour which resets the session
97
+ end
98
+
78
99
  protected
79
-
100
+
80
101
  # Tries all available sources (methods) until one doesn't return false.
81
102
  def login_from_other_sources
82
103
  result = nil
@@ -85,52 +106,51 @@ module Sorcery
85
106
  end
86
107
  result || false
87
108
  end
88
-
89
- def login_user(user)
90
- session[:user_id] = user.id
91
- end
92
-
109
+
93
110
  def login_from_session
94
111
  @current_user = (user_class.find_by_id(session[:user_id]) if session[:user_id]) || false
95
112
  end
96
-
113
+
97
114
  def after_login!(user, credentials)
98
115
  Config.after_login.each {|c| self.send(c, user, credentials)}
99
116
  end
100
-
117
+
101
118
  def after_failed_login!(credentials)
102
119
  Config.after_failed_login.each {|c| self.send(c, credentials)}
103
120
  end
104
-
121
+
105
122
  def before_logout!(user)
106
123
  Config.before_logout.each {|c| self.send(c, user)}
107
124
  end
108
-
125
+
109
126
  def after_logout!
110
127
  Config.after_logout.each {|c| self.send(c)}
111
128
  end
112
-
129
+
113
130
  def user_class
114
131
  @user_class ||= Config.user_class.to_s.constantize
115
132
  end
133
+
116
134
  end
117
-
135
+
118
136
  module Config
119
137
  class << self
120
138
  attr_accessor :submodules,
121
- :user_class, # what class to use as the user class.
139
+ :user_class, # what class to use as the user class.
122
140
  :not_authenticated_action, # what controller action to call for non-authenticated users.
123
-
141
+
124
142
  :save_return_to_url, # when a non logged in user tries to enter a page that requires
125
- # login, save the URL he wanted to reach,
143
+ # login, save the URL he wanted to reach,
126
144
  # and send him there after login.
127
-
145
+
146
+ :cookie_domain, # set domain option for cookies
147
+
128
148
  :login_sources,
129
149
  :after_login,
130
150
  :after_failed_login,
131
151
  :before_logout,
132
- :after_logout
133
-
152
+ :after_logout
153
+
134
154
  def init!
135
155
  @defaults = {
136
156
  :@user_class => nil,
@@ -141,31 +161,32 @@ module Sorcery
141
161
  :@after_failed_login => [],
142
162
  :@before_logout => [],
143
163
  :@after_logout => [],
144
- :@save_return_to_url => true
164
+ :@save_return_to_url => true,
165
+ :@cookie_domain => nil
145
166
  }
146
167
  end
147
-
168
+
148
169
  # Resets all configuration options to their default values.
149
170
  def reset!
150
171
  @defaults.each do |k,v|
151
172
  instance_variable_set(k,v)
152
- end
173
+ end
153
174
  end
154
-
175
+
155
176
  def update!
156
177
  @defaults.each do |k,v|
157
178
  instance_variable_set(k,v) if !instance_variable_defined?(k)
158
179
  end
159
180
  end
160
-
181
+
161
182
  def user_config(&blk)
162
183
  block_given? ? @user_config = blk : @user_config
163
184
  end
164
-
185
+
165
186
  def configure(&blk)
166
187
  @configure_blk = blk
167
188
  end
168
-
189
+
169
190
  def configure!
170
191
  @configure_blk.call(self) if @configure_blk
171
192
  end
@@ -174,4 +195,4 @@ module Sorcery
174
195
  reset!
175
196
  end
176
197
  end
177
- end
198
+ end
@@ -28,12 +28,16 @@ module Sorcery
28
28
  end
29
29
 
30
30
  def matches?(crypted, *tokens)
31
- aes.decrypt
32
- aes.key = @key
33
- (aes.update(crypted.unpack("m").first) + aes.final) == tokens.join
31
+ decrypt(crypted) == tokens.join
34
32
  rescue OpenSSL::CipherError
35
33
  false
36
34
  end
35
+
36
+ def decrypt(crypted)
37
+ aes.decrypt
38
+ aes.key = @key
39
+ (aes.update(crypted.unpack("m").first) + aes.final)
40
+ end
37
41
 
38
42
  private
39
43
 
@@ -10,6 +10,7 @@ module Sorcery
10
10
  initializer "extend Controller with sorcery" do |app|
11
11
  ActionController::Base.send(:include, Sorcery::Controller)
12
12
  ActionController::Base.helper_method :current_user
13
+ ActionController::Base.helper_method :logged_in?
13
14
  end
14
15
 
15
16
  rake_tasks do
@@ -8,7 +8,8 @@ module Sorcery
8
8
 
9
9
  module ClassMethods
10
10
  def find_by_credentials(credentials)
11
- where("#{@sorcery_config.username_attribute_name} = ?", credentials[0]).first
11
+ sql = @sorcery_config.username_attribute_names.map{|attribute| "#{attribute} = :login"}
12
+ where(sql.join(' OR '), :login => credentials[0]).first
12
13
  end
13
14
 
14
15
  def find_by_sorcery_token(token_attr_name, token)
@@ -0,0 +1,49 @@
1
+ module Sorcery
2
+ module Model
3
+ module Adapters
4
+ module MongoMapper
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ include Sorcery::Model
9
+ end
10
+
11
+ module InstanceMethods
12
+ def increment(attr)
13
+ self.inc(attr,1)
14
+ end
15
+
16
+ def save!(options = {})
17
+ save(options)
18
+ end
19
+ end
20
+
21
+ module ClassMethods
22
+ def find_by_credentials(credentials)
23
+ @sorcery_config.username_attribute_names.each do |attribute|
24
+ @user = where(attribute => credentials[0]).first
25
+ break if @user
26
+ end
27
+ @user
28
+ end
29
+
30
+ def find_by_id(id)
31
+ find(id)
32
+ end
33
+
34
+ def find_by_activation_token(token)
35
+ where(sorcery_config.activation_token_attribute_name => token).first
36
+ end
37
+
38
+ def transaction(&blk)
39
+ tap(&blk)
40
+ end
41
+
42
+ def find_by_sorcery_token(token_attr_name, token)
43
+ where(token_attr_name => token).first
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -15,7 +15,11 @@ module Sorcery
15
15
 
16
16
  module ClassMethods
17
17
  def find_by_credentials(credentials)
18
- where(sorcery_config.username_attribute_name => credentials[0]).first
18
+ @sorcery_config.username_attribute_names.each do |attribute|
19
+ @user = where(attribute => credentials[0]).first
20
+ break if @user
21
+ end
22
+ @user
19
23
  end
20
24
 
21
25
  def find_by_provider_and_uid(provider, uid)
@@ -36,7 +40,8 @@ module Sorcery
36
40
  end
37
41
 
38
42
  def find_by_username(username)
39
- where(sorcery_config.username_attribute_name => username).first
43
+ query = sorcery_config.username_attribute_names.map {|name| {name => username}}
44
+ any_of(*query).first
40
45
  end
41
46
 
42
47
  def transaction(&blk)
@@ -26,6 +26,9 @@ module Sorcery
26
26
 
27
27
  base.sorcery_config.before_authenticate << :prevent_locked_user_login
28
28
  base.sorcery_config.after_config << :define_brute_force_protection_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
29
+ if defined?(MongoMapper) and base.ancestors.include?(MongoMapper::Document)
30
+ base.sorcery_config.after_config << :define_brute_force_protection_mongo_mapper_fields
31
+ end
29
32
  base.extend(ClassMethods)
30
33
  base.send(:include, InstanceMethods)
31
34
  end
@@ -37,6 +40,11 @@ module Sorcery
37
40
  field sorcery_config.failed_logins_count_attribute_name, :type => Integer
38
41
  field sorcery_config.lock_expires_at_attribute_name, :type => DateTime
39
42
  end
43
+
44
+ def define_brute_force_protection_mongo_mapper_fields
45
+ key sorcery_config.failed_logins_count_attribute_name, Integer
46
+ key sorcery_config.lock_expires_at_attribute_name, DateTime
47
+ end
40
48
  end
41
49
 
42
50
  module InstanceMethods
@@ -54,13 +62,15 @@ module Sorcery
54
62
 
55
63
  def lock!
56
64
  config = sorcery_config
57
- self.update_attributes!(config.lock_expires_at_attribute_name => Time.now.utc + config.login_lock_time_period)
65
+ self.send(:"#{config.lock_expires_at_attribute_name}=", Time.now.utc + config.login_lock_time_period)
66
+ self.save!
58
67
  end
59
68
 
60
69
  def unlock!
61
70
  config = sorcery_config
62
- self.update_attributes!(config.lock_expires_at_attribute_name => nil,
63
- config.failed_logins_count_attribute_name => 0)
71
+ self.send(:"#{config.lock_expires_at_attribute_name}=", nil)
72
+ self.send(:"#{config.failed_logins_count_attribute_name}=", 0)
73
+ self.save!
64
74
  end
65
75
 
66
76
  def unlocked?
@@ -24,7 +24,10 @@ module Sorcery
24
24
  base.send(:include, InstanceMethods)
25
25
 
26
26
  base.sorcery_config.after_config << :define_remember_me_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
27
-
27
+ if defined?(MongoMapper) and base.ancestors.include?(MongoMapper::Document)
28
+ base.sorcery_config.after_config << :define_remember_me_mongo_mapper_fields
29
+ end
30
+
28
31
  base.extend(ClassMethods)
29
32
  end
30
33
 
@@ -36,13 +39,17 @@ module Sorcery
36
39
  field sorcery_config.remember_me_token_expires_at_attribute_name, :type => Time
37
40
  end
38
41
 
42
+ def define_remember_me_mongo_mapper_fields
43
+ key sorcery_config.remember_me_token_attribute_name, String
44
+ key sorcery_config.remember_me_token_expires_at_attribute_name, Time
45
+ end
39
46
  end
40
47
 
41
48
  module InstanceMethods
42
49
  # You shouldn't really use this one yourself - it's called by the controller's 'remember_me!' method.
43
50
  def remember_me!
44
51
  config = sorcery_config
45
- self.send(:"#{config.remember_me_token_attribute_name}=", generate_random_token)
52
+ self.send(:"#{config.remember_me_token_attribute_name}=", TemporaryToken.generate_random_token)
46
53
  self.send(:"#{config.remember_me_token_expires_at_attribute_name}=", Time.now + config.remember_me_for)
47
54
  self.save!(:validate => false)
48
55
  end