sorcery 0.8.5 → 0.9.0

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. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.travis.yml +122 -5
  4. data/CHANGELOG.md +37 -1
  5. data/Gemfile +10 -18
  6. data/README.md +159 -88
  7. data/gemfiles/active_record-rails40.gemfile +7 -0
  8. data/gemfiles/active_record-rails41.gemfile +7 -0
  9. data/gemfiles/mongo_mapper-rails40.gemfile +9 -0
  10. data/gemfiles/mongo_mapper-rails41.gemfile +9 -0
  11. data/gemfiles/mongoid-rails40.gemfile +9 -0
  12. data/gemfiles/mongoid-rails41.gemfile +9 -0
  13. data/gemfiles/mongoid3-rails32.gemfile +9 -0
  14. data/lib/generators/sorcery/USAGE +1 -1
  15. data/lib/generators/sorcery/install_generator.rb +19 -5
  16. data/lib/generators/sorcery/templates/initializer.rb +34 -9
  17. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +3 -1
  18. data/lib/generators/sorcery/templates/migration/core.rb +2 -2
  19. data/lib/generators/sorcery/templates/migration/external.rb +3 -1
  20. data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
  21. data/lib/sorcery/adapters/base_adapter.rb +30 -0
  22. data/lib/sorcery/adapters/data_mapper_adapter.rb +176 -0
  23. data/lib/sorcery/adapters/mongo_mapper_adapter.rb +110 -0
  24. data/lib/sorcery/adapters/mongoid_adapter.rb +97 -0
  25. data/lib/sorcery/controller/config.rb +65 -0
  26. data/lib/sorcery/controller/submodules/activity_logging.rb +16 -21
  27. data/lib/sorcery/controller/submodules/brute_force_protection.rb +6 -6
  28. data/lib/sorcery/controller/submodules/external.rb +35 -40
  29. data/lib/sorcery/controller/submodules/remember_me.rb +4 -4
  30. data/lib/sorcery/controller/submodules/session_timeout.rb +10 -6
  31. data/lib/sorcery/controller.rb +10 -74
  32. data/lib/sorcery/model/config.rb +96 -0
  33. data/lib/sorcery/model/submodules/activity_logging.rb +30 -13
  34. data/lib/sorcery/model/submodules/brute_force_protection.rb +21 -21
  35. data/lib/sorcery/model/submodules/external.rb +53 -9
  36. data/lib/sorcery/model/submodules/remember_me.rb +15 -19
  37. data/lib/sorcery/model/submodules/reset_password.rb +33 -34
  38. data/lib/sorcery/model/submodules/user_activation.rb +36 -47
  39. data/lib/sorcery/model/temporary_token.rb +4 -4
  40. data/lib/sorcery/model.rb +73 -173
  41. data/lib/sorcery/protocols/oauth.rb +42 -0
  42. data/lib/sorcery/protocols/oauth2.rb +47 -0
  43. data/lib/sorcery/providers/base.rb +38 -0
  44. data/lib/sorcery/providers/facebook.rb +63 -0
  45. data/lib/sorcery/providers/github.rb +51 -0
  46. data/lib/sorcery/providers/google.rb +51 -0
  47. data/lib/sorcery/providers/heroku.rb +57 -0
  48. data/lib/sorcery/providers/jira.rb +77 -0
  49. data/lib/sorcery/providers/linkedin.rb +66 -0
  50. data/lib/sorcery/providers/liveid.rb +53 -0
  51. data/lib/sorcery/providers/salesforce.rb +50 -0
  52. data/lib/sorcery/providers/twitter.rb +59 -0
  53. data/lib/sorcery/providers/vk.rb +63 -0
  54. data/lib/sorcery/providers/xing.rb +64 -0
  55. data/lib/sorcery/test_helpers/internal/rails.rb +14 -3
  56. data/lib/sorcery/test_helpers/internal.rb +7 -3
  57. data/lib/sorcery/test_helpers/rails/controller.rb +21 -0
  58. data/lib/sorcery/test_helpers/rails/integration.rb +26 -0
  59. data/lib/sorcery/version.rb +3 -0
  60. data/lib/sorcery.rb +82 -58
  61. data/sorcery.gemspec +19 -19
  62. data/spec/active_record/user_activation_spec.rb +1 -1
  63. data/spec/active_record/user_activity_logging_spec.rb +10 -1
  64. data/spec/active_record/user_brute_force_protection_spec.rb +1 -1
  65. data/spec/active_record/user_oauth_spec.rb +1 -1
  66. data/spec/active_record/user_remember_me_spec.rb +1 -1
  67. data/spec/active_record/user_reset_password_spec.rb +1 -1
  68. data/spec/active_record/user_spec.rb +7 -8
  69. data/spec/controllers/controller_activity_logging_spec.rb +124 -0
  70. data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
  71. data/spec/controllers/controller_http_basic_auth_spec.rb +68 -0
  72. data/spec/controllers/controller_oauth2_spec.rb +414 -0
  73. data/spec/controllers/controller_oauth_spec.rb +240 -0
  74. data/spec/controllers/controller_remember_me_spec.rb +117 -0
  75. data/spec/controllers/controller_session_timeout_spec.rb +80 -0
  76. data/spec/controllers/controller_spec.rb +218 -0
  77. data/spec/data_mapper/user_activation_spec.rb +10 -0
  78. data/spec/data_mapper/user_activity_logging_spec.rb +14 -0
  79. data/spec/data_mapper/user_brute_force_protection_spec.rb +9 -0
  80. data/spec/data_mapper/user_oauth_spec.rb +9 -0
  81. data/spec/data_mapper/user_remember_me_spec.rb +8 -0
  82. data/spec/data_mapper/user_reset_password_spec.rb +8 -0
  83. data/spec/data_mapper/user_spec.rb +27 -0
  84. data/spec/mongo_mapper/user_activation_spec.rb +1 -2
  85. data/spec/mongo_mapper/user_activity_logging_spec.rb +1 -1
  86. data/spec/mongo_mapper/user_brute_force_protection_spec.rb +1 -1
  87. data/spec/mongo_mapper/user_oauth_spec.rb +1 -1
  88. data/spec/mongo_mapper/user_remember_me_spec.rb +1 -1
  89. data/spec/mongo_mapper/user_reset_password_spec.rb +1 -1
  90. data/spec/mongo_mapper/user_spec.rb +7 -8
  91. data/spec/mongoid/user_activation_spec.rb +1 -2
  92. data/spec/mongoid/user_activity_logging_spec.rb +1 -2
  93. data/spec/mongoid/user_brute_force_protection_spec.rb +1 -2
  94. data/spec/mongoid/user_oauth_spec.rb +1 -2
  95. data/spec/mongoid/user_remember_me_spec.rb +1 -2
  96. data/spec/mongoid/user_reset_password_spec.rb +1 -2
  97. data/spec/mongoid/user_spec.rb +21 -9
  98. data/spec/orm/active_record.rb +14 -0
  99. data/spec/orm/data_mapper.rb +48 -0
  100. data/spec/orm/mongo_mapper.rb +1 -1
  101. data/spec/orm/mongoid.rb +5 -0
  102. data/spec/rails_app/app/controllers/sorcery_controller.rb +125 -59
  103. data/spec/rails_app/app/data_mapper/authentication.rb +8 -0
  104. data/spec/rails_app/app/data_mapper/user.rb +7 -0
  105. data/spec/rails_app/app/mongo_mapper/user.rb +2 -0
  106. data/spec/rails_app/config/routes.rb +27 -13
  107. data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +2 -2
  108. data/spec/shared_examples/user_activation_shared_examples.rb +108 -91
  109. data/spec/shared_examples/user_activity_logging_shared_examples.rb +83 -15
  110. data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +140 -21
  111. data/spec/shared_examples/user_oauth_shared_examples.rb +21 -16
  112. data/spec/shared_examples/user_remember_me_shared_examples.rb +36 -24
  113. data/spec/shared_examples/user_reset_password_shared_examples.rb +138 -117
  114. data/spec/shared_examples/user_shared_examples.rb +297 -150
  115. data/spec/sorcery_crypto_providers_spec.rb +28 -28
  116. data/spec/spec_helper.rb +12 -18
  117. metadata +99 -165
  118. data/Gemfile.rails4 +0 -24
  119. data/VERSION +0 -1
  120. data/lib/sorcery/controller/submodules/external/protocols/oauth1.rb +0 -46
  121. data/lib/sorcery/controller/submodules/external/protocols/oauth2.rb +0 -50
  122. data/lib/sorcery/controller/submodules/external/providers/base.rb +0 -21
  123. data/lib/sorcery/controller/submodules/external/providers/facebook.rb +0 -99
  124. data/lib/sorcery/controller/submodules/external/providers/github.rb +0 -93
  125. data/lib/sorcery/controller/submodules/external/providers/google.rb +0 -92
  126. data/lib/sorcery/controller/submodules/external/providers/linkedin.rb +0 -103
  127. data/lib/sorcery/controller/submodules/external/providers/liveid.rb +0 -93
  128. data/lib/sorcery/controller/submodules/external/providers/twitter.rb +0 -94
  129. data/lib/sorcery/controller/submodules/external/providers/vk.rb +0 -101
  130. data/lib/sorcery/controller/submodules/external/providers/xing.rb +0 -98
  131. data/lib/sorcery/model/adapters/active_record.rb +0 -49
  132. data/lib/sorcery/model/adapters/mongo_mapper.rb +0 -56
  133. data/lib/sorcery/model/adapters/mongoid.rb +0 -88
  134. data/lib/sorcery/test_helpers/rails.rb +0 -16
  135. data/lib/sorcery/test_helpers.rb +0 -5
  136. data/spec/active_record/controller_activity_logging_spec.rb +0 -140
  137. data/spec/active_record/controller_brute_force_protection_spec.rb +0 -136
  138. data/spec/active_record/controller_http_basic_auth_spec.rb +0 -59
  139. data/spec/active_record/controller_oauth2_spec.rb +0 -417
  140. data/spec/active_record/controller_oauth_spec.rb +0 -212
  141. data/spec/active_record/controller_remember_me_spec.rb +0 -96
  142. data/spec/active_record/controller_session_timeout_spec.rb +0 -55
  143. data/spec/active_record/controller_spec.rb +0 -182
  144. data/spec/active_record/integration_spec.rb +0 -23
  145. data/spec/mongo_mapper/controller_spec.rb +0 -175
  146. data/spec/mongoid/controller_activity_logging_spec.rb +0 -111
  147. data/spec/mongoid/controller_spec.rb +0 -186
  148. data/spec/rails_app/public/404.html +0 -26
  149. data/spec/rails_app/public/422.html +0 -26
  150. data/spec/rails_app/public/500.html +0 -26
  151. data/spec/rails_app/public/favicon.ico +0 -0
  152. data/spec/rails_app/public/images/rails.png +0 -0
  153. data/spec/rails_app/public/javascripts/application.js +0 -2
  154. data/spec/rails_app/public/javascripts/controls.js +0 -965
  155. data/spec/rails_app/public/javascripts/dragdrop.js +0 -974
  156. data/spec/rails_app/public/javascripts/effects.js +0 -1123
  157. data/spec/rails_app/public/javascripts/prototype.js +0 -6001
  158. data/spec/rails_app/public/javascripts/rails.js +0 -175
  159. data/spec/rails_app/public/robots.txt +0 -5
  160. data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
  161. data/spec/shared_examples/controller_oauth2_shared_examples.rb +0 -56
  162. data/spec/shared_examples/controller_oauth_shared_examples.rb +0 -69
  163. /data/lib/sorcery/{controller/submodules/external/protocols → protocols}/certs/ca-bundle.crt +0 -0
@@ -0,0 +1,96 @@
1
+ # Each class which calls 'activate_sorcery!' receives an instance of this class.
2
+ # Every submodule which gets loaded may add accessors to this class so that all
3
+ # options will be configured from a single place.
4
+ module Sorcery
5
+ module Model
6
+ class Config
7
+
8
+ attr_accessor :username_attribute_names, # change default username attribute, for example, to use :email
9
+ # as the login.
10
+
11
+ :password_attribute_name, # change *virtual* password attribute, the one which is used
12
+ # until an encrypted one is generated.
13
+
14
+ :email_attribute_name, # change default email attribute.
15
+
16
+ :downcase_username_before_authenticating, # downcase the username before trying to authenticate, default is false
17
+
18
+ :crypted_password_attribute_name, # change default crypted_password attribute.
19
+ :salt_join_token, # what pattern to use to join the password with the salt
20
+ :salt_attribute_name, # change default salt attribute.
21
+ :stretches, # how many times to apply encryption to the password.
22
+ :encryption_key, # encryption key used to encrypt reversible encryptions such as
23
+ # AES256.
24
+
25
+ :subclasses_inherit_config, # make this configuration inheritable for subclasses. Useful for
26
+ # ActiveRecord's STI.
27
+
28
+ :submodules, # configured in config/application.rb
29
+ :before_authenticate, # an array of method names to call before authentication
30
+ # completes. used internally.
31
+
32
+ :after_config # an array of method names to call after configuration by user.
33
+ # used internally.
34
+
35
+ attr_reader :encryption_provider, # change default encryption_provider.
36
+ :custom_encryption_provider, # use an external encryption class.
37
+ :encryption_algorithm # encryption algorithm name. See 'encryption_algorithm=' below
38
+ # for available options.
39
+
40
+ def initialize
41
+ @defaults = {
42
+ :@submodules => [],
43
+ :@username_attribute_names => [:email],
44
+ :@password_attribute_name => :password,
45
+ :@downcase_username_before_authenticating => false,
46
+ :@email_attribute_name => :email,
47
+ :@crypted_password_attribute_name => :crypted_password,
48
+ :@encryption_algorithm => :bcrypt,
49
+ :@encryption_provider => CryptoProviders::BCrypt,
50
+ :@custom_encryption_provider => nil,
51
+ :@encryption_key => nil,
52
+ :@salt_join_token => "",
53
+ :@salt_attribute_name => :salt,
54
+ :@stretches => nil,
55
+ :@subclasses_inherit_config => false,
56
+ :@before_authenticate => [],
57
+ :@after_config => []
58
+ }
59
+ reset!
60
+ end
61
+
62
+ # Resets all configuration options to their default values.
63
+ def reset!
64
+ @defaults.each do |k,v|
65
+ instance_variable_set(k,v)
66
+ end
67
+ end
68
+
69
+ def username_attribute_names=(fields)
70
+ @username_attribute_names = fields.kind_of?(Array) ? fields : [fields]
71
+ end
72
+
73
+ def custom_encryption_provider=(provider)
74
+ @custom_encryption_provider = @encryption_provider = provider
75
+ end
76
+
77
+ def encryption_algorithm=(algo)
78
+ @encryption_algorithm = algo
79
+ @encryption_provider = case @encryption_algorithm.to_sym
80
+ when :none then nil
81
+ when :md5 then CryptoProviders::MD5
82
+ when :sha1 then CryptoProviders::SHA1
83
+ when :sha256 then CryptoProviders::SHA256
84
+ when :sha512 then CryptoProviders::SHA512
85
+ when :aes256 then CryptoProviders::AES256
86
+ when :bcrypt then CryptoProviders::BCrypt
87
+ when :custom then @custom_encryption_provider
88
+ else raise ArgumentError.new("Encryption algorithm supplied, #{algo}, is invalid")
89
+ end
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+ end
96
+
@@ -3,22 +3,23 @@ module Sorcery
3
3
  module Submodules
4
4
  # This submodule keeps track of events such as login, logout, and last activity time, per user.
5
5
  # It helps in estimating which users are active now in the site.
6
- # This cannot be determined absolutely because a user might be reading a page without clicking anything
6
+ # This cannot be determined absolutely because a user might be reading a page without clicking anything
7
7
  # for a while.
8
8
  # This is the model part of the submodule, which provides configuration options.
9
9
  module ActivityLogging
10
10
  def self.included(base)
11
11
  base.extend(ClassMethods)
12
+ base.send(:include, InstanceMethods)
12
13
 
13
14
  base.sorcery_config.class_eval do
14
15
  attr_accessor :last_login_at_attribute_name, # last login attribute name.
15
16
  :last_logout_at_attribute_name, # last logout attribute name.
16
17
  :last_activity_at_attribute_name, # last activity attribute name.
17
18
  :last_login_from_ip_address_name, # last activity login source
18
- :activity_timeout # how long since last activity is
19
+ :activity_timeout # how long since last activity is
19
20
  #the user defined logged out?
20
21
  end
21
-
22
+
22
23
  base.sorcery_config.instance_eval do
23
24
  @defaults.merge!(:@last_login_at_attribute_name => :last_login_at,
24
25
  :@last_logout_at_attribute_name => :last_logout_at,
@@ -28,23 +29,39 @@ module Sorcery
28
29
  reset!
29
30
  end
30
31
 
31
- base.sorcery_config.after_config << :define_activity_logging_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
32
+ base.sorcery_config.after_config << :define_activity_logging_fields
33
+ end
34
+
35
+ module InstanceMethods
36
+ def set_last_login_at(time)
37
+ sorcery_adapter.update_attribute(sorcery_config.last_login_at_attribute_name, time)
38
+ end
39
+
40
+ def set_last_logout_at(time)
41
+ sorcery_adapter.update_attribute(sorcery_config.last_logout_at_attribute_name, time)
42
+ end
43
+
44
+ def set_last_activity_at(time)
45
+ sorcery_adapter.update_attribute(sorcery_config.last_activity_at_attribute_name, time)
46
+ end
47
+
48
+ def set_last_ip_addess(ip_address)
49
+ sorcery_adapter.update_attribute(sorcery_config.last_login_from_ip_address_name, ip_address)
50
+ end
32
51
  end
33
-
52
+
34
53
  module ClassMethods
35
54
  # get all users with last_activity within timeout
36
55
  def current_users
37
- config = sorcery_config
38
- get_current_users
56
+ sorcery_adapter.get_current_users
39
57
  end
40
58
 
41
59
  protected
42
-
43
- def define_activity_logging_mongoid_fields
44
- field sorcery_config.last_login_at_attribute_name, :type => Time
45
- field sorcery_config.last_logout_at_attribute_name, :type => Time
46
- field sorcery_config.last_activity_at_attribute_name, :type => Time
47
- field sorcery_config.last_login_from_ip_address_name, :type => String
60
+ def define_activity_logging_fields
61
+ sorcery_adapter.define_field sorcery_config.last_login_at_attribute_name, Time
62
+ sorcery_adapter.define_field sorcery_config.last_logout_at_attribute_name, Time
63
+ sorcery_adapter.define_field sorcery_config.last_activity_at_attribute_name, Time
64
+ sorcery_adapter.define_field sorcery_config.last_login_from_ip_address_name, String
48
65
  end
49
66
  end
50
67
  end
@@ -35,10 +35,7 @@ module Sorcery
35
35
  end
36
36
 
37
37
  base.sorcery_config.before_authenticate << :prevent_locked_user_login
38
- base.sorcery_config.after_config << :define_brute_force_protection_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
39
- if defined?(MongoMapper) and base.ancestors.include?(MongoMapper::Document)
40
- base.sorcery_config.after_config << :define_brute_force_protection_mongo_mapper_fields
41
- end
38
+ base.sorcery_config.after_config << :define_brute_force_protection_fields
42
39
  base.extend(ClassMethods)
43
40
  base.send(:include, InstanceMethods)
44
41
  end
@@ -46,22 +43,16 @@ module Sorcery
46
43
  module ClassMethods
47
44
  def load_from_unlock_token(token)
48
45
  return nil if token.blank?
49
- user = find_by_sorcery_token(sorcery_config.unlock_token_attribute_name,token)
46
+ user = sorcery_adapter.find_by_token(sorcery_config.unlock_token_attribute_name,token)
50
47
  user
51
48
  end
52
49
 
53
50
  protected
54
51
 
55
- def define_brute_force_protection_mongoid_fields
56
- field sorcery_config.failed_logins_count_attribute_name, :type => Integer, :default => 0
57
- field sorcery_config.lock_expires_at_attribute_name, :type => Time
58
- field sorcery_config.unlock_token_attribute_name, :type => String
59
- end
60
-
61
- def define_brute_force_protection_mongo_mapper_fields
62
- key sorcery_config.failed_logins_count_attribute_name, Integer, :default => 0
63
- key sorcery_config.lock_expires_at_attribute_name, Time
64
- key sorcery_config.unlock_token_attribute_name, String
52
+ def define_brute_force_protection_fields
53
+ sorcery_adapter.define_field sorcery_config.failed_logins_count_attribute_name, Integer, :default => 0
54
+ sorcery_adapter.define_field sorcery_config.lock_expires_at_attribute_name, Time
55
+ sorcery_adapter.define_field sorcery_config.unlock_token_attribute_name, String
65
56
  end
66
57
  end
67
58
 
@@ -71,9 +62,12 @@ module Sorcery
71
62
  def register_failed_login!
72
63
  config = sorcery_config
73
64
  return if !unlocked?
74
- self.increment(config.failed_logins_count_attribute_name)
75
- self.update_many_attributes(config.failed_logins_count_attribute_name => self.send(config.failed_logins_count_attribute_name))
76
- self.lock! if self.send(config.failed_logins_count_attribute_name) >= config.consecutive_login_retries_amount_limit
65
+
66
+ sorcery_adapter.increment(config.failed_logins_count_attribute_name)
67
+
68
+ if self.send(config.failed_logins_count_attribute_name) >= config.consecutive_login_retries_amount_limit
69
+ lock!
70
+ end
77
71
  end
78
72
 
79
73
  # /!\
@@ -84,7 +78,11 @@ module Sorcery
84
78
  attributes = {config.lock_expires_at_attribute_name => nil,
85
79
  config.failed_logins_count_attribute_name => 0,
86
80
  config.unlock_token_attribute_name => nil}
87
- self.update_many_attributes(attributes)
81
+ sorcery_adapter.update_attributes(attributes)
82
+ end
83
+
84
+ def locked?
85
+ !unlocked?
88
86
  end
89
87
 
90
88
  protected
@@ -93,7 +91,7 @@ module Sorcery
93
91
  config = sorcery_config
94
92
  attributes = {config.lock_expires_at_attribute_name => Time.now.in_time_zone + config.login_lock_time_period,
95
93
  config.unlock_token_attribute_name => TemporaryToken.generate_random_token}
96
- self.update_many_attributes(attributes)
94
+ sorcery_adapter.update_attributes(attributes)
97
95
 
98
96
  unless config.unlock_token_mailer_disabled || config.unlock_token_mailer.nil?
99
97
  send_unlock_token_email!
@@ -106,7 +104,9 @@ module Sorcery
106
104
  end
107
105
 
108
106
  def send_unlock_token_email!
109
- generic_send_email(:unlock_token_email_method_name, :unlock_token_mailer) unless sorcery_config.unlock_token_email_method_name.nil?
107
+ return if sorcery_config.unlock_token_email_method_name.nil?
108
+
109
+ generic_send_email(:unlock_token_email_method_name, :unlock_token_mailer)
110
110
  end
111
111
 
112
112
  # Prevents a locked user from logging in, and unlocks users that expired their lock time.
@@ -8,7 +8,7 @@ module Sorcery
8
8
  # Socery assumes (read: requires) you will create external users in the same table where
9
9
  # you keep your regular users,
10
10
  # but that you will have a separate table for keeping their external authentication data,
11
- # and that that separate table has a few rows for each user, facebook and twitter
11
+ # and that that separate table has a few rows for each user, facebook and twitter
12
12
  # for example (a one-to-many relationship).
13
13
  #
14
14
  # External users will have a null crypted_password field, since we do not hold their password.
@@ -22,7 +22,7 @@ module Sorcery
22
22
  :provider_uid_attribute_name
23
23
 
24
24
  end
25
-
25
+
26
26
  base.sorcery_config.instance_eval do
27
27
  @defaults.merge!(:@authentications_class => nil,
28
28
  :@authentications_user_id_attribute_name => :user_id,
@@ -31,26 +31,70 @@ module Sorcery
31
31
 
32
32
  reset!
33
33
  end
34
-
34
+
35
35
  base.send(:include, InstanceMethods)
36
36
  base.extend(ClassMethods)
37
37
 
38
38
  end
39
-
39
+
40
40
  module ClassMethods
41
41
  # takes a provider and uid and finds a user by them.
42
42
  def load_from_provider(provider,uid)
43
43
  config = sorcery_config
44
- authentication = config.authentications_class.find_by_provider_and_uid(provider, uid)
45
- user = find(authentication.send(config.authentications_user_id_attribute_name)) if authentication
44
+ authentication = config.authentications_class.sorcery_adapter.find_by_oauth_credentials(provider, uid)
45
+ user = sorcery_adapter.find_by_id(authentication.send(config.authentications_user_id_attribute_name)) if authentication
46
+ end
47
+
48
+ def create_and_validate_from_provider(provider, uid, attrs)
49
+ user = new(attrs)
50
+ user.send(sorcery_config.authentications_class.to_s.downcase.pluralize).build(
51
+ sorcery_config.provider_uid_attribute_name => uid,
52
+ sorcery_config.provider_attribute_name => provider
53
+ )
54
+ saved = user.sorcery_adapter.save
55
+ [user, saved]
56
+ end
57
+
58
+ def create_from_provider(provider, uid, attrs)
59
+ user = new
60
+ attrs.each do |k,v|
61
+ user.send(:"#{k}=", v)
62
+ end
63
+
64
+ if block_given?
65
+ return false unless yield user
66
+ end
67
+
68
+ sorcery_adapter.transaction do
69
+ user.sorcery_adapter.save(:validate => false)
70
+ sorcery_config.authentications_class.create!(
71
+ sorcery_config.authentications_user_id_attribute_name => user.id,
72
+ sorcery_config.provider_attribute_name => provider,
73
+ sorcery_config.provider_uid_attribute_name => uid
74
+ )
75
+ end
76
+ user
46
77
  end
47
78
  end
48
-
79
+
49
80
  module InstanceMethods
81
+ def add_provider_to_user(provider, uid)
82
+ authentications = sorcery_config.authentications_class.name.underscore.pluralize
83
+ # first check to see if user has a particular authentication already
84
+ if sorcery_adapter.find_authentication_by_oauth_credentials(authentications, provider, uid).nil?
85
+ user = send(authentications).build(sorcery_config.provider_uid_attribute_name => uid,
86
+ sorcery_config.provider_attribute_name => provider)
87
+ user.sorcery_adapter.save(validate: false)
88
+ else
89
+ user = false
90
+ end
91
+
92
+ user
93
+ end
50
94
 
51
95
  end
52
-
96
+
53
97
  end
54
98
  end
55
99
  end
56
- end
100
+ end
@@ -1,7 +1,7 @@
1
1
  module Sorcery
2
2
  module Model
3
3
  module Submodules
4
- # The Remember Me submodule takes care of setting the user's cookie so that he will
4
+ # The Remember Me submodule takes care of setting the user's cookie so that he will
5
5
  # be automatically logged in to the site on every visit,
6
6
  # until the cookie expires.
7
7
  module RememberMe
@@ -12,7 +12,7 @@ module Sorcery
12
12
  :remember_me_for # how long in seconds to remember.
13
13
 
14
14
  end
15
-
15
+
16
16
  base.sorcery_config.instance_eval do
17
17
  @defaults.merge!(:@remember_me_token_attribute_name => :remember_me_token,
18
18
  :@remember_me_token_expires_at_attribute_name => :remember_me_token_expires_at,
@@ -20,47 +20,43 @@ module Sorcery
20
20
 
21
21
  reset!
22
22
  end
23
-
23
+
24
24
  base.send(:include, InstanceMethods)
25
+ base.sorcery_config.after_config << :define_remember_me_fields
25
26
 
26
- base.sorcery_config.after_config << :define_remember_me_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
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
-
31
27
  base.extend(ClassMethods)
32
28
  end
33
29
 
34
30
  module ClassMethods
35
31
  protected
36
32
 
37
- def define_remember_me_mongoid_fields
38
- field sorcery_config.remember_me_token_attribute_name, :type => String
39
- field sorcery_config.remember_me_token_expires_at_attribute_name, :type => Time
33
+ def define_remember_me_fields
34
+ sorcery_adapter.define_field sorcery_config.remember_me_token_attribute_name, String
35
+ sorcery_adapter.define_field sorcery_config.remember_me_token_expires_at_attribute_name, Time
40
36
  end
41
37
 
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
46
38
  end
47
39
 
48
40
  module InstanceMethods
49
41
  # You shouldn't really use this one yourself - it's called by the controller's 'remember_me!' method.
50
42
  def remember_me!
51
43
  config = sorcery_config
52
- self.update_many_attributes(config.remember_me_token_attribute_name => TemporaryToken.generate_random_token,
44
+ self.sorcery_adapter.update_attributes(config.remember_me_token_attribute_name => TemporaryToken.generate_random_token,
53
45
  config.remember_me_token_expires_at_attribute_name => Time.now.in_time_zone + config.remember_me_for)
54
46
  end
55
-
47
+
48
+ def has_remember_me_token?
49
+ self.send(sorcery_config.remember_me_token_attribute_name).present?
50
+ end
51
+
56
52
  # You shouldn't really use this one yourself - it's called by the controller's 'forget_me!' method.
57
53
  def forget_me!
58
54
  config = sorcery_config
59
- self.update_many_attributes(config.remember_me_token_attribute_name => nil,
55
+ self.sorcery_adapter.update_attributes(config.remember_me_token_attribute_name => nil,
60
56
  config.remember_me_token_expires_at_attribute_name => nil)
61
57
  end
62
58
  end
63
59
  end
64
60
  end
65
61
  end
66
- end
62
+ end
@@ -9,14 +9,14 @@ module Sorcery
9
9
  # he will be able to reset his password via a form.
10
10
  #
11
11
  # When using this submodule, supplying a mailer is mandatory.
12
- module ResetPassword
12
+ module ResetPassword
13
13
  def self.included(base)
14
14
  base.sorcery_config.class_eval do
15
15
  attr_accessor :reset_password_token_attribute_name, # reset password code attribute name.
16
16
  :reset_password_token_expires_at_attribute_name, # expires at attribute name.
17
17
  :reset_password_email_sent_at_attribute_name, # when was email sent, used for hammering
18
18
  # protection.
19
-
19
+
20
20
  :reset_password_mailer, # mailer class. Needed.
21
21
 
22
22
  :reset_password_mailer_disabled, # when true sorcery will not automatically
@@ -25,15 +25,15 @@ module Sorcery
25
25
 
26
26
  :reset_password_email_method_name, # reset password email method on your
27
27
  # mailer class.
28
-
28
+
29
29
  :reset_password_expiration_period, # how many seconds before the reset request
30
30
  # expires. nil for never expires.
31
-
31
+
32
32
  :reset_password_time_between_emails # hammering protection, how long to wait
33
33
  # before allowing another email to be sent.
34
34
 
35
35
  end
36
-
36
+
37
37
  base.sorcery_config.instance_eval do
38
38
  @defaults.merge!(:@reset_password_token_attribute_name => :reset_password_token,
39
39
  :@reset_password_token_expires_at_attribute_name => :reset_password_token_expires_at,
@@ -50,15 +50,12 @@ module Sorcery
50
50
  base.extend(ClassMethods)
51
51
 
52
52
  base.sorcery_config.after_config << :validate_mailer_defined
53
- base.sorcery_config.after_config << :define_reset_password_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
54
- if defined?(MongoMapper) and base.ancestors.include?(MongoMapper::Document)
55
- base.sorcery_config.after_config << :define_reset_password_mongo_mapper_fields
56
- end
53
+ base.sorcery_config.after_config << :define_reset_password_fields
57
54
 
58
55
  base.send(:include, InstanceMethods)
59
56
 
60
57
  end
61
-
58
+
62
59
  module ClassMethods
63
60
  # Find user by token, also checks for expiration.
64
61
  # Returns the user if token found and is valid.
@@ -67,9 +64,9 @@ module Sorcery
67
64
  token_expiration_date_attr = @sorcery_config.reset_password_token_expires_at_attribute_name
68
65
  load_from_token(token, token_attr_name, token_expiration_date_attr)
69
66
  end
70
-
67
+
71
68
  protected
72
-
69
+
73
70
  # This submodule requires the developer to define his own mailer class to be used by it
74
71
  # when reset_password_mailer_disabled is false
75
72
  def validate_mailer_defined
@@ -77,43 +74,45 @@ module Sorcery
77
74
  raise ArgumentError, msg if @sorcery_config.reset_password_mailer == nil and @sorcery_config.reset_password_mailer_disabled == false
78
75
  end
79
76
 
80
- def define_reset_password_mongoid_fields
81
- field sorcery_config.reset_password_token_attribute_name, :type => String
82
- field sorcery_config.reset_password_token_expires_at_attribute_name, :type => Time
83
- field sorcery_config.reset_password_email_sent_at_attribute_name, :type => Time
84
- end
85
-
86
- def define_reset_password_mongo_mapper_fields
87
- key sorcery_config.reset_password_token_attribute_name, String
88
- key sorcery_config.reset_password_token_expires_at_attribute_name, Time
89
- key sorcery_config.reset_password_email_sent_at_attribute_name, Time
77
+ def define_reset_password_fields
78
+ sorcery_adapter.define_field sorcery_config.reset_password_token_attribute_name, String
79
+ sorcery_adapter.define_field sorcery_config.reset_password_token_expires_at_attribute_name, Time
80
+ sorcery_adapter.define_field sorcery_config.reset_password_email_sent_at_attribute_name, Time
90
81
  end
82
+
91
83
  end
92
-
84
+
93
85
  module InstanceMethods
94
- # generates a reset code with expiration and sends an email to the user.
95
- def deliver_reset_password_instructions!
86
+ # generates a reset code with expiration
87
+ def generate_reset_password_token!
96
88
  config = sorcery_config
97
- # hammering protection
98
- return false if config.reset_password_time_between_emails && self.send(config.reset_password_email_sent_at_attribute_name) && self.send(config.reset_password_email_sent_at_attribute_name) > config.reset_password_time_between_emails.ago.utc
99
89
  attributes = {config.reset_password_token_attribute_name => TemporaryToken.generate_random_token,
100
90
  config.reset_password_email_sent_at_attribute_name => Time.now.in_time_zone}
101
91
  attributes[config.reset_password_token_expires_at_attribute_name] = Time.now.in_time_zone + config.reset_password_expiration_period if config.reset_password_expiration_period
102
- self.class.transaction do
103
- self.update_many_attributes(attributes)
104
- send_reset_password_email! unless sorcery_config.reset_password_mailer_disabled
92
+
93
+ self.sorcery_adapter.update_attributes(attributes)
94
+ end
95
+
96
+ # generates a reset code with expiration and sends an email to the user.
97
+ def deliver_reset_password_instructions!
98
+ config = sorcery_config
99
+ # hammering protection
100
+ return false if config.reset_password_time_between_emails.present? && self.send(config.reset_password_email_sent_at_attribute_name) && self.send(config.reset_password_email_sent_at_attribute_name) > config.reset_password_time_between_emails.seconds.ago.utc
101
+ self.class.sorcery_adapter.transaction do
102
+ generate_reset_password_token!
103
+ send_reset_password_email! unless config.reset_password_mailer_disabled
105
104
  end
106
105
  end
107
-
106
+
108
107
  # Clears token and tries to update the new password for the user.
109
108
  def change_password!(new_password)
110
109
  clear_reset_password_token
111
110
  self.send(:"#{sorcery_config.password_attribute_name}=", new_password)
112
- save
111
+ sorcery_adapter.save
113
112
  end
114
113
 
115
114
  protected
116
-
115
+
117
116
  def send_reset_password_email!
118
117
  generic_send_email(:reset_password_email_method_name, :reset_password_mailer)
119
118
  end
@@ -125,7 +124,7 @@ module Sorcery
125
124
  self.send(:"#{config.reset_password_token_expires_at_attribute_name}=", nil) if config.reset_password_expiration_period
126
125
  end
127
126
  end
128
-
127
+
129
128
  end
130
129
  end
131
130
  end