sorcery 0.8.6 → 0.9.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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +75 -14
  4. data/CHANGELOG.md +32 -1
  5. data/Gemfile +1 -0
  6. data/README.md +138 -86
  7. data/gemfiles/active_record-rails40.gemfile +7 -0
  8. data/gemfiles/active_record-rails41.gemfile +3 -2
  9. data/gemfiles/mongo_mapper-rails40.gemfile +9 -0
  10. data/gemfiles/mongo_mapper-rails41.gemfile +2 -1
  11. data/gemfiles/mongoid-rails40.gemfile +9 -0
  12. data/gemfiles/mongoid-rails41.gemfile +3 -5
  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 +36 -10
  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 +9 -29
  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 +5 -64
  32. data/lib/sorcery/model/config.rb +96 -0
  33. data/lib/sorcery/model/submodules/activity_logging.rb +29 -36
  34. data/lib/sorcery/model/submodules/brute_force_protection.rb +21 -37
  35. data/lib/sorcery/model/submodules/external.rb +53 -9
  36. data/lib/sorcery/model/submodules/remember_me.rb +12 -31
  37. data/lib/sorcery/model/submodules/reset_password.rb +21 -39
  38. data/lib/sorcery/model/submodules/user_activation.rb +21 -63
  39. data/lib/sorcery/model/temporary_token.rb +4 -4
  40. data/lib/sorcery/model.rb +47 -175
  41. data/lib/sorcery/providers/base.rb +11 -0
  42. data/lib/sorcery/providers/facebook.rb +16 -5
  43. data/lib/sorcery/providers/github.rb +11 -2
  44. data/lib/sorcery/providers/google.rb +1 -1
  45. data/lib/sorcery/providers/heroku.rb +57 -0
  46. data/lib/sorcery/providers/jira.rb +77 -0
  47. data/lib/sorcery/providers/linkedin.rb +1 -1
  48. data/lib/sorcery/providers/liveid.rb +1 -1
  49. data/lib/sorcery/providers/salesforce.rb +50 -0
  50. data/lib/sorcery/providers/twitter.rb +1 -1
  51. data/lib/sorcery/providers/vk.rb +6 -4
  52. data/lib/sorcery/providers/xing.rb +2 -2
  53. data/lib/sorcery/test_helpers/internal.rb +7 -3
  54. data/lib/sorcery/test_helpers/rails/controller.rb +5 -1
  55. data/lib/sorcery/version.rb +3 -0
  56. data/lib/sorcery.rb +75 -43
  57. data/sorcery.gemspec +6 -2
  58. data/spec/active_record/user_activity_logging_spec.rb +9 -0
  59. data/spec/controllers/controller_activity_logging_spec.rb +124 -0
  60. data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
  61. data/spec/{active_record → controllers}/controller_http_basic_auth_spec.rb +14 -11
  62. data/spec/{active_record → controllers}/controller_oauth2_spec.rb +151 -64
  63. data/spec/{active_record → controllers}/controller_oauth_spec.rb +94 -70
  64. data/spec/{active_record → controllers}/controller_remember_me_spec.rb +32 -12
  65. data/spec/{active_record → controllers}/controller_session_timeout_spec.rb +15 -5
  66. data/spec/{shared_examples/controller_shared_examples.rb → controllers/controller_spec.rb} +34 -19
  67. data/spec/{datamapper → data_mapper}/user_activation_spec.rb +1 -1
  68. data/spec/data_mapper/user_activity_logging_spec.rb +14 -0
  69. data/spec/{datamapper → data_mapper}/user_brute_force_protection_spec.rb +1 -1
  70. data/spec/{datamapper → data_mapper}/user_oauth_spec.rb +1 -1
  71. data/spec/{datamapper → data_mapper}/user_remember_me_spec.rb +1 -1
  72. data/spec/{datamapper → data_mapper}/user_reset_password_spec.rb +1 -1
  73. data/spec/{datamapper → data_mapper}/user_spec.rb +1 -1
  74. data/spec/mongoid/user_spec.rb +13 -0
  75. data/spec/orm/active_record.rb +12 -0
  76. data/spec/orm/{datamapper.rb → data_mapper.rb} +16 -2
  77. data/spec/orm/mongo_mapper.rb +0 -1
  78. data/spec/orm/mongoid.rb +4 -0
  79. data/spec/rails_app/app/controllers/sorcery_controller.rb +62 -1
  80. data/spec/rails_app/app/mongo_mapper/user.rb +2 -0
  81. data/spec/rails_app/config/routes.rb +9 -0
  82. data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +2 -2
  83. data/spec/shared_examples/user_activation_shared_examples.rb +7 -7
  84. data/spec/shared_examples/user_activity_logging_shared_examples.rb +73 -5
  85. data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +127 -9
  86. data/spec/shared_examples/user_oauth_shared_examples.rb +3 -6
  87. data/spec/shared_examples/user_remember_me_shared_examples.rb +6 -3
  88. data/spec/shared_examples/user_reset_password_shared_examples.rb +10 -10
  89. data/spec/shared_examples/user_shared_examples.rb +146 -46
  90. data/spec/spec_helper.rb +7 -22
  91. metadata +36 -57
  92. data/Gemfile.rails4 +0 -22
  93. data/VERSION +0 -1
  94. data/lib/sorcery/model/adapters/active_record.rb +0 -54
  95. data/lib/sorcery/model/adapters/datamapper.rb +0 -123
  96. data/lib/sorcery/model/adapters/mongo_mapper.rb +0 -60
  97. data/lib/sorcery/model/adapters/mongoid.rb +0 -88
  98. data/lib/sorcery/test_helpers/rails.rb +0 -7
  99. data/spec/active_record/controller_activity_logging_spec.rb +0 -29
  100. data/spec/active_record/controller_brute_force_protection_spec.rb +0 -158
  101. data/spec/active_record/controller_spec.rb +0 -8
  102. data/spec/active_record/integration_spec.rb +0 -23
  103. data/spec/datamapper/controller_activity_logging_spec.rb +0 -17
  104. data/spec/datamapper/controller_spec.rb +0 -8
  105. data/spec/datamapper/user_activity_logging_spec.rb +0 -9
  106. data/spec/mongo_mapper/controller_spec.rb +0 -8
  107. data/spec/mongoid/controller_activity_logging_spec.rb +0 -16
  108. data/spec/mongoid/controller_spec.rb +0 -8
  109. data/spec/rails_app/public/404.html +0 -26
  110. data/spec/rails_app/public/422.html +0 -26
  111. data/spec/rails_app/public/500.html +0 -26
  112. data/spec/rails_app/public/favicon.ico +0 -0
  113. data/spec/rails_app/public/images/rails.png +0 -0
  114. data/spec/rails_app/public/javascripts/application.js +0 -2
  115. data/spec/rails_app/public/javascripts/controls.js +0 -965
  116. data/spec/rails_app/public/javascripts/dragdrop.js +0 -974
  117. data/spec/rails_app/public/javascripts/effects.js +0 -1123
  118. data/spec/rails_app/public/javascripts/prototype.js +0 -6001
  119. data/spec/rails_app/public/javascripts/rails.js +0 -175
  120. data/spec/rails_app/public/robots.txt +0 -5
  121. data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
  122. data/spec/shared_examples/controller_activity_logging_shared_examples.rb +0 -125
  123. data/spec/shared_examples/controller_oauth2_shared_examples.rb +0 -52
  124. data/spec/shared_examples/controller_oauth_shared_examples.rb +0 -62
  125. /data/spec/rails_app/app/{datamapper → data_mapper}/authentication.rb +0 -0
  126. /data/spec/rails_app/app/{datamapper → data_mapper}/user.rb +0 -0
@@ -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,47 +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
- if defined?(DataMapper) and base.ancestors.include?(DataMapper::Resource)
33
- # NOTE raise exception if data-store is not supported
34
- unless base.repository.adapter.is_a?(DataMapper::Adapters::MysqlAdapter)
35
- raise 'Unsupported DataMapper Adapter'
36
- end
37
- base.sorcery_config.after_config << :define_activity_logging_datamapper_fields
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)
38
50
  end
39
51
  end
40
-
52
+
41
53
  module ClassMethods
42
54
  # get all users with last_activity within timeout
43
55
  def current_users
44
- config = sorcery_config
45
- get_current_users
56
+ sorcery_adapter.get_current_users
46
57
  end
47
58
 
48
59
  protected
49
-
50
- def define_activity_logging_mongoid_fields
51
- field sorcery_config.last_login_at_attribute_name, :type => Time
52
- field sorcery_config.last_logout_at_attribute_name, :type => Time
53
- field sorcery_config.last_activity_at_attribute_name, :type => Time
54
- field sorcery_config.last_login_from_ip_address_name, :type => String
55
- end
56
-
57
- def define_activity_logging_datamapper_fields
58
- property sorcery_config.last_login_at_attribute_name, Time
59
- property sorcery_config.last_logout_at_attribute_name, Time
60
- property sorcery_config.last_activity_at_attribute_name, Time
61
- property sorcery_config.last_login_from_ip_address_name, String
62
- # Workaround local timezone retrieval problem NOTE dm-core issue #193
63
- [sorcery_config.last_login_at_attribute_name,
64
- sorcery_config.last_logout_at_attribute_name,
65
- sorcery_config.last_activity_at_attribute_name].each do |sym|
66
- alias_method "orig_#{sym}", sym
67
- define_method(sym) do
68
- t = send("orig_#{sym}")
69
- t && Time.new(t.year, t.month, t.day, t.hour, t.min, t.sec, 0)
70
- end
71
- end
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
72
65
  end
73
66
  end
74
67
  end
@@ -35,13 +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
42
- if defined?(DataMapper) and base.ancestors.include?(DataMapper::Resource)
43
- base.sorcery_config.after_config << :define_brute_force_protection_datamapper_fields
44
- end
38
+ base.sorcery_config.after_config << :define_brute_force_protection_fields
45
39
  base.extend(ClassMethods)
46
40
  base.send(:include, InstanceMethods)
47
41
  end
@@ -49,35 +43,16 @@ module Sorcery
49
43
  module ClassMethods
50
44
  def load_from_unlock_token(token)
51
45
  return nil if token.blank?
52
- 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)
53
47
  user
54
48
  end
55
49
 
56
50
  protected
57
51
 
58
- def define_brute_force_protection_mongoid_fields
59
- field sorcery_config.failed_logins_count_attribute_name, :type => Integer, :default => 0
60
- field sorcery_config.lock_expires_at_attribute_name, :type => Time
61
- field sorcery_config.unlock_token_attribute_name, :type => String
62
- end
63
-
64
- def define_brute_force_protection_mongo_mapper_fields
65
- key sorcery_config.failed_logins_count_attribute_name, Integer, :default => 0
66
- key sorcery_config.lock_expires_at_attribute_name, Time
67
- key sorcery_config.unlock_token_attribute_name, String
68
- end
69
-
70
- def define_brute_force_protection_datamapper_fields
71
- property sorcery_config.failed_logins_count_attribute_name, Integer, :default => 0
72
- property sorcery_config.lock_expires_at_attribute_name, Time
73
- property sorcery_config.unlock_token_attribute_name, String
74
- [sorcery_config.lock_expires_at_attribute_name].each do |sym|
75
- alias_method "orig_#{sym}", sym
76
- define_method(sym) do
77
- t = send("orig_#{sym}")
78
- t && Time.new(t.year, t.month, t.day, t.hour, t.min, t.sec, 0)
79
- end
80
- end
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
81
56
  end
82
57
  end
83
58
 
@@ -87,9 +62,12 @@ module Sorcery
87
62
  def register_failed_login!
88
63
  config = sorcery_config
89
64
  return if !unlocked?
90
- self.increment(config.failed_logins_count_attribute_name)
91
- self.update_many_attributes(config.failed_logins_count_attribute_name => self.send(config.failed_logins_count_attribute_name))
92
- 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
93
71
  end
94
72
 
95
73
  # /!\
@@ -100,7 +78,11 @@ module Sorcery
100
78
  attributes = {config.lock_expires_at_attribute_name => nil,
101
79
  config.failed_logins_count_attribute_name => 0,
102
80
  config.unlock_token_attribute_name => nil}
103
- self.update_many_attributes(attributes)
81
+ sorcery_adapter.update_attributes(attributes)
82
+ end
83
+
84
+ def locked?
85
+ !unlocked?
104
86
  end
105
87
 
106
88
  protected
@@ -109,7 +91,7 @@ module Sorcery
109
91
  config = sorcery_config
110
92
  attributes = {config.lock_expires_at_attribute_name => Time.now.in_time_zone + config.login_lock_time_period,
111
93
  config.unlock_token_attribute_name => TemporaryToken.generate_random_token}
112
- self.update_many_attributes(attributes)
94
+ sorcery_adapter.update_attributes(attributes)
113
95
 
114
96
  unless config.unlock_token_mailer_disabled || config.unlock_token_mailer.nil?
115
97
  send_unlock_token_email!
@@ -122,7 +104,9 @@ module Sorcery
122
104
  end
123
105
 
124
106
  def send_unlock_token_email!
125
- 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)
126
110
  end
127
111
 
128
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
@@ -22,14 +22,7 @@ module Sorcery
22
22
  end
23
23
 
24
24
  base.send(:include, InstanceMethods)
25
-
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
- if defined?(DataMapper) and base.ancestors.include?(DataMapper::Resource)
31
- base.sorcery_config.after_config << :define_remember_me_datamapper_fields
32
- end
25
+ base.sorcery_config.after_config << :define_remember_me_fields
33
26
 
34
27
  base.extend(ClassMethods)
35
28
  end
@@ -37,41 +30,29 @@ module Sorcery
37
30
  module ClassMethods
38
31
  protected
39
32
 
40
- def define_remember_me_mongoid_fields
41
- field sorcery_config.remember_me_token_attribute_name, :type => String
42
- field sorcery_config.remember_me_token_expires_at_attribute_name, :type => Time
43
- end
44
-
45
- def define_remember_me_mongo_mapper_fields
46
- key sorcery_config.remember_me_token_attribute_name, String
47
- key sorcery_config.remember_me_token_expires_at_attribute_name, 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
48
36
  end
49
37
 
50
- def define_remember_me_datamapper_fields
51
- property sorcery_config.remember_me_token_attribute_name, String
52
- property sorcery_config.remember_me_token_expires_at_attribute_name, Time
53
- [sorcery_config.remember_me_token_expires_at_attribute_name].each do |sym|
54
- alias_method "orig_#{sym}", sym
55
- define_method(sym) do
56
- t = send("orig_#{sym}")
57
- t && Time.new(t.year, t.month, t.day, t.hour, t.min, t.sec, 0)
58
- end
59
- end
60
- end
61
38
  end
62
39
 
63
40
  module InstanceMethods
64
41
  # You shouldn't really use this one yourself - it's called by the controller's 'remember_me!' method.
65
42
  def remember_me!
66
43
  config = sorcery_config
67
- 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,
68
45
  config.remember_me_token_expires_at_attribute_name => Time.now.in_time_zone + config.remember_me_for)
69
46
  end
70
-
47
+
48
+ def has_remember_me_token?
49
+ self.send(sorcery_config.remember_me_token_attribute_name).present?
50
+ end
51
+
71
52
  # You shouldn't really use this one yourself - it's called by the controller's 'forget_me!' method.
72
53
  def forget_me!
73
54
  config = sorcery_config
74
- self.update_many_attributes(config.remember_me_token_attribute_name => nil,
55
+ self.sorcery_adapter.update_attributes(config.remember_me_token_attribute_name => nil,
75
56
  config.remember_me_token_expires_at_attribute_name => nil)
76
57
  end
77
58
  end
@@ -50,13 +50,7 @@ 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
57
- if defined?(DataMapper) and base.ancestors.include?(DataMapper::Resource)
58
- base.sorcery_config.after_config << :define_reset_password_datamapper_fields
59
- end
53
+ base.sorcery_config.after_config << :define_reset_password_fields
60
54
 
61
55
  base.send(:include, InstanceMethods)
62
56
 
@@ -80,45 +74,33 @@ module Sorcery
80
74
  raise ArgumentError, msg if @sorcery_config.reset_password_mailer == nil and @sorcery_config.reset_password_mailer_disabled == false
81
75
  end
82
76
 
83
- def define_reset_password_mongoid_fields
84
- field sorcery_config.reset_password_token_attribute_name, :type => String
85
- field sorcery_config.reset_password_token_expires_at_attribute_name, :type => Time
86
- field sorcery_config.reset_password_email_sent_at_attribute_name, :type => 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
87
81
  end
88
82
 
89
- def define_reset_password_mongo_mapper_fields
90
- key sorcery_config.reset_password_token_attribute_name, String
91
- key sorcery_config.reset_password_token_expires_at_attribute_name, Time
92
- key sorcery_config.reset_password_email_sent_at_attribute_name, Time
93
- end
94
-
95
- def define_reset_password_datamapper_fields
96
- property sorcery_config.reset_password_token_attribute_name, String
97
- property sorcery_config.reset_password_token_expires_at_attribute_name, Time
98
- property sorcery_config.reset_password_email_sent_at_attribute_name, Time
99
- [sorcery_config.reset_password_token_expires_at_attribute_name,
100
- sorcery_config.reset_password_email_sent_at_attribute_name].each do |sym|
101
- alias_method "orig_#{sym}", sym
102
- define_method(sym) do
103
- t = send("orig_#{sym}")
104
- t && Time.new(t.year, t.month, t.day, t.hour, t.min, t.sec, 0)
105
- end
106
- end
107
- end
108
83
  end
109
84
 
110
85
  module InstanceMethods
111
- # generates a reset code with expiration and sends an email to the user.
112
- def deliver_reset_password_instructions!
86
+ # generates a reset code with expiration
87
+ def generate_reset_password_token!
113
88
  config = sorcery_config
114
- # hammering protection
115
- 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
116
89
  attributes = {config.reset_password_token_attribute_name => TemporaryToken.generate_random_token,
117
90
  config.reset_password_email_sent_at_attribute_name => Time.now.in_time_zone}
118
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
119
- self.class.transaction do
120
- self.update_many_attributes(attributes)
121
- 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
122
104
  end
123
105
  end
124
106
 
@@ -126,11 +108,11 @@ module Sorcery
126
108
  def change_password!(new_password)
127
109
  clear_reset_password_token
128
110
  self.send(:"#{sorcery_config.password_attribute_name}=", new_password)
129
- sorcery_save
111
+ sorcery_adapter.save
130
112
  end
131
113
 
132
114
  protected
133
-
115
+
134
116
  def send_reset_password_email!
135
117
  generic_send_email(:reset_password_email_method_name, :reset_password_mailer)
136
118
  end
@@ -15,7 +15,7 @@ module Sorcery
15
15
  # (sent by email).
16
16
 
17
17
  :activation_token_expires_at_attribute_name, # the attribute name to hold activation code
18
- # expiration date.
18
+ # expiration date.
19
19
 
20
20
  :activation_token_expiration_period, # how many seconds before the activation code
21
21
  # expires. nil for never expires.
@@ -51,33 +51,14 @@ module Sorcery
51
51
  end
52
52
 
53
53
  base.class_eval do
54
- if defined?(DataMapper) && self.ancestors.include?(DataMapper::Resource)
55
- before :valid? do
56
- if self.send(sorcery_config.password_attribute_name).present?
57
- setup_activation
58
- end
59
- end
60
- after :create do
61
- if send_activation_needed_email?
62
- send_activation_needed_email!
63
- end
64
- end
65
- else
66
- # don't setup activation if no password supplied - this user is created automatically
67
- before_create :setup_activation, :if => Proc.new { |user| user.send(sorcery_config.password_attribute_name).present? }
68
- # don't send activation needed email if no crypted password created - this user is external (OAuth etc.)
69
- after_create :send_activation_needed_email!, :if => :send_activation_needed_email?
70
- end
54
+ # don't setup activation if no password supplied - this user is created automatically
55
+ sorcery_adapter.define_callback :before, :create, :setup_activation, :if => Proc.new { |user| user.send(sorcery_config.password_attribute_name).present? }
56
+ # don't send activation needed email if no crypted password created - this user is external (OAuth etc.)
57
+ sorcery_adapter.define_callback :after, :create, :send_activation_needed_email!, :if => :send_activation_needed_email?
71
58
  end
72
59
 
73
60
  base.sorcery_config.after_config << :validate_mailer_defined
74
- base.sorcery_config.after_config << :define_user_activation_mongoid_fields if defined?(Mongoid) and base.ancestors.include?(Mongoid::Document)
75
- if defined?(MongoMapper) and base.ancestors.include?(MongoMapper::Document)
76
- base.sorcery_config.after_config << :define_user_activation_mongo_mapper_fields
77
- end
78
- if defined?(DataMapper) and base.ancestors.include?(DataMapper::Resource)
79
- base.sorcery_config.after_config << :define_user_activation_datamapper_fields
80
- end
61
+ base.sorcery_config.after_config << :define_user_activation_fields
81
62
  base.sorcery_config.before_authenticate << :prevent_non_active_login
82
63
 
83
64
  base.extend(ClassMethods)
@@ -104,58 +85,35 @@ module Sorcery
104
85
  raise ArgumentError, msg if @sorcery_config.user_activation_mailer == nil and @sorcery_config.activation_mailer_disabled == false
105
86
  end
106
87
 
107
- def define_user_activation_mongoid_fields
108
- self.class_eval do
109
- field sorcery_config.activation_state_attribute_name, :type => String
110
- field sorcery_config.activation_token_attribute_name, :type => String
111
- field sorcery_config.activation_token_expires_at_attribute_name, :type => Time
112
- end
113
- end
114
-
115
- def define_user_activation_mongo_mapper_fields
88
+ def define_user_activation_fields
116
89
  self.class_eval do
117
- key sorcery_config.activation_state_attribute_name, String
118
- key sorcery_config.activation_token_attribute_name, String
119
- key sorcery_config.activation_token_expires_at_attribute_name, Time
120
- end
121
- end
122
-
123
- def define_user_activation_datamapper_fields
124
- self.class_eval do
125
- property sorcery_config.activation_state_attribute_name, String
126
- property sorcery_config.activation_token_attribute_name, String
127
- property sorcery_config.activation_token_expires_at_attribute_name, Time
128
- [sorcery_config.activation_token_expires_at_attribute_name].each do |sym|
129
- alias_method "orig_#{sym}", sym
130
- define_method(sym) do
131
- t = send("orig_#{sym}")
132
- t && Time.new(t.year, t.month, t.day, t.hour, t.min, t.sec, 0)
133
- end
134
- end
90
+ sorcery_adapter.define_field sorcery_config.activation_state_attribute_name, String
91
+ sorcery_adapter.define_field sorcery_config.activation_token_attribute_name, String
92
+ sorcery_adapter.define_field sorcery_config.activation_token_expires_at_attribute_name, Time
135
93
  end
136
94
  end
137
95
  end
138
96
 
139
97
  module InstanceMethods
98
+ def setup_activation
99
+ config = sorcery_config
100
+ generated_activation_token = TemporaryToken.generate_random_token
101
+ self.send(:"#{config.activation_token_attribute_name}=", generated_activation_token)
102
+ self.send(:"#{config.activation_state_attribute_name}=", "pending")
103
+ self.send(:"#{config.activation_token_expires_at_attribute_name}=", Time.now.in_time_zone + config.activation_token_expiration_period) if config.activation_token_expiration_period
104
+ end
105
+
140
106
  # clears activation code, sets the user as 'active' and optionaly sends a success email.
141
107
  def activate!
142
108
  config = sorcery_config
143
109
  self.send(:"#{config.activation_token_attribute_name}=", nil)
144
110
  self.send(:"#{config.activation_state_attribute_name}=", "active")
145
111
  send_activation_success_email! if send_activation_success_email?
146
- sorcery_save(:validate => false, :raise_on_failure => true)
112
+ sorcery_adapter.save(:validate => false, :raise_on_failure => true)
147
113
  end
148
114
 
149
115
  protected
150
116
 
151
- def setup_activation
152
- config = sorcery_config
153
- generated_activation_token = TemporaryToken.generate_random_token
154
- self.send(:"#{config.activation_token_attribute_name}=", generated_activation_token)
155
- self.send(:"#{config.activation_state_attribute_name}=", "pending")
156
- self.send(:"#{config.activation_token_expires_at_attribute_name}=", Time.now.in_time_zone + config.activation_token_expiration_period) if config.activation_token_expiration_period
157
- end
158
-
159
117
  # called automatically after user initial creation.
160
118
  def send_activation_needed_email!
161
119
  generic_send_email(:activation_needed_email_method_name, :user_activation_mailer)
@@ -164,14 +122,14 @@ module Sorcery
164
122
  def send_activation_success_email!
165
123
  generic_send_email(:activation_success_email_method_name, :user_activation_mailer)
166
124
  end
167
-
125
+
168
126
  def send_activation_success_email?
169
127
  !external? && (
170
128
  !(sorcery_config.activation_success_email_method_name.nil? ||
171
129
  sorcery_config.activation_mailer_disabled == true)
172
130
  )
173
131
  end
174
-
132
+
175
133
  def send_activation_needed_email?
176
134
  !external? && (
177
135
  !(sorcery_config.activation_needed_email_method_name.nil? ||
@@ -3,22 +3,22 @@ require 'securerandom'
3
3
  module Sorcery
4
4
  module Model
5
5
  # This module encapsulates the logic for temporary token.
6
- # A temporary token is created to identify a user in scenarios
6
+ # A temporary token is created to identify a user in scenarios
7
7
  # such as reseting password and activating the user by email.
8
8
  module TemporaryToken
9
9
  def self.included(base)
10
10
  base.extend(ClassMethods)
11
11
  end
12
-
12
+
13
13
  # Random code, used for salt and temporary tokens.
14
14
  def self.generate_random_token
15
15
  SecureRandom.base64(15).tr('+/=lIO0', 'pqrsxyz')
16
16
  end
17
-
17
+
18
18
  module ClassMethods
19
19
  def load_from_token(token, token_attr_name, token_expiration_date_attr)
20
20
  return nil if token.blank?
21
- user = find_by_sorcery_token(token_attr_name,token)
21
+ user = sorcery_adapter.find_by_token(token_attr_name,token)
22
22
  if !user.blank? && !user.send(token_expiration_date_attr).nil?
23
23
  return Time.now.in_time_zone < user.send(token_expiration_date_attr) ? user : nil
24
24
  end