devise-multi_email 1.0.5 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -1
- data/CHANGELOG.md +15 -2
- data/Gemfile +2 -9
- data/README.md +69 -18
- data/devise-multi_email.gemspec +4 -0
- data/examples/rails5_app/.gitignore +21 -0
- data/examples/rails5_app/Gemfile +55 -0
- data/examples/rails5_app/Gemfile.lock +185 -0
- data/examples/rails5_app/README.md +24 -0
- data/examples/rails5_app/Rakefile +6 -0
- data/examples/rails5_app/app/assets/config/manifest.js +3 -0
- data/examples/rails5_app/app/assets/images/.keep +0 -0
- data/examples/rails5_app/app/assets/javascripts/application.js +16 -0
- data/examples/rails5_app/app/assets/javascripts/cable.js +13 -0
- data/examples/rails5_app/app/assets/javascripts/channels/.keep +0 -0
- data/examples/rails5_app/app/assets/stylesheets/application.css +15 -0
- data/examples/rails5_app/app/channels/application_cable/channel.rb +4 -0
- data/examples/rails5_app/app/channels/application_cable/connection.rb +4 -0
- data/examples/rails5_app/app/controllers/application_controller.rb +3 -0
- data/examples/rails5_app/app/controllers/concerns/.keep +0 -0
- data/examples/rails5_app/app/helpers/application_helper.rb +2 -0
- data/examples/rails5_app/app/jobs/application_job.rb +2 -0
- data/examples/rails5_app/app/mailers/application_mailer.rb +4 -0
- data/examples/rails5_app/app/models/application_record.rb +3 -0
- data/examples/rails5_app/app/models/concerns/.keep +0 -0
- data/examples/rails5_app/app/models/email.rb +3 -0
- data/examples/rails5_app/app/models/user.rb +9 -0
- data/examples/rails5_app/app/views/layouts/application.html.erb +14 -0
- data/examples/rails5_app/app/views/layouts/mailer.html.erb +13 -0
- data/examples/rails5_app/app/views/layouts/mailer.text.erb +1 -0
- data/examples/rails5_app/bin/bundle +3 -0
- data/examples/rails5_app/bin/rails +4 -0
- data/examples/rails5_app/bin/rake +4 -0
- data/examples/rails5_app/bin/setup +34 -0
- data/examples/rails5_app/bin/update +29 -0
- data/examples/rails5_app/config/application.rb +15 -0
- data/examples/rails5_app/config/boot.rb +3 -0
- data/examples/rails5_app/config/cable.yml +9 -0
- data/examples/rails5_app/config/database.yml +25 -0
- data/examples/rails5_app/config/environment.rb +5 -0
- data/examples/rails5_app/config/environments/development.rb +56 -0
- data/examples/rails5_app/config/environments/production.rb +86 -0
- data/examples/rails5_app/config/environments/test.rb +42 -0
- data/examples/rails5_app/config/initializers/application_controller_renderer.rb +6 -0
- data/examples/rails5_app/config/initializers/assets.rb +11 -0
- data/examples/rails5_app/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/rails5_app/config/initializers/cookies_serializer.rb +5 -0
- data/examples/rails5_app/config/initializers/devise.rb +274 -0
- data/examples/rails5_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/rails5_app/config/initializers/inflections.rb +16 -0
- data/examples/rails5_app/config/initializers/mime_types.rb +4 -0
- data/examples/rails5_app/config/initializers/new_framework_defaults.rb +24 -0
- data/examples/rails5_app/config/initializers/session_store.rb +3 -0
- data/examples/rails5_app/config/initializers/wrap_parameters.rb +14 -0
- data/examples/rails5_app/config/locales/devise.en.yml +62 -0
- data/examples/rails5_app/config/locales/en.yml +23 -0
- data/examples/rails5_app/config/puma.rb +47 -0
- data/examples/rails5_app/config/routes.rb +4 -0
- data/examples/rails5_app/config/secrets.yml +22 -0
- data/examples/rails5_app/config/spring.rb +6 -0
- data/examples/rails5_app/config.ru +5 -0
- data/examples/rails5_app/db/migrate/20170307140813_devise_create_users.rb +49 -0
- data/examples/rails5_app/db/migrate/20170307145547_add_password_salt_to_users.rb +5 -0
- data/examples/rails5_app/db/schema.rb +44 -0
- data/examples/rails5_app/db/seeds.rb +7 -0
- data/examples/rails5_app/lib/assets/.keep +0 -0
- data/examples/rails5_app/lib/tasks/.keep +0 -0
- data/examples/rails5_app/log/.keep +0 -0
- data/examples/rails5_app/public/404.html +67 -0
- data/examples/rails5_app/public/422.html +67 -0
- data/examples/rails5_app/public/500.html +66 -0
- data/examples/rails5_app/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/rails5_app/public/apple-touch-icon.png +0 -0
- data/examples/rails5_app/public/favicon.ico +0 -0
- data/examples/rails5_app/public/robots.txt +5 -0
- data/examples/rails5_app/test/controllers/.keep +0 -0
- data/examples/rails5_app/test/fixtures/.keep +0 -0
- data/examples/rails5_app/test/fixtures/files/.keep +0 -0
- data/examples/rails5_app/test/helpers/.keep +0 -0
- data/examples/rails5_app/test/integration/.keep +0 -0
- data/examples/rails5_app/test/mailers/.keep +0 -0
- data/examples/rails5_app/test/models/.keep +0 -0
- data/examples/rails5_app/test/test_helper.rb +10 -0
- data/examples/rails5_app/tmp/.keep +0 -0
- data/examples/rails5_app/vendor/assets/javascripts/.keep +0 -0
- data/examples/rails5_app/vendor/assets/stylesheets/.keep +0 -0
- data/gemfiles/rails_4_2.gemfile +5 -0
- data/gemfiles/rails_5_0.gemfile +5 -0
- data/gemfiles/rails_5_1.gemfile +5 -0
- data/lib/devise/multi_email/association_manager.rb +30 -0
- data/lib/devise/multi_email/email_model_extensions.rb +20 -0
- data/lib/devise/multi_email/email_model_manager.rb +18 -0
- data/lib/devise/multi_email/models/authenticatable.rb +23 -44
- data/lib/devise/multi_email/models/confirmable.rb +20 -21
- data/lib/devise/multi_email/models/validatable.rb +42 -38
- data/lib/devise/multi_email/parent_model_extensions.rb +27 -0
- data/lib/devise/multi_email/parent_model_manager.rb +55 -0
- data/lib/devise/multi_email/version.rb +1 -1
- data/lib/devise/multi_email.rb +32 -0
- metadata +147 -2
@@ -0,0 +1,67 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The page you were looking for doesn't exist (404)</title>
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
|
+
<style>
|
7
|
+
body {
|
8
|
+
background-color: #EFEFEF;
|
9
|
+
color: #2E2F30;
|
10
|
+
text-align: center;
|
11
|
+
font-family: arial, sans-serif;
|
12
|
+
margin: 0;
|
13
|
+
}
|
14
|
+
|
15
|
+
div.dialog {
|
16
|
+
width: 95%;
|
17
|
+
max-width: 33em;
|
18
|
+
margin: 4em auto 0;
|
19
|
+
}
|
20
|
+
|
21
|
+
div.dialog > div {
|
22
|
+
border: 1px solid #CCC;
|
23
|
+
border-right-color: #999;
|
24
|
+
border-left-color: #999;
|
25
|
+
border-bottom-color: #BBB;
|
26
|
+
border-top: #B00100 solid 4px;
|
27
|
+
border-top-left-radius: 9px;
|
28
|
+
border-top-right-radius: 9px;
|
29
|
+
background-color: white;
|
30
|
+
padding: 7px 12% 0;
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
|
+
}
|
33
|
+
|
34
|
+
h1 {
|
35
|
+
font-size: 100%;
|
36
|
+
color: #730E15;
|
37
|
+
line-height: 1.5em;
|
38
|
+
}
|
39
|
+
|
40
|
+
div.dialog > p {
|
41
|
+
margin: 0 0 1em;
|
42
|
+
padding: 1em;
|
43
|
+
background-color: #F7F7F7;
|
44
|
+
border: 1px solid #CCC;
|
45
|
+
border-right-color: #999;
|
46
|
+
border-left-color: #999;
|
47
|
+
border-bottom-color: #999;
|
48
|
+
border-bottom-left-radius: 4px;
|
49
|
+
border-bottom-right-radius: 4px;
|
50
|
+
border-top-color: #DADADA;
|
51
|
+
color: #666;
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
53
|
+
}
|
54
|
+
</style>
|
55
|
+
</head>
|
56
|
+
|
57
|
+
<body>
|
58
|
+
<!-- This file lives in public/404.html -->
|
59
|
+
<div class="dialog">
|
60
|
+
<div>
|
61
|
+
<h1>The page you were looking for doesn't exist.</h1>
|
62
|
+
<p>You may have mistyped the address or the page may have moved.</p>
|
63
|
+
</div>
|
64
|
+
<p>If you are the application owner check the logs for more information.</p>
|
65
|
+
</div>
|
66
|
+
</body>
|
67
|
+
</html>
|
@@ -0,0 +1,67 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The change you wanted was rejected (422)</title>
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
|
+
<style>
|
7
|
+
body {
|
8
|
+
background-color: #EFEFEF;
|
9
|
+
color: #2E2F30;
|
10
|
+
text-align: center;
|
11
|
+
font-family: arial, sans-serif;
|
12
|
+
margin: 0;
|
13
|
+
}
|
14
|
+
|
15
|
+
div.dialog {
|
16
|
+
width: 95%;
|
17
|
+
max-width: 33em;
|
18
|
+
margin: 4em auto 0;
|
19
|
+
}
|
20
|
+
|
21
|
+
div.dialog > div {
|
22
|
+
border: 1px solid #CCC;
|
23
|
+
border-right-color: #999;
|
24
|
+
border-left-color: #999;
|
25
|
+
border-bottom-color: #BBB;
|
26
|
+
border-top: #B00100 solid 4px;
|
27
|
+
border-top-left-radius: 9px;
|
28
|
+
border-top-right-radius: 9px;
|
29
|
+
background-color: white;
|
30
|
+
padding: 7px 12% 0;
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
|
+
}
|
33
|
+
|
34
|
+
h1 {
|
35
|
+
font-size: 100%;
|
36
|
+
color: #730E15;
|
37
|
+
line-height: 1.5em;
|
38
|
+
}
|
39
|
+
|
40
|
+
div.dialog > p {
|
41
|
+
margin: 0 0 1em;
|
42
|
+
padding: 1em;
|
43
|
+
background-color: #F7F7F7;
|
44
|
+
border: 1px solid #CCC;
|
45
|
+
border-right-color: #999;
|
46
|
+
border-left-color: #999;
|
47
|
+
border-bottom-color: #999;
|
48
|
+
border-bottom-left-radius: 4px;
|
49
|
+
border-bottom-right-radius: 4px;
|
50
|
+
border-top-color: #DADADA;
|
51
|
+
color: #666;
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
53
|
+
}
|
54
|
+
</style>
|
55
|
+
</head>
|
56
|
+
|
57
|
+
<body>
|
58
|
+
<!-- This file lives in public/422.html -->
|
59
|
+
<div class="dialog">
|
60
|
+
<div>
|
61
|
+
<h1>The change you wanted was rejected.</h1>
|
62
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
63
|
+
</div>
|
64
|
+
<p>If you are the application owner check the logs for more information.</p>
|
65
|
+
</div>
|
66
|
+
</body>
|
67
|
+
</html>
|
@@ -0,0 +1,66 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
|
+
<style>
|
7
|
+
body {
|
8
|
+
background-color: #EFEFEF;
|
9
|
+
color: #2E2F30;
|
10
|
+
text-align: center;
|
11
|
+
font-family: arial, sans-serif;
|
12
|
+
margin: 0;
|
13
|
+
}
|
14
|
+
|
15
|
+
div.dialog {
|
16
|
+
width: 95%;
|
17
|
+
max-width: 33em;
|
18
|
+
margin: 4em auto 0;
|
19
|
+
}
|
20
|
+
|
21
|
+
div.dialog > div {
|
22
|
+
border: 1px solid #CCC;
|
23
|
+
border-right-color: #999;
|
24
|
+
border-left-color: #999;
|
25
|
+
border-bottom-color: #BBB;
|
26
|
+
border-top: #B00100 solid 4px;
|
27
|
+
border-top-left-radius: 9px;
|
28
|
+
border-top-right-radius: 9px;
|
29
|
+
background-color: white;
|
30
|
+
padding: 7px 12% 0;
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
|
+
}
|
33
|
+
|
34
|
+
h1 {
|
35
|
+
font-size: 100%;
|
36
|
+
color: #730E15;
|
37
|
+
line-height: 1.5em;
|
38
|
+
}
|
39
|
+
|
40
|
+
div.dialog > p {
|
41
|
+
margin: 0 0 1em;
|
42
|
+
padding: 1em;
|
43
|
+
background-color: #F7F7F7;
|
44
|
+
border: 1px solid #CCC;
|
45
|
+
border-right-color: #999;
|
46
|
+
border-left-color: #999;
|
47
|
+
border-bottom-color: #999;
|
48
|
+
border-bottom-left-radius: 4px;
|
49
|
+
border-bottom-right-radius: 4px;
|
50
|
+
border-top-color: #DADADA;
|
51
|
+
color: #666;
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
53
|
+
}
|
54
|
+
</style>
|
55
|
+
</head>
|
56
|
+
|
57
|
+
<body>
|
58
|
+
<!-- This file lives in public/500.html -->
|
59
|
+
<div class="dialog">
|
60
|
+
<div>
|
61
|
+
<h1>We're sorry, but something went wrong.</h1>
|
62
|
+
</div>
|
63
|
+
<p>If you are the application owner check the logs for more information.</p>
|
64
|
+
</div>
|
65
|
+
</body>
|
66
|
+
</html>
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,10 @@
|
|
1
|
+
ENV['RAILS_ENV'] ||= 'test'
|
2
|
+
require File.expand_path('../../config/environment', __FILE__)
|
3
|
+
require 'rails/test_help'
|
4
|
+
|
5
|
+
class ActiveSupport::TestCase
|
6
|
+
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
|
7
|
+
fixtures :all
|
8
|
+
|
9
|
+
# Add more helper methods to be used by all tests here...
|
10
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module Devise
|
3
|
+
module MultiEmail
|
4
|
+
class AssociationManager
|
5
|
+
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
def initialize(klass, association_name)
|
9
|
+
@klass = klass
|
10
|
+
@name = association_name
|
11
|
+
end
|
12
|
+
|
13
|
+
def include_module(mod)
|
14
|
+
model_class.__send__ :include, mod
|
15
|
+
end
|
16
|
+
|
17
|
+
def model_class
|
18
|
+
unless reflection
|
19
|
+
raise "#{@klass}##{name} association not found: It might be because your declaration is after `devise :multi_email_confirmable`."
|
20
|
+
end
|
21
|
+
|
22
|
+
@model_class ||= reflection.class_name.constantize
|
23
|
+
end
|
24
|
+
|
25
|
+
def reflection
|
26
|
+
@reflection ||= @klass.reflect_on_association(name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'devise/multi_email/association_manager'
|
2
|
+
require 'devise/multi_email/email_model_manager'
|
3
|
+
|
4
|
+
module Devise
|
5
|
+
module MultiEmail
|
6
|
+
module EmailModelExtensions
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
def multi_email
|
10
|
+
@multi_email ||= EmailModelManager.new(self)
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def multi_email_association
|
15
|
+
@multi_email ||= AssociationManager.new(self, Devise::MultiEmail.parent_association_name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'devise/multi_email/email_model_extensions'
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module MultiEmail
|
5
|
+
class EmailModelManager
|
6
|
+
|
7
|
+
attr_reader :record
|
8
|
+
|
9
|
+
def initialize(record)
|
10
|
+
@record = record
|
11
|
+
end
|
12
|
+
|
13
|
+
def parent
|
14
|
+
record.__send__(record.class.multi_email_association.name)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,59 +1,47 @@
|
|
1
|
+
require 'devise/multi_email/parent_model_extensions'
|
2
|
+
|
1
3
|
module Devise
|
2
4
|
module Models
|
3
5
|
module EmailAuthenticatable
|
4
|
-
USER_ASSOCIATION = :user
|
5
|
-
|
6
6
|
def devise_scope
|
7
|
-
|
8
|
-
if user_association
|
9
|
-
user_association.class_name.constantize
|
10
|
-
else
|
11
|
-
raise "#{self.class.name}: Association :#{USER_ASSOCIATION} not found: Have you declared that ?"
|
12
|
-
end
|
7
|
+
self.class.multi_email_association.model_class
|
13
8
|
end
|
14
9
|
end
|
15
10
|
|
16
11
|
module MultiEmailAuthenticatable
|
17
12
|
extend ActiveSupport::Concern
|
18
|
-
EMAILS_ASSOCIATION = :emails
|
19
13
|
|
20
14
|
included do
|
21
|
-
|
15
|
+
include Devise::MultiEmail::ParentModelExtensions
|
22
16
|
|
23
17
|
attr_accessor :current_login_email
|
24
18
|
|
25
|
-
|
19
|
+
devise :database_authenticatable
|
20
|
+
|
21
|
+
include AuthenticatableExtensions
|
26
22
|
end
|
27
23
|
|
28
24
|
def self.required_fields(klass)
|
29
25
|
[]
|
30
26
|
end
|
31
27
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
28
|
+
module AuthenticatableExtensions
|
29
|
+
extend ActiveSupport::Concern
|
30
|
+
|
31
|
+
included do
|
32
|
+
multi_email_association.include_module(EmailAuthenticatable)
|
36
33
|
end
|
37
34
|
|
38
|
-
|
39
|
-
result ||= valid_emails.first
|
40
|
-
result
|
41
|
-
end
|
35
|
+
delegate :skip_confirmation!, to: Devise::MultiEmail.primary_email_method_name, allow_nil: false
|
42
36
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
37
|
+
# Gets the primary email address of the user.
|
38
|
+
def email
|
39
|
+
multi_email.primary_email.try(:email)
|
40
|
+
end
|
47
41
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
if email
|
52
|
-
record ||= emails.build
|
53
|
-
record.email = email
|
54
|
-
record.primary = true
|
55
|
-
elsif email.nil? && record
|
56
|
-
record.mark_for_destruction
|
42
|
+
# Sets the default email address of the user.
|
43
|
+
def email=(new_email)
|
44
|
+
multi_email.change_primary_email_to(new_email)
|
57
45
|
end
|
58
46
|
end
|
59
47
|
|
@@ -64,9 +52,9 @@ module Devise
|
|
64
52
|
|
65
53
|
if email && email.is_a?(String)
|
66
54
|
conditions = filtered_conditions.to_h.merge(opts).
|
67
|
-
reverse_merge(
|
55
|
+
reverse_merge(multi_email_association.reflection.table_name => { email: email })
|
68
56
|
|
69
|
-
resource = joins(
|
57
|
+
resource = joins(multi_email_association.name).find_by(conditions)
|
70
58
|
resource.current_login_email = email if resource.respond_to?(:current_login_email=)
|
71
59
|
resource
|
72
60
|
else
|
@@ -74,17 +62,8 @@ module Devise
|
|
74
62
|
end
|
75
63
|
end
|
76
64
|
|
77
|
-
def email_class
|
78
|
-
email_association = reflect_on_association(EMAILS_ASSOCIATION)
|
79
|
-
if email_association
|
80
|
-
email_association.class_name.constantize
|
81
|
-
else
|
82
|
-
raise "#{self.class.name}: Association :#{EMAILS_ASSOCIATION} not found: It might because your declaration is after `devise :multi_email_confirmable`."
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
65
|
def find_by_email(email)
|
87
|
-
joins(
|
66
|
+
joins(multi_email_association.name).where(multi_email_association.reflection.table_name => { email: email.downcase }).first
|
88
67
|
end
|
89
68
|
end
|
90
69
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'devise/multi_email/parent_model_extensions'
|
2
|
+
|
1
3
|
module Devise
|
2
4
|
module Models
|
3
5
|
module EmailConfirmable
|
@@ -11,7 +13,7 @@ module Devise
|
|
11
13
|
|
12
14
|
module ClassReplacementMethods
|
13
15
|
def allow_unconfirmed_access_for
|
14
|
-
0.
|
16
|
+
0.days
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -20,18 +22,25 @@ module Devise
|
|
20
22
|
extend ActiveSupport::Concern
|
21
23
|
|
22
24
|
included do
|
25
|
+
include Devise::MultiEmail::ParentModelExtensions
|
26
|
+
|
23
27
|
devise :confirmable
|
24
|
-
include InstanceReplacementMethods
|
25
|
-
extend ClassReplacementMethods
|
26
28
|
|
27
|
-
|
29
|
+
include ConfirmableExtensions
|
28
30
|
end
|
29
31
|
|
30
32
|
def self.required_fields(klass)
|
31
33
|
[]
|
32
34
|
end
|
33
35
|
|
34
|
-
module
|
36
|
+
module ConfirmableExtensions
|
37
|
+
extend ActiveSupport::Concern
|
38
|
+
|
39
|
+
included do
|
40
|
+
multi_email_association.include_module(EmailConfirmable)
|
41
|
+
end
|
42
|
+
|
43
|
+
# delegate before creating overriding methods
|
35
44
|
delegate :skip_confirmation!, :skip_confirmation_notification!, :skip_reconfirmation!, :confirmation_required?,
|
36
45
|
:confirmation_token, :confirmed_at, :confirmation_sent_at, :confirm, :confirmed?, :unconfirmed_email,
|
37
46
|
:reconfirmation_required?, :pending_reconfirmation?, to: :primary_email_record, allow_nil: true
|
@@ -58,7 +67,7 @@ module Devise
|
|
58
67
|
end
|
59
68
|
end
|
60
69
|
|
61
|
-
|
70
|
+
protected
|
62
71
|
|
63
72
|
# Overrides Devise::Models::Confirmable#postpone_email_change?
|
64
73
|
def postpone_email_change?
|
@@ -77,28 +86,18 @@ module Devise
|
|
77
86
|
def send_on_create_confirmation_instructions
|
78
87
|
end
|
79
88
|
|
80
|
-
|
89
|
+
private
|
81
90
|
|
82
91
|
def current_login_email_record
|
83
92
|
if respond_to?(:current_login_email) && current_login_email
|
84
|
-
|
93
|
+
multi_email.emails.find_by(email: current_login_email)
|
85
94
|
end
|
86
95
|
end
|
87
|
-
end
|
88
|
-
|
89
|
-
module ClassReplacementMethods
|
90
|
-
# Overrides Devise::Models::Confirmable.confirm_by_token
|
91
|
-
# Forward the logic to email.
|
92
|
-
def confirm_by_token(token)
|
93
|
-
email_class.confirm_by_token(token)
|
94
|
-
end
|
95
96
|
|
96
|
-
|
97
|
-
|
98
|
-
def send_confirmation_instructions(params)
|
99
|
-
email_class.send_confirmation_instructions(params)
|
97
|
+
module ClassMethods
|
98
|
+
delegate :confirm_by_token, :send_confirmation_instructions, to: 'multi_email_association.model_class', allow_nil: false
|
100
99
|
end
|
101
100
|
end
|
102
101
|
end
|
103
102
|
end
|
104
|
-
end
|
103
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
|
+
require 'devise/multi_email/parent_model_extensions'
|
2
|
+
|
1
3
|
module Devise
|
2
4
|
module Models
|
3
5
|
module EmailValidatable
|
4
|
-
|
5
|
-
base.extend ClassMethods
|
6
|
+
extend ActiveSupport::Concern
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
8
|
+
included do
|
9
|
+
validates_presence_of :email, if: :email_required?
|
10
|
+
validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
|
11
|
+
validates_format_of :email, with: email_regexp, allow_blank: true, if: :email_changed?
|
12
12
|
end
|
13
13
|
|
14
14
|
def email_required?
|
@@ -21,42 +21,31 @@ module Devise
|
|
21
21
|
end
|
22
22
|
|
23
23
|
module MultiEmailValidatable
|
24
|
-
|
25
|
-
[]
|
26
|
-
end
|
24
|
+
extend ActiveSupport::Concern
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
:validates_confirmation_of, :validates_length_of].freeze
|
26
|
+
included do
|
27
|
+
include Devise::MultiEmail::ParentModelExtensions
|
31
28
|
|
32
|
-
|
33
|
-
base.extend ClassMethods
|
34
|
-
assert_validations_api!(base)
|
29
|
+
assert_validations_api!(self)
|
35
30
|
|
36
|
-
|
37
|
-
validates_presence_of :email, if: :email_required?
|
31
|
+
validates_presence_of :email, if: :email_required?
|
38
32
|
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
validates_presence_of :password, if: :password_required?
|
34
|
+
validates_confirmation_of :password, if: :password_required?
|
35
|
+
validates_length_of :password, within: password_length, allow_blank: true
|
42
36
|
|
43
|
-
|
44
|
-
email_class.send :include, EmailValidatable
|
45
|
-
end
|
37
|
+
after_validation :propagate_email_errors
|
46
38
|
|
47
|
-
|
48
|
-
end
|
39
|
+
multi_email_association.include_module(EmailValidatable)
|
49
40
|
|
50
|
-
|
51
|
-
|
41
|
+
devise_modules << :validatable
|
42
|
+
end
|
52
43
|
|
53
|
-
|
54
|
-
|
55
|
-
"to the following methods: #{unavailable_validations.to_sentence}."
|
56
|
-
end
|
44
|
+
def self.required_fields(klass)
|
45
|
+
[]
|
57
46
|
end
|
58
47
|
|
59
|
-
|
48
|
+
protected
|
60
49
|
|
61
50
|
# Same as Devise::Models::Validatable#password_required?
|
62
51
|
def password_required?
|
@@ -68,15 +57,16 @@ module Devise
|
|
68
57
|
true
|
69
58
|
end
|
70
59
|
|
71
|
-
|
60
|
+
private
|
72
61
|
|
73
62
|
def propagate_email_errors
|
74
|
-
email_error_key = self.class
|
75
|
-
|
63
|
+
email_error_key = self.class.multi_email_association.name
|
64
|
+
|
65
|
+
if respond_to?("#{email_error_key}_attributes=")
|
76
66
|
email_error_key = "#{email_error_key}.email".to_sym
|
77
67
|
end
|
78
68
|
|
79
|
-
|
69
|
+
email_errors = errors.delete(email_error_key) || []
|
80
70
|
|
81
71
|
email_errors.each do |error|
|
82
72
|
errors.add(:email, error)
|
@@ -84,8 +74,22 @@ module Devise
|
|
84
74
|
end
|
85
75
|
|
86
76
|
module ClassMethods
|
77
|
+
|
78
|
+
# All validations used by this module.
|
79
|
+
VALIDATIONS = [:validates_presence_of, :validates_uniqueness_of, :validates_format_of,
|
80
|
+
:validates_confirmation_of, :validates_length_of].freeze
|
81
|
+
|
82
|
+
def assert_validations_api!(base) #:nodoc:
|
83
|
+
unavailable_validations = VALIDATIONS.select{ |v| !base.respond_to?(v) }
|
84
|
+
|
85
|
+
unless unavailable_validations.empty?
|
86
|
+
raise "Could not use :validatable module since #{base} does not respond " <<
|
87
|
+
"to the following methods: #{unavailable_validations.to_sentence}."
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
87
91
|
Devise::Models.config(self, :password_length)
|
88
92
|
end
|
89
93
|
end
|
90
94
|
end
|
91
|
-
end
|
95
|
+
end
|