aerogel-users 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +16 -0
  6. data/Rakefile +1 -0
  7. data/aerogel-users.gemspec +30 -0
  8. data/app/helpers/access_control.rb +32 -0
  9. data/app/helpers/auth.rb +58 -0
  10. data/app/helpers/auth_login_providers.rb +18 -0
  11. data/app/mailers/user.rb +43 -0
  12. data/app/routes/access_control.rb +15 -0
  13. data/app/routes/auth.rb +53 -0
  14. data/app/routes/user.rb +192 -0
  15. data/assets/README.md +1 -0
  16. data/assets/javascripts/.gitkeep +0 -0
  17. data/assets/stylesheets/.gitkeep +0 -0
  18. data/config/auth.conf +43 -0
  19. data/config/development/.keep +0 -0
  20. data/config/production/.keep +0 -0
  21. data/db/model/access.rb +67 -0
  22. data/db/model/authentication.rb +54 -0
  23. data/db/model/role.rb +17 -0
  24. data/db/model/user.rb +223 -0
  25. data/db/model/user_email.rb +24 -0
  26. data/db/model/user_registration_form.rb +23 -0
  27. data/db/model/user_request_account_activation_form.rb +30 -0
  28. data/db/model/user_request_email_confirmation_form.rb +40 -0
  29. data/db/model/user_request_password_reset_form.rb +37 -0
  30. data/db/model/user_reset_password_form.rb +41 -0
  31. data/db/seed/01_user_role.seed +8 -0
  32. data/db/seed/02_access_user.seed +25 -0
  33. data/db/seed/development/.keep +0 -0
  34. data/db/seed/development/test-user.seed +77 -0
  35. data/db/seed/production/.keep +0 -0
  36. data/lib/aerogel/users.rb +22 -0
  37. data/lib/aerogel/users/auth.rb +67 -0
  38. data/lib/aerogel/users/omniauth-failure_endpoint_ex.rb +21 -0
  39. data/lib/aerogel/users/omniauth-password.rb +63 -0
  40. data/lib/aerogel/users/secure_password.rb +55 -0
  41. data/lib/aerogel/users/version.rb +5 -0
  42. data/locales/actions/en.yml +18 -0
  43. data/locales/actions/ru.yml +17 -0
  44. data/locales/auth/en.yml +22 -0
  45. data/locales/auth/ru.yml +22 -0
  46. data/locales/mailers/en.yml +69 -0
  47. data/locales/mailers/ru.yml +73 -0
  48. data/locales/models/en.yml +65 -0
  49. data/locales/models/ru.yml +64 -0
  50. data/locales/views/en.yml +122 -0
  51. data/locales/views/ru.yml +126 -0
  52. data/public/README.md +1 -0
  53. data/rake/README.md +3 -0
  54. data/views/mailers/user/account_activation.html.erb +3 -0
  55. data/views/mailers/user/account_activation.text.erb +3 -0
  56. data/views/mailers/user/email_confirmation.html.erb +3 -0
  57. data/views/mailers/user/email_confirmation.text.erb +3 -0
  58. data/views/mailers/user/password_reset.html.erb +3 -0
  59. data/views/mailers/user/password_reset.text.erb +3 -0
  60. data/views/user/activate_account.html.erb +3 -0
  61. data/views/user/activate_account_failure.html.erb +3 -0
  62. data/views/user/confirm_email.html.erb +3 -0
  63. data/views/user/confirm_email_failure.html.erb +3 -0
  64. data/views/user/edit.html.erb +6 -0
  65. data/views/user/index.html.erb +19 -0
  66. data/views/user/login.html.erb +3 -0
  67. data/views/user/login/_form.html.erb +28 -0
  68. data/views/user/login/_provider.html.erb +5 -0
  69. data/views/user/logout.html.erb +3 -0
  70. data/views/user/register.html.erb +10 -0
  71. data/views/user/register_success.html.erb +3 -0
  72. data/views/user/request_account_activation.html.erb +9 -0
  73. data/views/user/request_account_activation_success.html.erb +3 -0
  74. data/views/user/request_email_confirmation.html.erb +8 -0
  75. data/views/user/request_email_confirmation_success.html.erb +3 -0
  76. data/views/user/request_password_reset.html.erb +8 -0
  77. data/views/user/request_password_reset_success.html.erb +3 -0
  78. data/views/user/reset_password.html.erb +9 -0
  79. data/views/user/reset_password_success.html.erb +3 -0
  80. 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,8 @@
1
+ model Role
2
+
3
+ find_by [:slug]
4
+
5
+ seeds [
6
+ { slug: :user, name: "Registered user" }
7
+ ]
8
+
@@ -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