sorcery 0.2.1 → 0.4.2

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 (163) hide show
  1. data/Gemfile +3 -2
  2. data/Gemfile.lock +13 -11
  3. data/README.rdoc +157 -61
  4. data/Rakefile +4 -4
  5. data/VERSION +1 -1
  6. data/lib/generators/sorcery_migration/sorcery_migration_generator.rb +24 -0
  7. data/lib/generators/sorcery_migration/templates/activity_logging.rb +17 -0
  8. data/lib/generators/sorcery_migration/templates/brute_force_protection.rb +11 -0
  9. data/lib/generators/sorcery_migration/templates/core.rb +16 -0
  10. data/lib/generators/sorcery_migration/templates/external.rb +14 -0
  11. data/lib/generators/sorcery_migration/templates/remember_me.rb +15 -0
  12. data/lib/generators/sorcery_migration/templates/reset_password.rb +13 -0
  13. data/lib/generators/sorcery_migration/templates/user_activation.rb +17 -0
  14. data/lib/sorcery/controller/adapters/sinatra.rb +97 -0
  15. data/lib/sorcery/controller/submodules/external/protocols/oauth1.rb +35 -0
  16. data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +26 -0
  17. data/lib/sorcery/controller/submodules/{oauth → external}/providers/facebook.rb +24 -6
  18. data/lib/sorcery/controller/submodules/{oauth → external}/providers/twitter.rb +31 -6
  19. data/lib/sorcery/controller/submodules/{oauth.rb → external.rb} +18 -27
  20. data/lib/sorcery/controller/submodules/http_basic_auth.rb +11 -7
  21. data/lib/sorcery/controller.rb +21 -21
  22. data/lib/sorcery/crypto_providers/bcrypt.rb +3 -5
  23. data/lib/sorcery/crypto_providers/common.rb +35 -0
  24. data/lib/sorcery/crypto_providers/md5.rb +3 -23
  25. data/lib/sorcery/crypto_providers/sha1.rb +4 -16
  26. data/lib/sorcery/crypto_providers/sha256.rb +3 -23
  27. data/lib/sorcery/crypto_providers/sha512.rb +3 -23
  28. data/lib/sorcery/engine.rb +4 -0
  29. data/lib/sorcery/initializers/initializer.rb +86 -0
  30. data/lib/sorcery/model/submodules/activity_logging.rb +2 -2
  31. data/lib/sorcery/model/submodules/brute_force_protection.rb +1 -5
  32. data/lib/sorcery/model/submodules/{oauth.rb → external.rb} +3 -3
  33. data/lib/sorcery/model/submodules/reset_password.rb +1 -1
  34. data/lib/sorcery/model.rb +34 -9
  35. data/lib/sorcery/railties/tasks.rake +10 -0
  36. data/lib/sorcery/sinatra.rb +5 -0
  37. data/lib/sorcery/test_helpers/internal/rails.rb +52 -0
  38. data/lib/sorcery/test_helpers/internal/sinatra.rb +122 -0
  39. data/lib/sorcery/test_helpers/internal.rb +55 -0
  40. data/lib/sorcery/test_helpers/rails.rb +16 -0
  41. data/lib/sorcery/test_helpers/sinatra.rb +85 -0
  42. data/lib/sorcery/test_helpers.rb +0 -79
  43. data/lib/sorcery.rb +25 -7
  44. data/sorcery.gemspec +207 -137
  45. data/spec/Gemfile +2 -2
  46. data/spec/Gemfile.lock +20 -12
  47. data/spec/Rakefile +1 -0
  48. data/spec/rails3/.rspec +1 -1
  49. data/spec/rails3/{app_root/Gemfile → Gemfile} +5 -7
  50. data/spec/rails3/{app_root/Gemfile.lock → Gemfile.lock} +20 -23
  51. data/spec/rails3/{app_root/Rakefile → Rakefile} +1 -0
  52. data/spec/rails3/{app_root/app → app}/controllers/application_controller.rb +11 -11
  53. data/spec/rails3/config/database.yml +27 -0
  54. data/spec/rails3/{app_root/spec → spec}/controller_activity_logging_spec.rb +2 -4
  55. data/spec/rails3/{app_root/spec → spec}/controller_brute_force_protection_spec.rb +3 -2
  56. data/spec/rails3/{app_root/spec → spec}/controller_oauth2_spec.rb +25 -22
  57. data/spec/rails3/{app_root/spec → spec}/controller_oauth_spec.rb +24 -19
  58. data/spec/rails3/spec/controller_session_timeout_spec.rb +55 -0
  59. data/spec/rails3/{app_root/spec → spec}/controller_spec.rb +6 -16
  60. data/spec/rails3/spec/spec.opts +2 -0
  61. data/spec/rails3/spec/spec_helper.rb +70 -0
  62. data/spec/rails3/{app_root/spec → spec}/user_activation_spec.rb +7 -13
  63. data/spec/rails3/{app_root/spec → spec}/user_brute_force_protection_spec.rb +2 -30
  64. data/spec/rails3/{app_root/spec → spec}/user_oauth_spec.rb +7 -7
  65. data/spec/rails3/{app_root/spec → spec}/user_remember_me_spec.rb +3 -11
  66. data/spec/rails3/{app_root/spec → spec}/user_reset_password_spec.rb +20 -17
  67. data/spec/rails3/{app_root/spec → spec}/user_spec.rb +21 -11
  68. data/spec/sinatra/Gemfile +12 -0
  69. data/spec/sinatra/Gemfile.lock +134 -0
  70. data/spec/sinatra/Rakefile +11 -0
  71. data/spec/sinatra/authentication.rb +3 -0
  72. data/spec/sinatra/db/migrate/activation/20101224223622_add_activation_to_users.rb +17 -0
  73. data/spec/sinatra/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +17 -0
  74. data/spec/sinatra/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +11 -0
  75. data/spec/sinatra/db/migrate/core/20101224223620_create_users.rb +16 -0
  76. data/spec/sinatra/db/migrate/external/20101224223628_create_authentications.rb +14 -0
  77. data/spec/sinatra/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +15 -0
  78. data/spec/sinatra/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
  79. data/spec/sinatra/filters.rb +21 -0
  80. data/spec/sinatra/myapp.rb +133 -0
  81. data/spec/sinatra/sorcery_mailer.rb +25 -0
  82. data/spec/sinatra/spec/controller_activity_logging_spec.rb +85 -0
  83. data/spec/sinatra/spec/controller_brute_force_protection_spec.rb +70 -0
  84. data/spec/sinatra/spec/controller_http_basic_auth_spec.rb +53 -0
  85. data/spec/sinatra/spec/controller_oauth2_spec.rb +120 -0
  86. data/spec/sinatra/spec/controller_oauth_spec.rb +121 -0
  87. data/spec/sinatra/spec/controller_remember_me_spec.rb +64 -0
  88. data/spec/sinatra/spec/controller_session_timeout_spec.rb +57 -0
  89. data/spec/sinatra/spec/controller_spec.rb +120 -0
  90. data/spec/sinatra/spec/spec.opts +2 -0
  91. data/spec/sinatra/spec/spec_helper.rb +46 -0
  92. data/spec/sinatra/user.rb +6 -0
  93. data/spec/sinatra/views/test_login.erb +4 -0
  94. data/spec/sorcery_crypto_providers_spec.rb +5 -4
  95. data/spec/spec.opts +2 -0
  96. data/spec/spec_helper.rb +3 -4
  97. data/spec/untitled folder +18 -0
  98. metadata +217 -139
  99. data/lib/sorcery/controller/submodules/oauth/oauth1.rb +0 -26
  100. data/lib/sorcery/controller/submodules/oauth/oauth2.rb +0 -24
  101. data/spec/rails3/app_root/.rspec +0 -1
  102. data/spec/rails3/app_root/config/database.yml +0 -27
  103. data/spec/rails3/app_root/spec/controller_session_timeout_spec.rb +0 -50
  104. data/spec/rails3/app_root/spec/spec_helper.rb +0 -61
  105. /data/spec/rails3/{app_root/.gitignore → .gitignore} +0 -0
  106. /data/spec/rails3/{app_root/README → README} +0 -0
  107. /data/spec/rails3/{app_root/Rakefile.unused → Rakefile.unused} +0 -0
  108. /data/spec/rails3/{app_root/app → app}/helpers/application_helper.rb +0 -0
  109. /data/spec/rails3/{app_root/app → app}/mailers/sorcery_mailer.rb +0 -0
  110. /data/spec/rails3/{app_root/app → app}/models/authentication.rb +0 -0
  111. /data/spec/rails3/{app_root/app → app}/models/user.rb +0 -0
  112. /data/spec/rails3/{app_root/app → app}/views/layouts/application.html.erb +0 -0
  113. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/activation_email.html.erb +0 -0
  114. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/activation_email.text.erb +0 -0
  115. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/activation_success_email.html.erb +0 -0
  116. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/activation_success_email.text.erb +0 -0
  117. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/reset_password_email.html.erb +0 -0
  118. /data/spec/rails3/{app_root/app → app}/views/sorcery_mailer/reset_password_email.text.erb +0 -0
  119. /data/spec/rails3/{app_root/config → config}/application.rb +0 -0
  120. /data/spec/rails3/{app_root/config → config}/boot.rb +0 -0
  121. /data/spec/rails3/{app_root/config → config}/environment.rb +0 -0
  122. /data/spec/rails3/{app_root/config → config}/environments/development.rb +0 -0
  123. /data/spec/rails3/{app_root/config → config}/environments/in_memory.rb +0 -0
  124. /data/spec/rails3/{app_root/config → config}/environments/production.rb +0 -0
  125. /data/spec/rails3/{app_root/config → config}/environments/test.rb +0 -0
  126. /data/spec/rails3/{app_root/config → config}/initializers/backtrace_silencers.rb +0 -0
  127. /data/spec/rails3/{app_root/config → config}/initializers/inflections.rb +0 -0
  128. /data/spec/rails3/{app_root/config → config}/initializers/mime_types.rb +0 -0
  129. /data/spec/rails3/{app_root/config → config}/initializers/secret_token.rb +0 -0
  130. /data/spec/rails3/{app_root/config → config}/initializers/session_store.rb +0 -0
  131. /data/spec/rails3/{app_root/config → config}/locales/en.yml +0 -0
  132. /data/spec/rails3/{app_root/config → config}/routes.rb +0 -0
  133. /data/spec/rails3/{app_root/config.ru → config.ru} +0 -0
  134. /data/spec/rails3/{app_root/db → db}/migrate/activation/20101224223622_add_activation_to_users.rb +0 -0
  135. /data/spec/rails3/{app_root/db → db}/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +0 -0
  136. /data/spec/rails3/{app_root/db → db}/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +0 -0
  137. /data/spec/rails3/{app_root/db → db}/migrate/core/20101224223620_create_users.rb +0 -0
  138. /data/spec/rails3/{app_root/db/migrate/oauth → db/migrate/external}/20101224223628_create_authentications.rb +0 -0
  139. /data/spec/rails3/{app_root/db → db}/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +0 -0
  140. /data/spec/rails3/{app_root/db → db}/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +0 -0
  141. /data/spec/rails3/{app_root/db → db}/schema.rb +0 -0
  142. /data/spec/rails3/{app_root/db → db}/seeds.rb +0 -0
  143. /data/spec/rails3/{app_root/lib → lib}/tasks/.gitkeep +0 -0
  144. /data/spec/rails3/{app_root/public → public}/404.html +0 -0
  145. /data/spec/rails3/{app_root/public → public}/422.html +0 -0
  146. /data/spec/rails3/{app_root/public → public}/500.html +0 -0
  147. /data/spec/rails3/{app_root/public → public}/favicon.ico +0 -0
  148. /data/spec/rails3/{app_root/public → public}/images/rails.png +0 -0
  149. /data/spec/rails3/{app_root/public → public}/index.html +0 -0
  150. /data/spec/rails3/{app_root/public → public}/javascripts/application.js +0 -0
  151. /data/spec/rails3/{app_root/public → public}/javascripts/controls.js +0 -0
  152. /data/spec/rails3/{app_root/public → public}/javascripts/dragdrop.js +0 -0
  153. /data/spec/rails3/{app_root/public → public}/javascripts/effects.js +0 -0
  154. /data/spec/rails3/{app_root/public → public}/javascripts/prototype.js +0 -0
  155. /data/spec/rails3/{app_root/public → public}/javascripts/rails.js +0 -0
  156. /data/spec/rails3/{app_root/public → public}/robots.txt +0 -0
  157. /data/spec/rails3/{app_root/public → public}/stylesheets/.gitkeep +0 -0
  158. /data/spec/rails3/{app_root/script → script}/rails +0 -0
  159. /data/spec/rails3/{app_root/spec → spec}/controller_http_basic_auth_spec.rb +0 -0
  160. /data/spec/rails3/{app_root/spec → spec}/controller_remember_me_spec.rb +0 -0
  161. /data/spec/rails3/{app_root/spec → spec}/spec_helper.orig.rb +0 -0
  162. /data/spec/rails3/{app_root/spec → spec}/user_activity_logging_spec.rb +0 -0
  163. /data/spec/rails3/{app_root/vendor → vendor}/plugins/.gitkeep +0 -0
@@ -1,7 +1,7 @@
1
1
  module Sorcery
2
2
  module Controller
3
3
  module Submodules
4
- module Oauth
4
+ module External
5
5
  module Providers
6
6
  # This module adds support for OAuth with facebook.com.
7
7
  # When included in the 'config.providers' option, it adds a new option, 'config.facebook'.
@@ -16,7 +16,7 @@ module Sorcery
16
16
  base.module_eval do
17
17
  class << self
18
18
  attr_reader :facebook # access to facebook_client.
19
-
19
+
20
20
  def merge_facebook_defaults!
21
21
  @defaults.merge!(:@facebook => FacebookClient)
22
22
  end
@@ -36,7 +36,7 @@ module Sorcery
36
36
  :scope,
37
37
  :user_info_mapping
38
38
 
39
- include Oauth2
39
+ include Protocols::Oauth2
40
40
 
41
41
  def init
42
42
  @site = "https://graph.facebook.com"
@@ -45,13 +45,31 @@ module Sorcery
45
45
  @user_info_mapping = {}
46
46
  end
47
47
 
48
- def get_user_hash(access_token)
48
+ def get_user_hash
49
49
  user_hash = {}
50
- response = access_token.get(@user_info_path)
50
+ response = @access_token.get(@user_info_path)
51
51
  user_hash[:user_info] = JSON.parse(response)
52
- user_hash[:uid] = user_hash[:user_info]['id'].to_i
52
+ user_hash[:uid] = user_hash[:user_info]['id']
53
53
  user_hash
54
54
  end
55
+
56
+ def has_callback?
57
+ true
58
+ end
59
+
60
+ # calculates and returns the url to which the user should be redirected,
61
+ # to get authenticated at the external provider's site.
62
+ def login_url(params,session)
63
+ self.authorize_url
64
+ end
65
+
66
+ # tries to login the user from access token
67
+ def process_callback(params,session)
68
+ args = {}
69
+ args.merge!({:code => params[:code]}) if params[:code]
70
+ @access_token = self.get_access_token(args)
71
+ end
72
+
55
73
  end
56
74
  init
57
75
  end
@@ -1,7 +1,7 @@
1
1
  module Sorcery
2
2
  module Controller
3
3
  module Submodules
4
- module Oauth
4
+ module External
5
5
  module Providers
6
6
  # This module adds support for OAuth with Twitter.com.
7
7
  # When included in the 'config.providers' option, it adds a new option, 'config.twitter'.
@@ -15,7 +15,10 @@ module Sorcery
15
15
  def self.included(base)
16
16
  base.module_eval do
17
17
  class << self
18
- attr_reader :twitter # access to twitter_client.
18
+ attr_reader :twitter
19
+ # def twitter(&blk) # allows block syntax.
20
+ # yield @twitter
21
+ # end
19
22
 
20
23
  def merge_twitter_defaults!
21
24
  @defaults.merge!(:@twitter => TwitterClient)
@@ -25,7 +28,7 @@ module Sorcery
25
28
  update!
26
29
  end
27
30
  end
28
-
31
+
29
32
  module TwitterClient
30
33
  class << self
31
34
  attr_accessor :key,
@@ -35,7 +38,7 @@ module Sorcery
35
38
  :user_info_path,
36
39
  :user_info_mapping
37
40
 
38
- include Oauth1
41
+ include Protocols::Oauth1
39
42
 
40
43
  def init
41
44
  @site = "https://api.twitter.com"
@@ -43,13 +46,35 @@ module Sorcery
43
46
  @user_info_mapping = {}
44
47
  end
45
48
 
46
- def get_user_hash(access_token)
49
+ def get_user_hash
47
50
  user_hash = {}
48
- response = access_token.get(@user_info_path)
51
+ response = @access_token.get(@user_info_path)
49
52
  user_hash[:user_info] = JSON.parse(response.body)
50
53
  user_hash[:uid] = user_hash[:user_info]['id']
51
54
  user_hash
52
55
  end
56
+
57
+ def has_callback?
58
+ true
59
+ end
60
+
61
+ # calculates and returns the url to which the user should be redirected,
62
+ # to get authenticated at the external provider's site.
63
+ def login_url(params,session)
64
+ req_token = self.get_request_token
65
+ session[:request_token] = req_token.token
66
+ session[:request_token_secret] = req_token.secret
67
+ self.authorize_url({:request_token => req_token.token, :request_token_secret => req_token.secret})
68
+ end
69
+
70
+ # tries to login the user from access token
71
+ def process_callback(params,session)
72
+ args = {}
73
+ args.merge!({:oauth_verifier => params[:oauth_verifier], :request_token => session[:request_token], :request_token_secret => session[:request_token_secret]})
74
+ args.merge!({:code => params[:code]}) if params[:code]
75
+ @access_token = self.get_access_token(args)
76
+ end
77
+
53
78
  end
54
79
  init
55
80
  end
@@ -1,27 +1,26 @@
1
1
  module Sorcery
2
2
  module Controller
3
3
  module Submodules
4
- # This submodule helps you login users from OAuth providers such as Twitter.
4
+ # This submodule helps you login users from external auth providers such as Twitter.
5
5
  # This is the controller part which handles the http requests and tokens passed between the app and the provider.
6
- # For more configuration options see Sorcery::Model::Oauth.
7
- module Oauth
6
+ module External
8
7
  def self.included(base)
9
8
  base.send(:include, InstanceMethods)
10
9
  Config.module_eval do
11
10
  class << self
12
- attr_reader :oauth_providers # oauth providers like twitter.
11
+ attr_reader :external_providers # external providers like twitter.
13
12
 
14
- def merge_oauth_defaults!
15
- @defaults.merge!(:@oauth_providers => [])
13
+ def merge_external_defaults!
14
+ @defaults.merge!(:@external_providers => [])
16
15
  end
17
16
 
18
- def oauth_providers=(providers)
17
+ def external_providers=(providers)
19
18
  providers.each do |provider|
20
19
  include Providers.const_get(provider.to_s.split("_").map {|p| p.capitalize}.join(""))
21
20
  end
22
21
  end
23
22
  end
24
- merge_oauth_defaults!
23
+ merge_external_defaults!
25
24
  end
26
25
  end
27
26
 
@@ -30,23 +29,20 @@ module Sorcery
30
29
 
31
30
  # sends user to authenticate at the provider's website.
32
31
  # after authentication the user is redirected to the callback defined in the provider config
33
- def auth_at_provider(provider)
32
+ def login_at(provider, args = {})
34
33
  @provider = Config.send(provider)
35
- if @provider.respond_to?(:get_request_token)
36
- args = {:request_token => @provider.get_request_token}
37
- session[:request_token] = args[:request_token]
34
+ if @provider.has_callback?
35
+ redirect_to @provider.login_url(params,session)
36
+ else
37
+ #@provider.login(args)
38
38
  end
39
- redirect_to @provider.authorize_url(args)
40
39
  end
41
40
 
42
- # tries to login the user from access token
43
- def login_from_access_token(provider)
41
+ # tries to login the user from provider's callback
42
+ def login_from(provider)
44
43
  @provider = Config.send(provider)
45
- args = {}
46
- args.merge!({:oauth_verifier => params[:oauth_verifier], :request_token => session[:request_token]}) if @provider.respond_to?(:get_request_token)
47
- args.merge!({:code => params[:code]}) if params[:code]
48
- @access_token = @provider.get_access_token(args)
49
- @user_hash = @provider.get_user_hash(@access_token)
44
+ @provider.process_callback(params,session)
45
+ @user_hash = @provider.get_user_hash
50
46
  if user = Config.user_class.load_from_provider(provider,@user_hash[:uid])
51
47
  reset_session
52
48
  login_user(user)
@@ -54,11 +50,6 @@ module Sorcery
54
50
  end
55
51
  end
56
52
 
57
- def get_user_hash(provider)
58
- @provider = Config.send(provider)
59
- @provider.get_user_hash(@access_token)
60
- end
61
-
62
53
  # this method automatically creates a new user from the data in the external user hash.
63
54
  # The mappings from user hash fields to user db fields are set at controller config.
64
55
  # If the hash field you would like to map is nested, use slashes. For example, Given a hash like:
@@ -70,10 +61,10 @@ module Sorcery
70
61
  # {:username => "user/name"}
71
62
  #
72
63
  # And this will cause 'moishe' to be set as the value of :username field.
73
- def create_from_provider!(provider)
64
+ def create_from(provider)
74
65
  provider = provider.to_sym
75
66
  @provider = Config.send(provider)
76
- @user_hash = get_user_hash(provider)
67
+ @user_hash = @provider.get_user_hash
77
68
  config = Config.user_class.sorcery_config
78
69
  attrs = {}
79
70
  @provider.user_info_mapping.each do |k,v|
@@ -9,7 +9,7 @@ module Sorcery
9
9
  base.send(:include, InstanceMethods)
10
10
  Config.module_eval do
11
11
  class << self
12
- attr_accessor :controller_to_realm_map # how many failed logins allowed.
12
+ attr_accessor :controller_to_realm_map # What realm to display for which controller name.
13
13
 
14
14
  def merge_http_basic_auth_defaults!
15
15
  @defaults.merge!(:@controller_to_realm_map => {"application" => "Application"})
@@ -48,13 +48,17 @@ module Sorcery
48
48
 
49
49
  # Sets the realm name by searching the controller name in the hash given at configuration time.
50
50
  def realm_name_by_controller
51
- current_controller = self.class
52
- while current_controller != ActionController::Base
53
- result = Config.controller_to_realm_map[current_controller.controller_name]
54
- return result if result
55
- current_controller = self.class.superclass
51
+ if defined?(ActionController::Base)
52
+ current_controller = self.class
53
+ while current_controller != ActionController::Base
54
+ result = Config.controller_to_realm_map[current_controller.controller_name]
55
+ return result if result
56
+ current_controller = self.class.superclass
57
+ end
58
+ nil
59
+ else
60
+ Config.controller_to_realm_map["application"]
56
61
  end
57
- nil
58
62
  end
59
63
 
60
64
  end
@@ -2,28 +2,17 @@ module Sorcery
2
2
  module Controller
3
3
  def self.included(klass)
4
4
  klass.class_eval do
5
- extend ClassMethods
6
5
  include InstanceMethods
7
6
  Config.submodules.each do |mod|
8
- begin # FIXME: is this protection needed?
7
+ begin
9
8
  include Submodules.const_get(mod.to_s.split("_").map {|p| p.capitalize}.join(""))
10
9
  rescue NameError
11
10
  # don't stop on a missing submodule.
12
11
  end
13
12
  end
14
- Config.update!
15
- end
16
- end
17
-
18
- module ClassMethods
19
- def activate_sorcery!(&block)
20
- yield Config if block_given?
21
- after_config!
22
- end
23
-
24
- def after_config!
25
- Config.after_config.each {|c| send(c)}
26
13
  end
14
+ Config.update!
15
+ Config.configure!
27
16
  end
28
17
 
29
18
  module InstanceMethods
@@ -73,12 +62,14 @@ module Sorcery
73
62
  @current_user ||= login_from_session || login_from_other_sources unless @current_user == false
74
63
  end
75
64
 
76
- def return_or_redirect_to(url, flash_hash = {})
65
+ # used when a user tries to access a page while logged out, is asked to login, and we want to return him back to the page he originally wanted.
66
+ def redirect_back_or_to(url, flash_hash = {})
77
67
  redirect_to(session[:return_to_url] || url, :flash => flash_hash)
78
68
  end
79
69
 
80
70
  # The default action for denying non-authenticated users.
81
- # You can override this method in your controllers.
71
+ # You can override this method in your controllers,
72
+ # or provide a different method in the configuration.
82
73
  def not_authenticated
83
74
  redirect_to root_path
84
75
  end
@@ -124,7 +115,7 @@ module Sorcery
124
115
  class << self
125
116
  attr_accessor :submodules,
126
117
 
127
- :user_class, # what class to use as the user class. Set automatically when you call activate_sorcery! in the User class.
118
+ :user_class, # what class to use as the user class. Set automatically when you call authenticates_with_sorcery! in the User class.
128
119
 
129
120
  :not_authenticated_action, # what controller action to call for non-authenticated users.
130
121
 
@@ -135,9 +126,7 @@ module Sorcery
135
126
  :after_login,
136
127
  :after_failed_login,
137
128
  :before_logout,
138
- :after_logout,
139
- :after_config
140
-
129
+ :after_logout
141
130
 
142
131
  def init!
143
132
  @defaults = {
@@ -149,7 +138,6 @@ module Sorcery
149
138
  :@after_failed_login => [],
150
139
  :@before_logout => [],
151
140
  :@after_logout => [],
152
- :@after_config => [],
153
141
  :@save_return_to_url => true
154
142
  }
155
143
  end
@@ -166,6 +154,18 @@ module Sorcery
166
154
  instance_variable_set(k,v) if !instance_variable_defined?(k)
167
155
  end
168
156
  end
157
+
158
+ def user_config(&blk)
159
+ block_given? ? @user_config = blk : @user_config
160
+ end
161
+
162
+ def configure(&blk)
163
+ @configure_blk = blk
164
+ end
165
+
166
+ def configure!
167
+ @configure_blk.call(self) if @configure_blk
168
+ end
169
169
  end
170
170
  init!
171
171
  reset!
@@ -30,11 +30,9 @@ module Sorcery
30
30
  #
31
31
  # gem install bcrypt-ruby
32
32
  #
33
- # Tell activate_sorcery! to use it:
33
+ # Update your initializer to use it:
34
34
  #
35
- # activate_sorcery! do |c|
36
- # c.encryption_algorithm = :bcrypt
37
- # end
35
+ # config.encryption_algorithm = :bcrypt
38
36
  #
39
37
  # You are good to go!
40
38
  class BCrypt
@@ -42,7 +40,7 @@ module Sorcery
42
40
  # This is the :cost option for the BCrpyt library. The higher the cost the more secure it is and the longer is take the generate a hash. By default this is 10.
43
41
  # Set this to whatever you want, play around with it to get that perfect balance between security and performance.
44
42
  def cost
45
- @cost ||= 1
43
+ @cost ||= 10
46
44
  end
47
45
  attr_writer :cost
48
46
  alias :stretches= :cost=
@@ -0,0 +1,35 @@
1
+ module Sorcery
2
+ module CryptoProviders
3
+ module Common
4
+ def self.included(base)
5
+ base.class_eval do
6
+ class << self
7
+ attr_accessor :join_token
8
+
9
+ # The number of times to loop through the encryption.
10
+ def stretches
11
+ @stretches ||= 1
12
+ end
13
+ attr_writer :stretches
14
+
15
+ def encrypt(*tokens)
16
+ digest = tokens.flatten.join(join_token)
17
+ stretches.times { digest = secure_digest(digest) }
18
+ digest
19
+ end
20
+
21
+ # Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
22
+ def matches?(crypted, *tokens)
23
+ encrypt(*tokens) == crypted
24
+ end
25
+
26
+ def reset!
27
+ @stretches = 1
28
+ @join_token = nil
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -8,30 +8,10 @@ module Sorcery
8
8
  #
9
9
  # Please use any other provider offered by Sorcery.
10
10
  class MD5
11
+ include Common
11
12
  class << self
12
- attr_accessor :join_token
13
-
14
- # The number of times to loop through the encryption.
15
- def stretches
16
- @stretches ||= 1
17
- end
18
- attr_writer :stretches
19
-
20
- # Turns your raw password into a MD5 hash.
21
- def encrypt(*tokens)
22
- digest = tokens.flatten.join(join_token)
23
- stretches.times { digest = Digest::MD5.hexdigest(digest) }
24
- digest
25
- end
26
-
27
- # Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
28
- def matches?(crypted, *tokens)
29
- encrypt(*tokens) == crypted
30
- end
31
-
32
- def reset!
33
- @stretches = 1
34
- @join_token = nil
13
+ def secure_digest(digest)
14
+ Digest::MD5.hexdigest(digest)
35
15
  end
36
16
  end
37
17
  end
@@ -5,34 +5,22 @@ module Sorcery
5
5
  # This class was made for the users transitioning from restful_authentication. I highly discourage using this
6
6
  # crypto provider as it inferior to your other options. Please use any other provider offered by Sorcery.
7
7
  class SHA1
8
+ include Common
8
9
  class << self
9
10
  def join_token
10
11
  @join_token ||= "--"
11
12
  end
12
- attr_writer :join_token
13
-
14
- # The number of times to loop through the encryption. This is ten because that is what restful_authentication defaults to.
15
- def stretches
16
- @stretches ||= 10
17
- end
18
- attr_writer :stretches
19
13
 
20
14
  # Turns your raw password into a Sha1 hash.
21
15
  def encrypt(*tokens)
22
16
  tokens = tokens.flatten
23
17
  digest = tokens.shift
24
- stretches.times { digest = Digest::SHA1.hexdigest([digest, *tokens].join(join_token)) }
18
+ stretches.times { digest = secure_digest([digest, *tokens].join(join_token)) }
25
19
  digest
26
20
  end
27
21
 
28
- # Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
29
- def matches?(crypted, *tokens)
30
- encrypt(*tokens) == crypted
31
- end
32
-
33
- def reset!
34
- @stretches = 10
35
- @join_token = nil
22
+ def secure_digest(digest)
23
+ Digest::SHA1.hexdigest(digest)
36
24
  end
37
25
  end
38
26
  end
@@ -24,30 +24,10 @@ module Sorcery
24
24
  #
25
25
  # Uses the Sha256 hash algorithm to encrypt passwords.
26
26
  class SHA256
27
+ include Common
27
28
  class << self
28
- attr_accessor :join_token
29
-
30
- # The number of times to loop through the encryption.
31
- def stretches
32
- @stretches ||= 20
33
- end
34
- attr_writer :stretches
35
-
36
- # Turns your raw password into a Sha256 hash.
37
- def encrypt(*tokens)
38
- digest = tokens.flatten.join(join_token)
39
- stretches.times { digest = Digest::SHA256.hexdigest(digest) }
40
- digest
41
- end
42
-
43
- # Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
44
- def matches?(crypted, *tokens)
45
- encrypt(*tokens) == crypted
46
- end
47
-
48
- def reset!
49
- @stretches = 20
50
- @join_token = nil
29
+ def secure_digest(digest)
30
+ Digest::SHA256.hexdigest(digest)
51
31
  end
52
32
  end
53
33
  end
@@ -24,30 +24,10 @@ module Sorcery
24
24
  #
25
25
  # Uses the Sha512 hash algorithm to encrypt passwords.
26
26
  class SHA512
27
+ include Common
27
28
  class << self
28
- attr_accessor :join_token
29
-
30
- # The number of times to loop through the encryption.
31
- def stretches
32
- @stretches ||= 20
33
- end
34
- attr_writer :stretches
35
-
36
- # Turns your raw password into a Sha512 hash.
37
- def encrypt(*tokens)
38
- digest = tokens.flatten.join(join_token)
39
- stretches.times { digest = Digest::SHA512.hexdigest(digest) }
40
- digest
41
- end
42
-
43
- # Does the crypted password match the tokens? Uses the same tokens that were used to encrypt.
44
- def matches?(crypted, *tokens)
45
- encrypt(*tokens) == crypted
46
- end
47
-
48
- def reset!
49
- @stretches = 20
50
- @join_token = nil
29
+ def secure_digest(digest)
30
+ Digest::SHA512.hexdigest(digest)
51
31
  end
52
32
  end
53
33
  end
@@ -23,5 +23,9 @@ module Sorcery
23
23
  end
24
24
  end
25
25
 
26
+ rake_tasks do
27
+ load "sorcery/railties/tasks.rake"
28
+ end
29
+
26
30
  end
27
31
  end
@@ -0,0 +1,86 @@
1
+ # The first thing you need to configure is which modules you need in your app.
2
+ # The default is nothing which will include only core features (password encryption, login/logout).
3
+ # Available submodules are: :user_activation, :http_basic_auth, :remember_me, :reset_password, :session_timeout, :brute_force_protection, :activity_logging, :external
4
+ Rails.application.config.sorcery.submodules = []
5
+
6
+ # Here you can configure each submodule's features.
7
+ Rails.application.config.sorcery.configure do |config|
8
+ # -- core --
9
+ # config.not_authenticated_action = :not_authenticated # what controller action to call for non-authenticated users. You can also override 'not_authenticated' instead.
10
+ # config.save_return_to_url = true # when a non logged in user tries to enter a page that requires login, save the URL he wanted to reach,
11
+ # and send him there after login, using 'redirect_back_or_to'.
12
+ # subclasses_inherit_config = false # make this configuration inheritable for subclasses. Useful for ActiveRecord's STI.
13
+
14
+ # -- session timeout --
15
+ # config.session_timeout = 3600 # how long in seconds to keep the session alive.
16
+ # config.session_timeout_from_last_action = false # use the last action as the beginning of session timeout.
17
+
18
+ # -- http_basic_auth --
19
+ # config.controller_to_realm_map = {"application" => "Application"} # What realm to display for which controller name.
20
+ # For example {"My App" => "Application"}
21
+
22
+ # -- external --
23
+ # config.external_providers = [] # What providers are supported by this app, i.e. [:twitter, :facebook] .
24
+ #
25
+ # config.twitter.key = "eYVNBjBDi33aa9GkA3w"
26
+ # config.twitter.secret = "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8"
27
+ # config.twitter.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=twitter"
28
+ # config.twitter.user_info_mapping = {:email => "screen_name"}
29
+ #
30
+ # config.facebook.key = "34cebc81c08a521bc66e212f947d73ec"
31
+ # config.facebook.secret = "5b458d179f61d4f036ee66a497ffbcd0"
32
+ # config.facebook.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=facebook"
33
+ # config.facebook.user_info_mapping = {:email => "name"}
34
+
35
+ # --- user config ---
36
+ config.user_config do |user|
37
+ # -- core --
38
+ # user.username_attribute_name = :username # change default username attribute, for example, to use :email as the login.
39
+ # user.password_attribute_name = :password # change *virtual* password attribute, the one which is used until an encrypted one is generated.
40
+ # user.email_attribute_name = :email # change default email attribute.
41
+ # user.crypted_password_attribute_name = :crypted_password # change default crypted_password attribute.
42
+ # user.salt_join_token = "" # what pattern to use to join the password with the salt
43
+ # user.salt_attribute_name = :salt # change default salt attribute.
44
+ # user.stretches = nil # how many times to apply encryption to the password.
45
+ # user.encryption_key = nil # encryption key used to encrypt reversible encryptions such as AES256.
46
+ # user.custom_encryption_provider = nil # use an external encryption class.
47
+ # user.encryption_algorithm = :bcrypt # encryption algorithm name. See 'encryption_algorithm=' for available options.
48
+
49
+ # -- user_activation --
50
+ # user.activation_state_attribute_name = :activation_state # the attribute name to hold activation state (active/pending).
51
+ # user.activation_token_attribute_name = :activation_token # the attribute name to hold activation code (sent by email).
52
+ # user.activation_token_expires_at_attribute_name = :activation_token_expires_at # the attribute name to hold activation code expiration date.
53
+ # user.activation_token_expiration_period = nil # how many seconds before the activation code expires. nil for never expires.
54
+ # user.user_activation_mailer = nil # your mailer class. Required.
55
+ # user.activation_needed_email_method_name = :activation_needed_email # activation needed email method on your mailer class.
56
+ # user.activation_success_email_method_name = :activation_success_email # activation success email method on your mailer class.
57
+ # user.prevent_non_active_users_to_login = true # do you want to prevent or allow users that did not activate by email to login?
58
+
59
+ # -- reset_password --
60
+ # user.reset_password_token_attribute_name = :reset_password_token # reset password code attribute name.
61
+ # user.reset_password_token_expires_at_attribute_name = :reset_password_token_expires_at # expires at attribute name.
62
+ # user.reset_password_email_sent_at_attribute_name = :reset_password_email_sent_at # when was email sent, used for hammering protection.
63
+ # user.reset_password_mailer = nil # mailer class. Needed.
64
+ # user.reset_password_email_method_name = :reset_password_email # reset password email method on your mailer class.
65
+ # user.reset_password_expiration_period = nil # how many seconds before the reset request expires. nil for never expires.
66
+ # user.reset_password_time_between_emails = 5 * 60 # hammering protection, how long to wait before allowing another email to be sent.
67
+
68
+ # -- brute_force_protection --
69
+ # user.failed_logins_count_attribute_name = :failed_logins_count # failed logins attribute name.
70
+ # user.lock_expires_at_attribute_name = :lock_expires_at # this field indicates whether user is banned and when it will be active again.
71
+ # user.consecutive_login_retries_amount_limit = 50 # how many failed logins allowed.
72
+ # user.login_lock_time_period = 60 * 60 # how long the user should be banned. in seconds. 0 for permanent.
73
+
74
+ # -- activity logging --
75
+ # user.last_login_at_attribute_name = :last_login_at # last login attribute name.
76
+ # user.last_logout_at_attribute_name = :last_logout_at # last logout attribute name.
77
+ # user.last_activity_at_attribute_name = :last_activity_at # last activity attribute name.
78
+ # user.activity_timeout = 10 * 60 # how long since last activity is the user defined logged out?
79
+
80
+ # -- external --
81
+ # user.authentications_class = nil # class which holds the various external provider data for this user.
82
+ # user.authentications_user_id_attribute_name = :user_id # user's identifier in authentications class.
83
+ # user.provider_attribute_name = :provider # provider's identifier in authentications class.
84
+ # user.provider_uid_attribute_name = :uid # user's external unique identifier in authentications class.
85
+ end
86
+ end