token_authenticate_me 0.4.3 → 0.5.0

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.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/{LICENSE → MIT-LICENSE} +1 -1
  3. data/Rakefile +27 -11
  4. data/app/controllers/token_authenticate_me/api/v1/base_controller.rb +9 -0
  5. data/app/controllers/token_authenticate_me/api/v1/invites_controller.rb +14 -0
  6. data/app/controllers/token_authenticate_me/api/v1/password_resets_controller.rb +11 -0
  7. data/app/controllers/token_authenticate_me/api/v1/sessions_controller.rb +11 -0
  8. data/app/controllers/token_authenticate_me/api/v1/users_controller.rb +17 -0
  9. data/app/controllers/token_authenticate_me/application_controller.rb +5 -0
  10. data/app/helpers/token_authenticate_me/application_helper.rb +4 -0
  11. data/app/mailers/token_authenticate_me_mailer.rb +16 -9
  12. data/app/models/token_authenticate_me/invite.rb +11 -0
  13. data/app/models/token_authenticate_me/session.rb +8 -0
  14. data/app/models/token_authenticate_me/user.rb +11 -0
  15. data/app/views/token_authenticate_me_mailer/invite_user_email.html.erb +0 -0
  16. data/config/routes.rb +23 -0
  17. data/db/migrate/20160620184327_create_token_authenticate_me_invites.rb +14 -0
  18. data/db/migrate/20160621211347_create_token_authenticate_me_users.rb +18 -0
  19. data/db/migrate/20160622203801_create_token_authenticate_me_sessions.rb +14 -0
  20. data/lib/generators/token_authenticate_me/controllers/controllers_generator.rb +1 -76
  21. data/lib/generators/token_authenticate_me/install/install_generator.rb +9 -3
  22. data/lib/generators/token_authenticate_me/models/models_generator.rb +1 -59
  23. data/lib/generators/token_authenticate_me/policies/policies_generator.rb +15 -0
  24. data/lib/generators/token_authenticate_me/policies/templates/invite_policy.rb +31 -0
  25. data/lib/generators/token_authenticate_me/policies/templates/user_policy.rb +23 -0
  26. data/lib/tasks/token_authenticate_me_tasks.rake +4 -0
  27. data/lib/token_authenticate_me.rb +11 -0
  28. data/lib/token_authenticate_me/concerns/controllers/invitable.rb +58 -0
  29. data/lib/token_authenticate_me/concerns/controllers/password_resetable.rb +97 -0
  30. data/lib/token_authenticate_me/concerns/controllers/sessionable.rb +55 -0
  31. data/lib/token_authenticate_me/concerns/controllers/token_authenticateable.rb +45 -0
  32. data/lib/token_authenticate_me/concerns/models/authenticatable.rb +102 -0
  33. data/lib/token_authenticate_me/concerns/models/invitable.rb +20 -0
  34. data/lib/token_authenticate_me/concerns/models/sessionable.rb +44 -0
  35. data/lib/token_authenticate_me/configuration.rb +16 -0
  36. data/lib/token_authenticate_me/engine.rb +2 -2
  37. data/lib/token_authenticate_me/models.rb +4 -0
  38. data/lib/token_authenticate_me/version.rb +1 -1
  39. data/test/dummy/README.rdoc +28 -0
  40. data/test/dummy/Rakefile +6 -0
  41. data/test/dummy/app/assets/javascripts/application.js +13 -0
  42. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  43. data/{spec/internal → test/dummy}/app/controllers/application_controller.rb +0 -0
  44. data/test/dummy/app/helpers/application_helper.rb +2 -0
  45. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  46. data/test/dummy/bin/bundle +3 -0
  47. data/test/dummy/bin/rails +4 -0
  48. data/test/dummy/bin/rake +4 -0
  49. data/test/dummy/bin/setup +29 -0
  50. data/test/dummy/config.ru +4 -0
  51. data/test/dummy/config/application.rb +25 -0
  52. data/test/dummy/config/boot.rb +5 -0
  53. data/test/dummy/config/database.yml +25 -0
  54. data/test/dummy/config/environment.rb +5 -0
  55. data/test/dummy/config/environments/development.rb +41 -0
  56. data/test/dummy/config/environments/production.rb +79 -0
  57. data/test/dummy/config/environments/test.rb +42 -0
  58. data/test/dummy/config/initializers/assets.rb +11 -0
  59. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  60. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  61. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  62. data/test/dummy/config/initializers/inflections.rb +16 -0
  63. data/test/dummy/config/initializers/mime_types.rb +4 -0
  64. data/test/dummy/config/initializers/session_store.rb +3 -0
  65. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  66. data/test/dummy/config/locales/en.yml +23 -0
  67. data/test/dummy/config/routes.rb +3 -0
  68. data/test/dummy/config/secrets.yml +22 -0
  69. data/test/dummy/log/test.log +0 -0
  70. data/test/dummy/public/404.html +67 -0
  71. data/test/dummy/public/422.html +67 -0
  72. data/test/dummy/public/500.html +66 -0
  73. data/test/dummy/public/favicon.ico +0 -0
  74. data/test/fixtures/token_authenticate_me/invites.yml +11 -0
  75. data/test/fixtures/token_authenticate_me/sessions.yml +11 -0
  76. data/test/fixtures/token_authenticate_me/users.yml +11 -0
  77. data/test/integration/navigation_test.rb +7 -0
  78. data/test/models/token_authenticate_me/invite_test.rb +9 -0
  79. data/test/models/token_authenticate_me/session_test.rb +9 -0
  80. data/test/models/token_authenticate_me/user_test.rb +9 -0
  81. data/test/test_helper.rb +21 -0
  82. data/test/token_authenticate_me_test.rb +7 -0
  83. metadata +129 -160
  84. data/.editorconfig +0 -41
  85. data/.gitignore +0 -4
  86. data/.rubocop.yml +0 -8
  87. data/CHANGELOG.md +0 -2
  88. data/Gemfile +0 -7
  89. data/config.ru +0 -7
  90. data/lib/generators/token_authenticate_me/controllers/templates/password_reset.rb +0 -6
  91. data/lib/generators/token_authenticate_me/controllers/templates/sessions.rb +0 -6
  92. data/lib/generators/token_authenticate_me/controllers/templates/users.rb +0 -8
  93. data/lib/generators/token_authenticate_me/models/templates/authentication_migration.rb +0 -20
  94. data/lib/generators/token_authenticate_me/models/templates/authentication_model.rb +0 -11
  95. data/lib/generators/token_authenticate_me/models/templates/session_migration.rb +0 -17
  96. data/lib/generators/token_authenticate_me/models/templates/session_model.rb +0 -12
  97. data/lib/token_authenticate_me/controllers/password_resetable.rb +0 -95
  98. data/lib/token_authenticate_me/controllers/sessionable.rb +0 -53
  99. data/lib/token_authenticate_me/controllers/token_authenticateable.rb +0 -52
  100. data/lib/token_authenticate_me/models/authenticatable.rb +0 -93
  101. data/lib/token_authenticate_me/models/sessionable.rb +0 -36
  102. data/spec/acceptance/password_reset_api_spec.rb +0 -111
  103. data/spec/acceptance/session_api_spec.rb +0 -95
  104. data/spec/acceptance/users_api_spec.rb +0 -70
  105. data/spec/internal/app/controllers/password_resets_controller.rb +0 -5
  106. data/spec/internal/app/controllers/sessions_controller.rb +0 -5
  107. data/spec/internal/app/controllers/users_controller.rb +0 -7
  108. data/spec/internal/app/models/session.rb +0 -11
  109. data/spec/internal/app/models/user.rb +0 -11
  110. data/spec/internal/app/policies/user_policy.rb +0 -29
  111. data/spec/internal/app/serializers/user_serializer.rb +0 -3
  112. data/spec/internal/config/database.yml +0 -3
  113. data/spec/internal/config/routes.rb +0 -13
  114. data/spec/internal/db/fixtures/users.rb +0 -11
  115. data/spec/internal/db/schema.rb +0 -19
  116. data/spec/spec_helper.rb +0 -38
  117. data/token_authenticate_me.gemspec +0 -32
data/.rubocop.yml DELETED
@@ -1,8 +0,0 @@
1
- AllCops:
2
- Exclude:
3
- - '**/templates/*'
4
- - '*.gemspec'
5
- LineLength:
6
- Max: 100
7
- Documentation:
8
- Enabled: false
data/CHANGELOG.md DELETED
@@ -1,2 +0,0 @@
1
- ## 0.4.2 / 2015-09-08
2
- * [BUGFIX] fixed bug #26.
data/Gemfile DELETED
@@ -1,7 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
4
-
5
- group :test do
6
- gem 'active_model_serializers', '~> 0.8.0'
7
- end
data/config.ru DELETED
@@ -1,7 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler'
3
-
4
- Bundler.require :default, :development
5
-
6
- Combustion.initialize!
7
- run Combustion::Application
@@ -1,6 +0,0 @@
1
- require 'token_authenticate_me/controllers/password_resetable'
2
-
3
- class Api::PasswordResetsController < ApplicationController
4
- include TokenAuthenticateMe::Controllers::PasswordResetable
5
-
6
- end
@@ -1,6 +0,0 @@
1
- require 'token_authenticate_me/controllers/sessionable'
2
-
3
- class Api::SessionsController < ApplicationController
4
- include TokenAuthenticateMe::Controllers::Sessionable
5
-
6
- end
@@ -1,8 +0,0 @@
1
- require 'token_authenticate_me/controllers/token_authenticateable'
2
-
3
- class Api::V1::UsersController < ApplicationController
4
- include ApiMe
5
- include TokenAuthenticateMe::Controllers::TokenAuthenticateable
6
-
7
- skip_before_action :authenticate, only: [:create]
8
- end
@@ -1,20 +0,0 @@
1
- class CreateUsers < ActiveRecord::Migration
2
- def up
3
- create_table :users do |t|
4
- t.string :username, null: false
5
- t.string :email, null: false
6
- t.string :password_digest, null: false
7
- t.string :reset_password_token
8
- t.datetime :reset_password_token_exp
9
- t.timestamps
10
- end
11
-
12
- add_index :users, :email, unique: true
13
- add_index :users, :username, unique: true
14
- add_index :users, :reset_password_token, unique: true
15
- end
16
-
17
- def down
18
- drop_table :users
19
- end
20
- end
@@ -1,11 +0,0 @@
1
- require 'token_authenticate_me/models/authenticatable'
2
-
3
- class User < ActiveRecord::Base
4
- include TokenAuthenticateMe::Models::Authenticatable
5
-
6
- has_many :<%= session_model_plural_name %>
7
-
8
- def as_json(options=nil)
9
- { <%= authenticate_model_singular_name %>: super(options) }
10
- end
11
- end
@@ -1,17 +0,0 @@
1
- class CreateSessions < ActiveRecord::Migration
2
- def up
3
- create_table :sessions do |t|
4
- t.string :key, null: false
5
- t.datetime :expiration
6
- t.integer :user_id
7
-
8
- t.timestamps
9
- end
10
-
11
- add_index :sessions, :key, unique: true
12
- end
13
-
14
- def down
15
- drop_table :sessions
16
- end
17
- end
@@ -1,12 +0,0 @@
1
- require 'token_authenticate_me/models/sessionable'
2
-
3
- class Session < ActiveRecord::Base
4
- include TokenAuthenticateMe::Models::Sessionable
5
-
6
- belongs_to :<%= authenticate_model_singular_name %>
7
-
8
- def as_json(options={})
9
- { <%= session_model_singular_name %>: super({ include: :<%= authenticate_model_singular_name %> }.merge(options)) }
10
- end
11
-
12
- end
@@ -1,95 +0,0 @@
1
- require 'active_support/concern'
2
-
3
- require 'token_authenticate_me/controllers/token_authenticateable'
4
-
5
- module TokenAuthenticateMe
6
- module Controllers
7
- module PasswordResetable
8
- extend ActiveSupport::Concern
9
-
10
- included do
11
- include TokenAuthenticateMe::Controllers::TokenAuthenticateable
12
-
13
- skip_before_action :authenticate, only: [:create, :update]
14
- before_action :validate_reset_token, only: [:update]
15
-
16
- # Send reset token to user with e-mail address
17
- def create
18
- @user = User.find_by_email(params[:email])
19
-
20
- if @user
21
- send_valid_reset_email(@user)
22
- else
23
- send_invalid_reset_email(params[:email])
24
- end
25
-
26
- render status: 204, nothing: true
27
- end
28
-
29
- # Allow user to reset password when the token is valid
30
- # and not expired
31
- def update
32
- @user.update!(
33
- password: params[:password],
34
- password_confirmation: params[:password_confirmation],
35
- reset_password_token: nil,
36
- reset_password_token_exp: nil
37
- )
38
-
39
- render status: 204, nothing: true
40
- rescue ActiveRecord::RecordInvalid => e
41
- handle_errors(e)
42
- end
43
-
44
- private
45
-
46
- def send_valid_reset_email(user)
47
- user.create_reset_token!
48
-
49
- TokenAuthenticateMeMailer.valid_user_reset_password_email(
50
- request.base_url,
51
- user
52
- ).deliver
53
- end
54
-
55
- def send_invalid_reset_email(email)
56
- TokenAuthenticateMeMailer.invalid_user_reset_password_email(
57
- request.base_url,
58
- email
59
- ).deliver
60
- end
61
-
62
- def session_params
63
- params.permit(:password, :password_confirmation)
64
- end
65
-
66
- def render_errors(errors, status = 422)
67
- render(json: { errors: errors }, status: status)
68
- end
69
-
70
- def handle_errors(e)
71
- render_errors(e.record.errors.messages)
72
- end
73
-
74
- def validate_reset_token
75
- valid_reset_token? || render_not_found
76
- end
77
-
78
- def render_not_found
79
- render status: 404, nothing: true
80
- end
81
-
82
- def valid_reset_token?
83
- # Check for
84
- # https://github.com/rails/rails/commit/e8572cf2f94872d81e7145da31d55c6e1b074247
85
- # security issue when config.action_dispatch.perform_deep_munge = false is set
86
- # which is common for JSON APIs
87
- return false if params[:id].class == Array || params[:id].nil?
88
-
89
- @user = User.find_by_reset_password_token(params[:id])
90
- @user && @user.reset_password_token_exp > DateTime.now
91
- end
92
- end
93
- end
94
- end
95
- end
@@ -1,53 +0,0 @@
1
- require 'active_support/concern'
2
-
3
- require 'token_authenticate_me/controllers/token_authenticateable'
4
-
5
- module TokenAuthenticateMe
6
- module Controllers
7
- module Sessionable
8
- extend ActiveSupport::Concern
9
-
10
- include TokenAuthenticateMe::Controllers::TokenAuthenticateable
11
-
12
- included do
13
- skip_before_action :authenticate, only: [:create]
14
- after_action :cleanup_sessions, only: [:destroy]
15
-
16
- def create
17
- resource = User.where('username=? OR email=?', params[:username], params[:username]).first
18
- if resource && resource.authenticate(params[:password])
19
- @session = Session.create(user_id: resource.id)
20
- render json: @session, status: 201
21
- else
22
- render json: { message: 'Bad credentials' }, status: 401
23
- end
24
- end
25
-
26
- def show
27
- @session = authenticate_token
28
- render json: @session
29
- end
30
-
31
- def destroy
32
- authenticate_token.destroy
33
-
34
- render status: 204, nothing: true
35
- rescue
36
- render_unauthorized
37
- end
38
-
39
- private
40
-
41
- def session_params
42
- params.permit(:username, :email, :password)
43
- end
44
-
45
- def cleanup_sessions
46
- ApiSession.where('expiration < ?', DateTime.now).delete_all
47
- rescue
48
- Rails.logger.warn 'Error cleaning up old authentication sessions'
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,52 +0,0 @@
1
- require 'active_support/concern'
2
-
3
- module TokenAuthenticateMe
4
- module Controllers
5
- module TokenAuthenticateable
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- before_action :authenticate
10
- end
11
-
12
- protected
13
-
14
- def authenticate
15
- authenticate_token || render_unauthorized
16
- end
17
-
18
- def current_user
19
- if authenticate_token
20
- @current_user ||= User.find_by_id(authenticate_token.user_id)
21
- else
22
- nil
23
- end
24
- end
25
-
26
- def authenticate_token
27
- @session ||= (
28
- authenticate_with_http_token(&method(:token_handler)) || authenticate_with_params
29
- )
30
- end
31
-
32
- def authenticate_with_params
33
- token = params[:authentication_token]
34
- token_handler(token, {})
35
- end
36
-
37
- def render_unauthorized
38
- headers['WWW-Authenticate'] = 'Token realm="Application"'
39
- render json: 'Bad credentials', status: 401
40
- end
41
-
42
- def token_handler(token, _options)
43
- session = Session.find_by_key(token)
44
- if session && session.expiration > DateTime.now
45
- session
46
- else
47
- false
48
- end
49
- end
50
- end
51
- end
52
- end
@@ -1,93 +0,0 @@
1
- require 'active_support/concern'
2
-
3
- module TokenAuthenticateMe
4
- module Models
5
- module Authenticatable
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- has_secure_password validations: false
10
- attr_accessor :current_password
11
-
12
- validates(
13
- :email,
14
- presence: true,
15
- uniqueness: { case_sensitive: false },
16
- format: {
17
- with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i,
18
- message: 'invalid e-mail address'
19
- }
20
- )
21
-
22
- validates(
23
- :username,
24
- format: { with: /\A[a-zA-Z0-9]+\Z/ },
25
- presence: true,
26
- uniqueness: { case_sensitive: false }
27
- )
28
-
29
- validates(
30
- :password,
31
- presence: true,
32
- length: { in: 8..72 },
33
- confirmation: true,
34
- if: :password_required?
35
- )
36
-
37
- validate(
38
- :current_password_correct,
39
- if: :current_password_required?
40
- )
41
-
42
- def attributes
43
- {
44
- 'id' => id,
45
- 'username' => username,
46
- 'email' => email,
47
- 'created_at' => created_at,
48
- 'updated_at' => updated_at
49
- }
50
- end
51
-
52
- def create_reset_token!
53
- # rubocop:disable Lint/Loop
54
- begin
55
- self.reset_password_token = SecureRandom.hex
56
- end while self.class.exists?(reset_password_token: reset_password_token)
57
-
58
- self.reset_password_token_exp = password_expiration_hours.hours.from_now
59
- self.save!
60
- end
61
-
62
- def password_expiration_hours
63
- 8
64
- end
65
-
66
- def password=(unencrypted_password)
67
- super(unencrypted_password) unless unencrypted_password.blank? && !password_required?
68
- end
69
-
70
- def current_password_correct
71
- errors.add(:current_password, 'is required to change email and/or password') if current_password.blank? # rubocop:disable Metrics/LineLength
72
- errors.add(:current_password, 'is incorrect') unless authenticate(current_password)
73
- end
74
-
75
- def current_password_required?
76
- !new_record? && (email_changed? || attempting_to_change_password?) && !password_resetting?
77
- end
78
-
79
- def password_resetting?
80
- reset_password_token_changed? && reset_password_token_exp_changed?
81
- end
82
-
83
- def password_required?
84
- attempting_to_change_password? || new_record?
85
- end
86
-
87
- def attempting_to_change_password?
88
- (!password.blank? || !password_confirmation.blank?) && password_digest_changed?
89
- end
90
- end
91
- end
92
- end
93
- end
@@ -1,36 +0,0 @@
1
- require 'active_support/concern'
2
-
3
- module TokenAuthenticateMe
4
- module Models
5
- module Sessionable
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- before_create :generate_unique_key
10
-
11
- def attributes
12
- {
13
- 'key' => key,
14
- 'expiration' => expiration,
15
- 'created_at' => created_at,
16
- 'updated_at' => updated_at
17
- }
18
- end
19
-
20
- private
21
-
22
- def generate_unique_key
23
- begin
24
- self.key = SecureRandom.hex
25
- end while self.class.exists?(key: key) # rubocop:disable Lint/Loop
26
-
27
- self.expiration = expiration_hours.hours.from_now
28
- end
29
-
30
- def expiration_hours
31
- 24
32
- end
33
- end
34
- end
35
- end
36
- end