aerogel-users 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|