aerogel-users 1.4.3
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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +16 -0
- data/Rakefile +1 -0
- data/aerogel-users.gemspec +30 -0
- data/app/helpers/access_control.rb +32 -0
- data/app/helpers/auth.rb +58 -0
- data/app/helpers/auth_login_providers.rb +18 -0
- data/app/mailers/user.rb +43 -0
- data/app/routes/access_control.rb +15 -0
- data/app/routes/auth.rb +53 -0
- data/app/routes/user.rb +192 -0
- data/assets/README.md +1 -0
- data/assets/javascripts/.gitkeep +0 -0
- data/assets/stylesheets/.gitkeep +0 -0
- data/config/auth.conf +43 -0
- data/config/development/.keep +0 -0
- data/config/production/.keep +0 -0
- data/db/model/access.rb +67 -0
- data/db/model/authentication.rb +54 -0
- data/db/model/role.rb +17 -0
- data/db/model/user.rb +223 -0
- data/db/model/user_email.rb +24 -0
- data/db/model/user_registration_form.rb +23 -0
- data/db/model/user_request_account_activation_form.rb +30 -0
- data/db/model/user_request_email_confirmation_form.rb +40 -0
- data/db/model/user_request_password_reset_form.rb +37 -0
- data/db/model/user_reset_password_form.rb +41 -0
- data/db/seed/01_user_role.seed +8 -0
- data/db/seed/02_access_user.seed +25 -0
- data/db/seed/development/.keep +0 -0
- data/db/seed/development/test-user.seed +77 -0
- data/db/seed/production/.keep +0 -0
- data/lib/aerogel/users.rb +22 -0
- data/lib/aerogel/users/auth.rb +67 -0
- data/lib/aerogel/users/omniauth-failure_endpoint_ex.rb +21 -0
- data/lib/aerogel/users/omniauth-password.rb +63 -0
- data/lib/aerogel/users/secure_password.rb +55 -0
- data/lib/aerogel/users/version.rb +5 -0
- data/locales/actions/en.yml +18 -0
- data/locales/actions/ru.yml +17 -0
- data/locales/auth/en.yml +22 -0
- data/locales/auth/ru.yml +22 -0
- data/locales/mailers/en.yml +69 -0
- data/locales/mailers/ru.yml +73 -0
- data/locales/models/en.yml +65 -0
- data/locales/models/ru.yml +64 -0
- data/locales/views/en.yml +122 -0
- data/locales/views/ru.yml +126 -0
- data/public/README.md +1 -0
- data/rake/README.md +3 -0
- data/views/mailers/user/account_activation.html.erb +3 -0
- data/views/mailers/user/account_activation.text.erb +3 -0
- data/views/mailers/user/email_confirmation.html.erb +3 -0
- data/views/mailers/user/email_confirmation.text.erb +3 -0
- data/views/mailers/user/password_reset.html.erb +3 -0
- data/views/mailers/user/password_reset.text.erb +3 -0
- data/views/user/activate_account.html.erb +3 -0
- data/views/user/activate_account_failure.html.erb +3 -0
- data/views/user/confirm_email.html.erb +3 -0
- data/views/user/confirm_email_failure.html.erb +3 -0
- data/views/user/edit.html.erb +6 -0
- data/views/user/index.html.erb +19 -0
- data/views/user/login.html.erb +3 -0
- data/views/user/login/_form.html.erb +28 -0
- data/views/user/login/_provider.html.erb +5 -0
- data/views/user/logout.html.erb +3 -0
- data/views/user/register.html.erb +10 -0
- data/views/user/register_success.html.erb +3 -0
- data/views/user/request_account_activation.html.erb +9 -0
- data/views/user/request_account_activation_success.html.erb +3 -0
- data/views/user/request_email_confirmation.html.erb +8 -0
- data/views/user/request_email_confirmation_success.html.erb +3 -0
- data/views/user/request_password_reset.html.erb +8 -0
- data/views/user/request_password_reset_success.html.erb +3 -0
- data/views/user/reset_password.html.erb +9 -0
- data/views/user/reset_password_success.html.erb +3 -0
- metadata +234 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
class UserRequestAccountActivationForm
|
2
|
+
|
3
|
+
include Model::NonPersistent
|
4
|
+
|
5
|
+
field :email, type: String
|
6
|
+
|
7
|
+
validates_presence_of :email
|
8
|
+
validates_format_of :email, with: /@/, message: :invalid_format
|
9
|
+
|
10
|
+
# validates uniqueness of provider & uid (email) among all users
|
11
|
+
validate do |record|
|
12
|
+
user = User.where( 'emails.email' => record.email ).first
|
13
|
+
unless user
|
14
|
+
record.errors.add :email, :not_registered
|
15
|
+
return
|
16
|
+
end
|
17
|
+
if user.activated?( record.email )
|
18
|
+
record.errors.add :base, :account_already_activated
|
19
|
+
return
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns UserEmail object, corresponding to this email address
|
24
|
+
#
|
25
|
+
def user
|
26
|
+
user = User.where( 'emails.email' => email ).first
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
end # class UserRequestAccountActivationForm
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class UserRequestEmailConfirmationForm
|
2
|
+
|
3
|
+
include Model::NonPersistent
|
4
|
+
|
5
|
+
field :email, type: String
|
6
|
+
|
7
|
+
validates_presence_of :email
|
8
|
+
validates_format_of :email, with: /@/, message: :invalid_format
|
9
|
+
|
10
|
+
# validates uniqueness of provider & uid (email) among all users
|
11
|
+
validate do |record|
|
12
|
+
user = User.where( 'emails.email' => record.email ).first
|
13
|
+
unless user
|
14
|
+
record.errors.add :email, :not_registered
|
15
|
+
return
|
16
|
+
end
|
17
|
+
user_email = user.emails.where( email: record.email ).first
|
18
|
+
unless user_email
|
19
|
+
record.errors.add :email, :invalid
|
20
|
+
return
|
21
|
+
end
|
22
|
+
if user_email.confirmed
|
23
|
+
record.errors.add :email, :already_confirmed
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns User object, corresponding to this email address
|
28
|
+
#
|
29
|
+
def user
|
30
|
+
User.where( 'emails.email' => email ).first
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns UserEmail object, corresponding to this email address
|
34
|
+
#
|
35
|
+
def user_email
|
36
|
+
user.emails.where( email: email ).first
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end # class UserRequestEmailConfirmationForm
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class UserRequestPasswordResetForm
|
2
|
+
|
3
|
+
include Model::NonPersistent
|
4
|
+
|
5
|
+
field :email, type: String
|
6
|
+
|
7
|
+
validates_presence_of :email
|
8
|
+
validates_format_of :email, with: /@/, message: :invalid_format
|
9
|
+
|
10
|
+
# validates uniqueness of provider & uid (email) among all users
|
11
|
+
validate do |record|
|
12
|
+
user = User.where( 'emails.email' => record.email ).first
|
13
|
+
unless user
|
14
|
+
record.errors.add :email, :not_registered
|
15
|
+
return
|
16
|
+
end
|
17
|
+
authentication = user.authentications.where( provider: :password, uid: record.email ).first
|
18
|
+
unless authentication
|
19
|
+
record.errors.add :email, :password_login_not_allowed
|
20
|
+
return
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns User object, corresponding to this email address
|
25
|
+
#
|
26
|
+
def user
|
27
|
+
User.where( 'emails.email' => email ).first
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns UserEmail object, corresponding to this email address
|
31
|
+
#
|
32
|
+
def authentication
|
33
|
+
user.authentications.where( provider: :password, uid: email ).first
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
end # class UserRequestPasswordResetForm
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class UserResetPasswordForm
|
2
|
+
|
3
|
+
include Model::NonPersistent
|
4
|
+
include Aerogel::Db::SecurePassword
|
5
|
+
|
6
|
+
field :email, type: String
|
7
|
+
field :password_reset_token, type: String
|
8
|
+
|
9
|
+
use_secure_password
|
10
|
+
|
11
|
+
validates_presence_of :email, :password_reset_token
|
12
|
+
validates_format_of :email, with: /@/, message: :invalid_format
|
13
|
+
|
14
|
+
# validates uniqueness of provider & uid (email) among all users
|
15
|
+
validate do |record|
|
16
|
+
user = User.where( 'emails.email' => record.email ).first
|
17
|
+
unless user
|
18
|
+
record.errors.add :email, :not_registered
|
19
|
+
return
|
20
|
+
end
|
21
|
+
authentication = user.authentications.where( provider: :password, uid: record.email ).first
|
22
|
+
unless authentication
|
23
|
+
record.errors.add :email, :password_login_not_allowed
|
24
|
+
return
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns User object, corresponding to this email address
|
29
|
+
#
|
30
|
+
def user
|
31
|
+
User.where( 'emails.email' => email ).first
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns UserEmail object, corresponding to this email address
|
35
|
+
#
|
36
|
+
def authentication
|
37
|
+
user.authentications.where( provider: :password, uid: email ).first
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
end # class UserRequestPasswordResetForm
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# A .seed file is a .conf file which stores
|
2
|
+
# database seed data and rules.
|
3
|
+
#
|
4
|
+
|
5
|
+
# Model class to use
|
6
|
+
#
|
7
|
+
# ! required
|
8
|
+
model Access
|
9
|
+
|
10
|
+
# Attribute name or a list of attribute names to be used as key(s)
|
11
|
+
# when finding objects
|
12
|
+
#
|
13
|
+
# Usage:
|
14
|
+
# find_by :name
|
15
|
+
# or
|
16
|
+
# find_by [:first_name, :last_name]
|
17
|
+
#
|
18
|
+
# ! required
|
19
|
+
find_by [:path, :role]
|
20
|
+
|
21
|
+
seeds [
|
22
|
+
{ path: '/user', access: :R, role: :user },
|
23
|
+
{ path: '/user/edit', access: :RW, role: :user }
|
24
|
+
]
|
25
|
+
|
File without changes
|
@@ -0,0 +1,77 @@
|
|
1
|
+
model User
|
2
|
+
|
3
|
+
# Attribute name or a list of attribute names to be used as key(s)
|
4
|
+
# when finding objects
|
5
|
+
#
|
6
|
+
# Usage:
|
7
|
+
# find_by :name
|
8
|
+
# or
|
9
|
+
# find_by [:first_name, :last_name]
|
10
|
+
#
|
11
|
+
# ! required
|
12
|
+
find_by :full_name
|
13
|
+
|
14
|
+
# Values of attributes listed here will be set even
|
15
|
+
# if they exist already in the matching database object.
|
16
|
+
#
|
17
|
+
# Other attributes in the seed data will be treated as a default value,
|
18
|
+
# i.e. they will only be set if the matching database object does not exist
|
19
|
+
# or its corresponding attribute is not set.
|
20
|
+
#
|
21
|
+
# Usage:
|
22
|
+
# force :value
|
23
|
+
# or:
|
24
|
+
# force [:value, :description]
|
25
|
+
#
|
26
|
+
# default is: no fields are forced
|
27
|
+
|
28
|
+
#force :value
|
29
|
+
|
30
|
+
seeds [
|
31
|
+
{
|
32
|
+
full_name: 'test',
|
33
|
+
roles: [:user],
|
34
|
+
emails:[{
|
35
|
+
email: 'test@test',
|
36
|
+
confirmed: true
|
37
|
+
}],
|
38
|
+
authentications:[{
|
39
|
+
provider: :password,
|
40
|
+
uid: 'test@test',
|
41
|
+
email_id: 'test@test',
|
42
|
+
password: 'test',
|
43
|
+
password_confirmation: 'test'
|
44
|
+
}]
|
45
|
+
},
|
46
|
+
{
|
47
|
+
full_name: 'test1',
|
48
|
+
roles: [:user],
|
49
|
+
emails:[{
|
50
|
+
email: 'test1@test',
|
51
|
+
confirmed: true
|
52
|
+
}],
|
53
|
+
authentications:[{
|
54
|
+
provider: :password,
|
55
|
+
uid: 'test1@test',
|
56
|
+
email_id: 'test1@test',
|
57
|
+
password: 'test',
|
58
|
+
password_confirmation: 'test'
|
59
|
+
}]
|
60
|
+
},
|
61
|
+
{
|
62
|
+
full_name: 'test2',
|
63
|
+
roles: [:user],
|
64
|
+
emails:[{
|
65
|
+
email: 'test2@test',
|
66
|
+
confirmed: true
|
67
|
+
}],
|
68
|
+
authentications:[{
|
69
|
+
provider: :password,
|
70
|
+
uid: 'test2@test',
|
71
|
+
email_id: 'test2@test',
|
72
|
+
password: 'test',
|
73
|
+
password_confirmation: 'test'
|
74
|
+
}]
|
75
|
+
}
|
76
|
+
]
|
77
|
+
|
File without changes
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'omniauth'
|
2
|
+
require 'aerogel/core'
|
3
|
+
require 'aerogel/mailer'
|
4
|
+
require "aerogel/users/version"
|
5
|
+
require "aerogel/users/auth"
|
6
|
+
require "aerogel/users/omniauth-password"
|
7
|
+
require "aerogel/users/omniauth-failure_endpoint_ex"
|
8
|
+
require "aerogel/users/secure_password"
|
9
|
+
|
10
|
+
module Aerogel
|
11
|
+
module Users
|
12
|
+
# Your code goes here...
|
13
|
+
end
|
14
|
+
|
15
|
+
# Finally, register module's root folder
|
16
|
+
register_path File.join( File.dirname(__FILE__), '..', '..' )
|
17
|
+
|
18
|
+
on_load do |app|
|
19
|
+
Aerogel::Auth.load_middleware( app )
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Aerogel
|
2
|
+
module Auth
|
3
|
+
|
4
|
+
# known providers
|
5
|
+
# PROVIDERS = {
|
6
|
+
# password: { name: "Password", gem: nil },
|
7
|
+
# github: { name: "GitHub", gem: 'omniauth-github' },
|
8
|
+
# facebook: { name: "Facebook", gem: 'omniauth-facebook' },
|
9
|
+
# twitter: { name: "Twitter", gem: 'omniauth-twitter' },
|
10
|
+
# linkedin: { name: "LinkedIn", gem: 'omniauth-linkedin-oauth2' },
|
11
|
+
# vkontakte: { name: "Vkontakte", gem: 'omniauth-vkontakte' }
|
12
|
+
# }
|
13
|
+
#
|
14
|
+
PROVIDERS = nil
|
15
|
+
|
16
|
+
# Returns hash of registered omniauth providers.
|
17
|
+
#
|
18
|
+
def self.providers
|
19
|
+
return @providers unless @providers.nil?
|
20
|
+
@providers = Aerogel.config.auth.providers.to_hash
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns list of enabled omniauth providers as symbols.
|
24
|
+
#
|
25
|
+
# Example:
|
26
|
+
# Aerogel::Auth.enabled_providers # => [:password, :github, :twitter]
|
27
|
+
#
|
28
|
+
def self.enabled_providers
|
29
|
+
return @enabled_providers unless @enabled_providers.nil?
|
30
|
+
@enabled_providers = []
|
31
|
+
providers.each do |provider, opts|
|
32
|
+
# always enable :password
|
33
|
+
next unless provider == :password || Aerogel.config.auth.send( :"#{provider}?" )
|
34
|
+
@enabled_providers << provider
|
35
|
+
end
|
36
|
+
@enabled_providers
|
37
|
+
end
|
38
|
+
|
39
|
+
# Loads gems for enabled providers.
|
40
|
+
#
|
41
|
+
def self.load_provider_gems
|
42
|
+
enabled_providers.each do |provider_key|
|
43
|
+
gem_name = providers[provider_key][:gem_name]
|
44
|
+
# puts "** requiring #{provider_key}: #{gem_name}"
|
45
|
+
require gem_name if gem_name
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Loads OmniAuth middleware with enabled providers.
|
50
|
+
#
|
51
|
+
def self.load_middleware( app )
|
52
|
+
load_provider_gems
|
53
|
+
app.use OmniAuth::Builder do
|
54
|
+
# puts "** configuring OmniAuth"
|
55
|
+
provider :password, model: User
|
56
|
+
Aerogel::Auth.enabled_providers.each do |provider_key|
|
57
|
+
next if provider_key == :password
|
58
|
+
provider_config = app.config.auth.send(provider_key)
|
59
|
+
provider provider_key, provider_config.api_key!, provider_config.api_secret!
|
60
|
+
# puts "** configuring #{provider_key}: #{provider_config.api_key!}"
|
61
|
+
end
|
62
|
+
on_failure {|env| OmniAuth::FailureEndpointEx.new(env).redirect_to_failure }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end # module Auth
|
67
|
+
end # module Aerogel
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Alternative FailureEndpoint for OmniAuth,
|
2
|
+
# which preserves all parameters passed to provider/callback
|
3
|
+
#
|
4
|
+
module OmniAuth
|
5
|
+
class FailureEndpointEx < FailureEndpoint
|
6
|
+
|
7
|
+
def redirect_to_failure
|
8
|
+
message_key = env['omniauth.error.type']
|
9
|
+
new_path = "#{env['SCRIPT_NAME']}#{OmniAuth.config.path_prefix}/failure?message=#{message_key}#{origin_query_param}#{strategy_name_query_param}#{extra_query_param}"
|
10
|
+
Rack::Response.new(["302 Moved"], 302, 'Location' => new_path).finish
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns extra query params passed to callback.
|
14
|
+
#
|
15
|
+
def extra_query_param
|
16
|
+
return "" unless env['omniauth.params']
|
17
|
+
env['omniauth.params'].map{|k,v| "&#{k}=#{Rack::Utils.escape(v)}"}.join
|
18
|
+
end
|
19
|
+
|
20
|
+
end # class FailureEndpointEx < FailureEndpoint
|
21
|
+
end # module OmniAuth
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'omniauth'
|
2
|
+
|
3
|
+
module OmniAuth
|
4
|
+
module Strategies
|
5
|
+
class Password
|
6
|
+
include OmniAuth::Strategy
|
7
|
+
|
8
|
+
PROVIDER_NAME = :password
|
9
|
+
|
10
|
+
option :username_field, :email
|
11
|
+
option :password_field, :password
|
12
|
+
option :uid_field, :email
|
13
|
+
if defined? User
|
14
|
+
option :model, User
|
15
|
+
else
|
16
|
+
option :model, nil
|
17
|
+
end
|
18
|
+
option :authenticate_method, :authenticate
|
19
|
+
|
20
|
+
option :on_authenticate, ->(params) {
|
21
|
+
options.model.send( options.authenticate_method, PROVIDER_NAME, params )
|
22
|
+
}
|
23
|
+
|
24
|
+
|
25
|
+
# def request_phase
|
26
|
+
# form = OmniAuth::Form.new(:title => "User Info", :url => callback_path)
|
27
|
+
# [ options.username_field, options.password_field ].each do |field|
|
28
|
+
# form.text_field field.to_s.capitalize.gsub("_", " "), field.to_s
|
29
|
+
# end
|
30
|
+
# form.button "Sign In"
|
31
|
+
# form.to_response
|
32
|
+
# end
|
33
|
+
|
34
|
+
def callback_phase
|
35
|
+
request.params['uid'] = uid
|
36
|
+
request.env['omniauth.origin'] ||= request.params['origin']
|
37
|
+
request.env['omniauth.params'] = request.params
|
38
|
+
unless instance_exec( request.params, &options.on_authenticate )
|
39
|
+
return fail!(:invalid_credentials)
|
40
|
+
end
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
uid do
|
45
|
+
if options.uid_field.is_a? Proc
|
46
|
+
options.uid_field.call( request.params )
|
47
|
+
else
|
48
|
+
request.params[options.uid_field.to_s]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
info do
|
53
|
+
hash = {}
|
54
|
+
[ options.username_field, options.password_field ].each do |field|
|
55
|
+
hash[field] = request.params[field.to_s]
|
56
|
+
end
|
57
|
+
hash
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
end # class Password
|
62
|
+
end # module Strategies
|
63
|
+
end # module OmniAuth
|