sorcery 0.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sorcery might be problematic. Click here for more details.

Files changed (101) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +19 -0
  4. data/Gemfile.lock +129 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +139 -0
  7. data/Rakefile +61 -0
  8. data/VERSION +1 -0
  9. data/features/support/env.rb +13 -0
  10. data/lib/sorcery.rb +28 -0
  11. data/lib/sorcery/controller.rb +156 -0
  12. data/lib/sorcery/controller/submodules/brute_force_protection.rb +89 -0
  13. data/lib/sorcery/controller/submodules/remember_me.rb +43 -0
  14. data/lib/sorcery/controller/submodules/session_timeout.rb +42 -0
  15. data/lib/sorcery/crypto_providers/aes256.rb +44 -0
  16. data/lib/sorcery/crypto_providers/bcrypt.rb +96 -0
  17. data/lib/sorcery/crypto_providers/md5.rb +39 -0
  18. data/lib/sorcery/crypto_providers/sha1.rb +40 -0
  19. data/lib/sorcery/crypto_providers/sha256.rb +55 -0
  20. data/lib/sorcery/crypto_providers/sha512.rb +55 -0
  21. data/lib/sorcery/engine.rb +20 -0
  22. data/lib/sorcery/model.rb +175 -0
  23. data/lib/sorcery/model/submodules/password_reset.rb +64 -0
  24. data/lib/sorcery/model/submodules/remember_me.rb +42 -0
  25. data/lib/sorcery/model/submodules/user_activation.rb +84 -0
  26. data/spec/Gemfile +11 -0
  27. data/spec/Gemfile.lock +108 -0
  28. data/spec/Rakefile +11 -0
  29. data/spec/rails3/.rspec +1 -0
  30. data/spec/rails3/Gemfile +12 -0
  31. data/spec/rails3/Gemfile.lock +114 -0
  32. data/spec/rails3/Rakefile +10 -0
  33. data/spec/rails3/app_root/.gitignore +4 -0
  34. data/spec/rails3/app_root/README +256 -0
  35. data/spec/rails3/app_root/Rakefile.unused +7 -0
  36. data/spec/rails3/app_root/app/controllers/application_controller.rb +61 -0
  37. data/spec/rails3/app_root/app/helpers/application_helper.rb +2 -0
  38. data/spec/rails3/app_root/app/mailers/sorcery_mailer.rb +25 -0
  39. data/spec/rails3/app_root/app/models/user.rb +3 -0
  40. data/spec/rails3/app_root/app/views/layouts/application.html.erb +14 -0
  41. data/spec/rails3/app_root/app/views/sorcery_mailer/activation_email.html.erb +17 -0
  42. data/spec/rails3/app_root/app/views/sorcery_mailer/activation_email.text.erb +9 -0
  43. data/spec/rails3/app_root/app/views/sorcery_mailer/activation_success_email.html.erb +17 -0
  44. data/spec/rails3/app_root/app/views/sorcery_mailer/activation_success_email.text.erb +9 -0
  45. data/spec/rails3/app_root/app/views/sorcery_mailer/reset_password_email.html.erb +16 -0
  46. data/spec/rails3/app_root/app/views/sorcery_mailer/reset_password_email.text.erb +8 -0
  47. data/spec/rails3/app_root/config.ru +4 -0
  48. data/spec/rails3/app_root/config/application.rb +48 -0
  49. data/spec/rails3/app_root/config/boot.rb +13 -0
  50. data/spec/rails3/app_root/config/database.yml +27 -0
  51. data/spec/rails3/app_root/config/environment.rb +5 -0
  52. data/spec/rails3/app_root/config/environments/development.rb +26 -0
  53. data/spec/rails3/app_root/config/environments/in_memory.rb +0 -0
  54. data/spec/rails3/app_root/config/environments/production.rb +49 -0
  55. data/spec/rails3/app_root/config/environments/test.rb +35 -0
  56. data/spec/rails3/app_root/config/initializers/backtrace_silencers.rb +7 -0
  57. data/spec/rails3/app_root/config/initializers/inflections.rb +10 -0
  58. data/spec/rails3/app_root/config/initializers/mime_types.rb +5 -0
  59. data/spec/rails3/app_root/config/initializers/secret_token.rb +7 -0
  60. data/spec/rails3/app_root/config/initializers/session_store.rb +8 -0
  61. data/spec/rails3/app_root/config/locales/en.yml +5 -0
  62. data/spec/rails3/app_root/config/routes.rb +67 -0
  63. data/spec/rails3/app_root/db/migrate/activation/20101224223622_add_activation_to_users.rb +15 -0
  64. data/spec/rails3/app_root/db/migrate/core/20101224223620_create_users.rb +16 -0
  65. data/spec/rails3/app_root/db/migrate/password_reset/20101224223622_add_password_reset_to_users.rb +9 -0
  66. data/spec/rails3/app_root/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +15 -0
  67. data/spec/rails3/app_root/db/schema.rb +23 -0
  68. data/spec/rails3/app_root/db/seeds.rb +7 -0
  69. data/spec/rails3/app_root/lib/tasks/.gitkeep +0 -0
  70. data/spec/rails3/app_root/public/404.html +26 -0
  71. data/spec/rails3/app_root/public/422.html +26 -0
  72. data/spec/rails3/app_root/public/500.html +26 -0
  73. data/spec/rails3/app_root/public/favicon.ico +0 -0
  74. data/spec/rails3/app_root/public/images/rails.png +0 -0
  75. data/spec/rails3/app_root/public/index.html +239 -0
  76. data/spec/rails3/app_root/public/javascripts/application.js +2 -0
  77. data/spec/rails3/app_root/public/javascripts/controls.js +965 -0
  78. data/spec/rails3/app_root/public/javascripts/dragdrop.js +974 -0
  79. data/spec/rails3/app_root/public/javascripts/effects.js +1123 -0
  80. data/spec/rails3/app_root/public/javascripts/prototype.js +6001 -0
  81. data/spec/rails3/app_root/public/javascripts/rails.js +175 -0
  82. data/spec/rails3/app_root/public/robots.txt +5 -0
  83. data/spec/rails3/app_root/public/stylesheets/.gitkeep +0 -0
  84. data/spec/rails3/app_root/script/rails +6 -0
  85. data/spec/rails3/app_root/test/fixtures/users.yml +9 -0
  86. data/spec/rails3/app_root/test/performance/browsing_test.rb +9 -0
  87. data/spec/rails3/app_root/test/test_helper.rb +13 -0
  88. data/spec/rails3/app_root/test/unit/user_test.rb +8 -0
  89. data/spec/rails3/app_root/vendor/plugins/.gitkeep +0 -0
  90. data/spec/rails3/controller_brute_force_protection_spec.rb +72 -0
  91. data/spec/rails3/controller_remember_me_spec.rb +65 -0
  92. data/spec/rails3/controller_session_timeout_spec.rb +49 -0
  93. data/spec/rails3/controller_spec.rb +115 -0
  94. data/spec/rails3/spec_helper.rb +115 -0
  95. data/spec/rails3/user_activation_spec.rb +148 -0
  96. data/spec/rails3/user_password_reset_spec.rb +76 -0
  97. data/spec/rails3/user_remember_me_spec.rb +66 -0
  98. data/spec/rails3/user_spec.rb +283 -0
  99. data/spec/sorcery_crypto_providers_spec.rb +182 -0
  100. data/spec/spec_helper.rb +18 -0
  101. metadata +341 -0
@@ -0,0 +1,55 @@
1
+ require "digest/sha2"
2
+
3
+ module Sorcery
4
+ # The activate_sorcery method has a custom_crypto_provider configuration option. This allows you to use any type of encryption you like.
5
+ # Just create a class with a class level encrypt and matches? method. See example below.
6
+ #
7
+ # === Example
8
+ #
9
+ # class MyAwesomeEncryptionMethod
10
+ # def self.encrypt(*tokens)
11
+ # # the tokens passed will be an array of objects, what type of object is irrelevant,
12
+ # # just do what you need to do with them and return a single encrypted string.
13
+ # # for example, you will most likely join all of the objects into a single string and then encrypt that string
14
+ # end
15
+ #
16
+ # def self.matches?(crypted, *tokens)
17
+ # # return true if the crypted string matches the tokens.
18
+ # # depending on your algorithm you might decrypt the string then compare it to the token, or you might
19
+ # # encrypt the tokens and make sure it matches the crypted string, its up to you
20
+ # end
21
+ # end
22
+ module CryptoProviders
23
+ # = Sha512
24
+ #
25
+ # Uses the Sha512 hash algorithm to encrypt passwords.
26
+ class SHA512
27
+ 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
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,20 @@
1
+ require 'sorcery'
2
+ require 'rails'
3
+
4
+ module Sorcery
5
+ # The Sorcery engine takes care of extending ActiveRecord (if used) and ActionController,
6
+ # With the plugin logic.
7
+ class Engine < Rails::Engine
8
+ config.sorcery = ::Sorcery::Controller::Config
9
+
10
+ initializer "extend Model with sorcery" do |app|
11
+ ActiveRecord::Base.send(:include, Sorcery::Model) if defined?(ActiveRecord)
12
+ end
13
+
14
+ initializer "extend Controller with sorcery" do |app|
15
+ ActionController::Base.send(:include, Sorcery::Controller)
16
+ ActionController::Base.helper_method :logged_in_user
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,175 @@
1
+ module Sorcery
2
+ # This module handles all plugin operations which are related to the Model layer in the MVC pattern.
3
+ # It should be included into the ORM base class.
4
+ # In the case of Rails this is usually ActiveRecord (actually, in that case, the plugin does this automatically).
5
+ #
6
+ # When included it defines a single method: 'activate_sorcery!' which when called adds the other capabilities to the class.
7
+ # This method is also the place to configure the plugin in the Model layer.
8
+ module Model
9
+ def self.included(klass)
10
+ klass.class_eval do
11
+ class << self
12
+ def activate_sorcery!
13
+ @sorcery_config = Config.new
14
+ self.class_eval do
15
+ extend ClassMethods # included here, before submodules, so they can be overriden by them.
16
+ include InstanceMethods
17
+ ::Sorcery::Controller::Config.user_class = self
18
+ @sorcery_config.submodules = ::Sorcery::Controller::Config.submodules
19
+ @sorcery_config.submodules.each do |mod|
20
+ begin
21
+ include Submodules.const_get(mod.to_s.split("_").map {|p| p.capitalize}.join(""))
22
+ rescue NameError
23
+ # don't stop on a missing submodule.
24
+ end
25
+ end
26
+ end
27
+
28
+ yield @sorcery_config if block_given?
29
+
30
+ self.class_eval do
31
+ attr_accessor @sorcery_config.password_attribute_name
32
+ attr_protected @sorcery_config.crypted_password_attribute_name, @sorcery_config.salt_attribute_name
33
+ before_save :encrypt_password, :if => Proc.new { |record| record.send(sorcery_config.password_attribute_name).present? }
34
+ after_save :clear_virtual_password, :if => Proc.new { |record| record.send(sorcery_config.password_attribute_name).present? }
35
+ end
36
+ @sorcery_config.after_config.each { |c| send(c) }
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ module ClassMethods
43
+ # Returns the class instance variable for configuration, when called by the class itself.
44
+ def sorcery_config
45
+ @sorcery_config
46
+ end
47
+
48
+ # The default authentication method.
49
+ # Takes a username and password,
50
+ # Finds the user by the username and compares the user's password to the one supplied to the method.
51
+ # returns the user if success, nil otherwise.
52
+ def authenticate(*credentials)
53
+ raise ArgumentError, "at least 2 arguments required" if credentials.size < 2
54
+ user = where("#{@sorcery_config.username_attribute_name} = ?", credentials[0]).first
55
+ salt = user.send(@sorcery_config.salt_attribute_name) if user && !@sorcery_config.salt_attribute_name.nil?
56
+ user if user && @sorcery_config.before_authenticate.all? {|c| user.send(c)} && (user.send(@sorcery_config.crypted_password_attribute_name)) == encrypt(credentials[1],salt)
57
+ end
58
+
59
+ def encrypt(*tokens)
60
+ return tokens.first if @sorcery_config.encryption_provider.nil?
61
+
62
+ @sorcery_config.encryption_provider.stretches = @sorcery_config.stretches if @sorcery_config.encryption_provider.respond_to?(:stretches) && @sorcery_config.stretches
63
+ @sorcery_config.encryption_provider.join_token = @sorcery_config.salt_join_token if @sorcery_config.encryption_provider.respond_to?(:join_token) && @sorcery_config.salt_join_token
64
+ CryptoProviders::AES256.key = @sorcery_config.encryption_key if @sorcery_config.encryption_algorithm == :aes256
65
+ @sorcery_config.encryption_provider.encrypt(*tokens)
66
+ end
67
+ end
68
+
69
+ module InstanceMethods
70
+ # Returns the class instance variable for configuration, when called by an instance.
71
+ def sorcery_config
72
+ self.class.sorcery_config
73
+ end
74
+
75
+ protected
76
+
77
+ # creates new salt and saves it.
78
+ # encrypts password with salt and save it.
79
+ def encrypt_password
80
+ config = sorcery_config
81
+ self.send(:"#{config.salt_attribute_name}=", generate_random_code) if !config.salt_attribute_name.nil?
82
+ self.send(:"#{config.crypted_password_attribute_name}=", self.class.encrypt(self.send(config.password_attribute_name),salt))
83
+ end
84
+
85
+ def clear_virtual_password
86
+ config = sorcery_config
87
+ self.send(:"#{config.password_attribute_name}=", nil)
88
+ end
89
+
90
+ # calls the requested email method on the configured mailer
91
+ # supports both the ActionMailer 3 way of calling, and the plain old Ruby object way.
92
+ def generic_send_email(method)
93
+ config = sorcery_config
94
+ mail = config.sorcery_mailer.send(config.send(method),self)
95
+ if defined?(ActionMailer) and config.sorcery_mailer.superclass == ActionMailer::Base
96
+ mail.deliver
97
+ end
98
+ end
99
+
100
+ # Random code, used for salt and temporary tokens.
101
+ def generate_random_code
102
+ return Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
103
+ end
104
+ end
105
+
106
+ # Each class which calls 'activate_sorcery!' receives an instance of this class.
107
+ # Every submodule which gets loaded may add accessors to this class so that all options will be configured from a single place.
108
+ class Config
109
+
110
+ attr_accessor :username_attribute_name, # change default username attribute, for example, to use :email as the login.
111
+ :password_attribute_name, # change *virtual* password attribute, the one which is used until an encrypted one is generated.
112
+ :email_attribute_name, # change default email attribute.
113
+ :crypted_password_attribute_name, # change default crypted_password attribute.
114
+ :salt_join_token, # what pattern to use to join the password with the salt
115
+ :salt_attribute_name, # change default salt attribute.
116
+ :stretches, # how many times to apply encryption to the password.
117
+ :encryption_key, # encryption key used to encrypt reversible encryptions such as AES256.
118
+
119
+ :submodules, # configured in config/application.rb
120
+ :before_authenticate, # an array of method names to call before authentication completes. used internally.
121
+ :after_config # an array of method names to call after configuration by user. used internally.
122
+
123
+ attr_reader :encryption_provider, # change default encryption_provider.
124
+ :custom_encryption_provider, # use an external encryption class.
125
+ :encryption_algorithm # encryption algorithm name. See 'encryption_algorithm=' below for available options.
126
+
127
+ def initialize
128
+ @defaults = {
129
+ :@submodules => [],
130
+ :@username_attribute_name => :username,
131
+ :@password_attribute_name => :password,
132
+ :@email_attribute_name => :email,
133
+ :@crypted_password_attribute_name => :crypted_password,
134
+ :@encryption_algorithm => :sha256,
135
+ :@encryption_provider => CryptoProviders::BCrypt,
136
+ :@custom_encryption_provider => nil,
137
+ :@encryption_key => nil,
138
+ :@salt_join_token => "",
139
+ :@salt_attribute_name => :salt,
140
+ :@stretches => nil,
141
+ :@before_authenticate => [],
142
+ :@after_config => []
143
+ }
144
+ reset!
145
+ end
146
+
147
+ # Resets all configuration options to their default values.
148
+ def reset!
149
+ @defaults.each do |k,v|
150
+ instance_variable_set(k,v)
151
+ end
152
+ end
153
+
154
+ def custom_encryption_provider=(provider)
155
+ @custom_encryption_provider = @encryption_provider = provider
156
+ end
157
+
158
+ def encryption_algorithm=(algo)
159
+ @encryption_algorithm = algo
160
+ @encryption_provider = case @encryption_algorithm
161
+ when :none then nil
162
+ when :md5 then CryptoProviders::MD5
163
+ when :sha1 then CryptoProviders::SHA1
164
+ when :sha256 then CryptoProviders::SHA256
165
+ when :sha512 then CryptoProviders::SHA512
166
+ when :aes256 then CryptoProviders::AES256
167
+ when :bcrypt then CryptoProviders::BCrypt
168
+ when :custom then @custom_encryption_provider
169
+ end
170
+ end
171
+
172
+ end
173
+
174
+ end
175
+ end
@@ -0,0 +1,64 @@
1
+ module Sorcery
2
+ module Model
3
+ module Submodules
4
+ # This submodule adds the ability to reset password via email confirmation.
5
+ module PasswordReset
6
+ def self.included(base)
7
+ base.sorcery_config.class_eval do
8
+ attr_accessor :reset_password_code_attribute_name, # reset password code attribute name.
9
+ :sorcery_mailer, # mailer class. Needed.
10
+ :reset_password_email_method_name # reset password email method on your mailer class.
11
+
12
+ end
13
+
14
+ base.sorcery_config.instance_eval do
15
+ @defaults.merge!(:@reset_password_code_attribute_name => :reset_password_code,
16
+ :@sorcery_mailer => nil,
17
+ :@reset_password_email_method_name => :reset_password_email)
18
+
19
+ reset!
20
+ end
21
+
22
+ base.class_eval do
23
+ clear_reset_password_code_proc = Proc.new do |record|
24
+ record.valid? && record.send(sorcery_config.password_attribute_name)
25
+ end
26
+
27
+ before_save :clear_reset_password_code, :if =>clear_reset_password_code_proc
28
+ end
29
+
30
+ base.sorcery_config.after_config << :validate_mailer_defined
31
+
32
+ base.extend(ClassMethods)
33
+ base.send(:include, InstanceMethods)
34
+ end
35
+
36
+ module ClassMethods
37
+ def validate_mailer_defined
38
+ msg = "To use password_reset submodule, you must define a mailer (config.sorcery_mailer = YourMailerClass)."
39
+ raise ArgumentError, msg if @sorcery_config.sorcery_mailer == nil
40
+ end
41
+ end
42
+
43
+ module InstanceMethods
44
+ def reset_password!
45
+ config = sorcery_config
46
+ self.send(:"#{config.reset_password_code_attribute_name}=", generate_random_code)
47
+ self.class.transaction do
48
+ self.save!(:validate => false)
49
+ generic_send_email(:reset_password_email_method_name)
50
+ end
51
+ end
52
+
53
+ protected
54
+
55
+ def clear_reset_password_code
56
+ config = sorcery_config
57
+ self.send(:"#{config.reset_password_code_attribute_name}=", nil)
58
+ end
59
+ end
60
+
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,42 @@
1
+ module Sorcery
2
+ module Model
3
+ module Submodules
4
+ module RememberMe
5
+ def self.included(base)
6
+ base.sorcery_config.class_eval do
7
+ attr_accessor :remember_me_token_attribute_name, # the attribute in the model class.
8
+ :remember_me_token_expires_at_attribute_name, # the expires attribute in the model class.
9
+ :remember_me_for # how long in seconds to remember.
10
+
11
+ end
12
+
13
+ base.sorcery_config.instance_eval do
14
+ @defaults.merge!(:@remember_me_token_attribute_name => :remember_me_token,
15
+ :@remember_me_token_expires_at_attribute_name => :remember_me_token_expires_at,
16
+ :@remember_me_for => 7 * 60 * 60 * 24)
17
+
18
+ reset!
19
+ end
20
+
21
+ base.send(:include, InstanceMethods)
22
+ end
23
+
24
+ module InstanceMethods
25
+ def remember_me!
26
+ config = sorcery_config
27
+ self.send(:"#{config.remember_me_token_attribute_name}=", generate_random_code)
28
+ self.send(:"#{config.remember_me_token_expires_at_attribute_name}=", Time.now + config.remember_me_for)
29
+ self.save!(:validate => false)
30
+ end
31
+
32
+ def forget_me!
33
+ config = sorcery_config
34
+ self.send(:"#{config.remember_me_token_attribute_name}=", nil)
35
+ self.send(:"#{config.remember_me_token_expires_at_attribute_name}=", nil)
36
+ self.save!(:validate => false)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,84 @@
1
+ module Sorcery
2
+ module Model
3
+ module Submodules
4
+ # This submodule adds the ability to make the user activate his account via email
5
+ # or any other way in which he can recieve an activation code.
6
+ # with the activation code the user may activate his account.
7
+ # When using this submodule, supplying a mailer is mandatory.
8
+ module UserActivation
9
+ def self.included(base)
10
+ base.sorcery_config.class_eval do
11
+ attr_accessor :activation_state_attribute_name, # the attribute name to hold activation state (active/pending).
12
+ :activation_code_attribute_name, # the attribute name to hold activation code (sent by email).
13
+ :sorcery_mailer, # your mailer class. Needed.
14
+ :activation_needed_email_method_name, # activation needed email method on your mailer class.
15
+ :activation_success_email_method_name, # activation success email method on your mailer class.
16
+ :prevent_non_active_users_to_login # do you want to prevent or allow users that did not activate by email to login?
17
+ end
18
+
19
+ base.sorcery_config.instance_eval do
20
+ @defaults.merge!(:@activation_state_attribute_name => :activation_state,
21
+ :@activation_code_attribute_name => :activation_code,
22
+ :@sorcery_mailer => nil,
23
+ :@activation_needed_email_method_name => :activation_needed_email,
24
+ :@activation_success_email_method_name => :activation_success_email,
25
+ :@prevent_non_active_users_to_login => true)
26
+ reset!
27
+ end
28
+
29
+ base.class_eval do
30
+ before_create :setup_activation
31
+ after_create :send_activation_needed_email!
32
+ end
33
+
34
+ base.sorcery_config.after_config << :validate_mailer_defined
35
+
36
+ base.sorcery_config.before_authenticate << :prevent_non_active_login
37
+
38
+ base.extend(ClassMethods)
39
+ base.send(:include, InstanceMethods)
40
+ end
41
+
42
+ module ClassMethods
43
+ def validate_mailer_defined
44
+ msg = "To use user_activation submodule, you must define a mailer (config.sorcery_mailer = YourMailerClass)."
45
+ raise ArgumentError, msg if @sorcery_config.sorcery_mailer == nil
46
+ end
47
+ end
48
+
49
+ module InstanceMethods
50
+ def activate!
51
+ config = sorcery_config
52
+ self.send(:"#{config.activation_code_attribute_name}=", nil)
53
+ self.send(:"#{config.activation_state_attribute_name}=", "active")
54
+ send_activation_success_email!
55
+ save!(:validate => false) # don't run validations
56
+ end
57
+
58
+ protected
59
+
60
+ def setup_activation
61
+ config = sorcery_config
62
+ generated_activation_code = CryptoProviders::SHA1.encrypt( Time.now.to_s.split(//).sort_by {rand}.join )
63
+ self.send(:"#{config.activation_code_attribute_name}=", generated_activation_code)
64
+ self.send(:"#{config.activation_state_attribute_name}=", "pending")
65
+ end
66
+
67
+ def send_activation_needed_email!
68
+ generic_send_email(:activation_needed_email_method_name) unless sorcery_config.activation_needed_email_method_name.nil?
69
+ end
70
+
71
+ def send_activation_success_email!
72
+ generic_send_email(:activation_success_email_method_name) unless sorcery_config.activation_success_email_method_name.nil?
73
+ end
74
+
75
+ def prevent_non_active_login
76
+ config = sorcery_config
77
+ config.prevent_non_active_users_to_login ? self.send(config.activation_state_attribute_name) == "active" : true
78
+ end
79
+
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end