challah 1.6.1 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/README.md +5 -38
  4. data/VERSION +1 -1
  5. data/app/controllers/sessions_controller.rb +11 -10
  6. data/app/models/authorization.rb +2 -0
  7. data/lib/challah/audit.rb +38 -36
  8. data/lib/challah/authenticators/api_key.rb +4 -2
  9. data/lib/challah/authenticators/password.rb +3 -1
  10. data/lib/challah/authenticators.rb +5 -3
  11. data/lib/challah/concerns/authorizeable.rb +4 -0
  12. data/lib/challah/concerns/user/attributeable.rb +35 -33
  13. data/lib/challah/concerns/user/authenticateable.rb +2 -0
  14. data/lib/challah/concerns/user/authorizable.rb +16 -12
  15. data/lib/challah/concerns/user/findable.rb +13 -10
  16. data/lib/challah/concerns/user/passwordable.rb +5 -3
  17. data/lib/challah/concerns/user/provideable.rb +22 -20
  18. data/lib/challah/concerns/user/statusable.rb +3 -21
  19. data/lib/challah/concerns/user/validateable.rb +3 -1
  20. data/lib/challah/concerns/userable.rb +1 -3
  21. data/lib/challah/controller.rb +69 -65
  22. data/lib/challah/cookie_store.rb +7 -5
  23. data/lib/challah/encrypter.rb +4 -2
  24. data/lib/challah/engine.rb +5 -18
  25. data/lib/challah/providers/password_provider.rb +9 -7
  26. data/lib/challah/providers.rb +3 -1
  27. data/lib/challah/random.rb +6 -4
  28. data/lib/challah/routes.rb +6 -6
  29. data/lib/challah/session.rb +27 -25
  30. data/lib/challah/signup.rb +5 -3
  31. data/lib/challah/simple_cookie_store.rb +82 -80
  32. data/lib/challah/techniques/api_key_technique.rb +2 -2
  33. data/lib/challah/techniques/password_technique.rb +2 -1
  34. data/lib/challah/techniques/token_technique.rb +1 -1
  35. data/lib/challah/techniques.rb +2 -0
  36. data/lib/challah/test.rb +6 -0
  37. data/lib/challah/validators/email_validator.rb +2 -0
  38. data/lib/challah/validators/password_validator.rb +5 -3
  39. data/lib/challah/version.rb +3 -1
  40. data/lib/challah.rb +2 -5
  41. data/lib/generators/challah_generator.rb +2 -8
  42. data/lib/generators/templates/{migration.rb → migration.erb} +3 -6
  43. metadata +42 -19
  44. data/lib/challah/plugins.rb +0 -54
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52c23a580c2dfe4d78653d75a44f1a1f5f0c54b3d62c7091ce0089621e35add4
4
- data.tar.gz: 839e41cf3038d7e8319d476268abad5004a8adbbedcf5eba2fbb1119ddef9b23
3
+ metadata.gz: 0b260522736245710527baecf3c8060c67609feee2619eb460c36771350aa8ac
4
+ data.tar.gz: f94497f70a4ad972954284a54ebfe997757d5d08ae7c2dc320f947fc147731f5
5
5
  SHA512:
6
- metadata.gz: f91ad595ae383d6775e533f1cc60053be1221d824ff351b6ea6f24a22eed1e9ea6ff3172f82f6930a7aa522e6e910d0bb3b0e3a86a457a5e5d79368196c86938
7
- data.tar.gz: c5b43537d21543b4d9d3eb2aa3791b669c9d91c26050f4211a07c5bf7bea5f5b9f5081e0de239fb8519cef8c61fdba3e9a05bbf18ec2c5a2a3341b86011af93a
6
+ metadata.gz: 66bb3654fc8a8204075bb6e5645486a233a591eb57e37a20b3b979bab4961ab2b67c6b130479b977796eef88aadef49e4b7ec4b114b90fbbfcfac2809884234d
7
+ data.tar.gz: f93ed733130b3b69a128fde0cd8c4bc36e9989b4ac340410c72fa32b2e6498838860f4cc18e2c780adc3b2129d069efe3fe9e8be086c7f407770b39bcae4a16c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## Challah 2.0.0.beta1
2
+
3
+ This version introduces the following breaking changes, and therefore a new major version number:
4
+
5
+ * Plugins no longer supported. This was never fully baked and was only used for the now defunct challah-rolls library, which is no longer maintained.
6
+ * Drops support for Rails 4
7
+ * Drops support for Ruby prior to 2.5.0
8
+ * Removes legacy support for boolean-based User#active column in favor of enums on User#status
9
+
10
+ Plus the following new changes:
11
+
12
+ * Support for Rails 6.0
13
+ * Authorizations table is now properly set as a foreign key to users (for new installations only, for existing tables you can do this yourself)
14
+
1
15
  ## Challah 1.6.1
2
16
 
3
17
  * Prevent an email address that is blank from saving the `User#email_hash` attribute
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Challah
2
2
 
3
- [![Build Status](https://travis-ci.org/jdtornow/challah.svg?branch=master)](https://travis-ci.org/jdtornow/challah) [![Code Climate](https://codeclimate.com/github/jdtornow/challah/badges/gpa.svg)](https://codeclimate.com/github/jdtornow/challah) [![Gem Version](https://badge.fury.io/rb/challah.svg)](https://badge.fury.io/rb/challah)
3
+ [![CircleCI](https://circleci.com/gh/jdtornow/challah.svg?style=svg)](https://circleci.com/gh/jdtornow/challah) [![Code Climate](https://codeclimate.com/github/jdtornow/challah/badges/gpa.svg)](https://codeclimate.com/github/jdtornow/challah) [![Gem Version](https://badge.fury.io/rb/challah.svg)](https://badge.fury.io/rb/challah)
4
4
 
5
5
  Challah (pronounced HAH-lah) is a simple Rails authentication gem that provides users a way to authenticate with your app. Most of the functionality within the gem lives within a Rails engine and tries to stay out of the way of your app.
6
6
 
@@ -8,9 +8,8 @@ Challah doesn't provide any fancy controllers or views that clutter your app or
8
8
 
9
9
  ## Requirements
10
10
 
11
- * Ruby 2.2.2+
12
- * Bundler
13
- * Rails 5.0+
11
+ * Ruby 2.5.0+
12
+ * Rails 5.2+
14
13
 
15
14
  ## Installation
16
15
 
@@ -35,7 +34,7 @@ This will copy over the necessary migrations to your app and migrate the databas
35
34
  If you would prefer to handle these steps manually, you can do so by using these rake tasks instead:
36
35
 
37
36
  ```bash
38
- rails g challah
37
+ rails generate challah
39
38
  rails challah:unpack:user
40
39
  rails db:migrate
41
40
  ```
@@ -187,7 +186,7 @@ curl -H "X-App-User: abc123" \
187
186
 
188
187
  _Note: Custom HTTP headers should always start with X-_
189
188
 
190
- ## ActionCable in Rails 5
189
+ ## ActionCable
191
190
 
192
191
  Challah works well with securing your ActionCable channels since Rails 5. Here is a sample `ApplicationCable::Connection` file to secure connections to a valid signed-in user:
193
192
 
@@ -215,38 +214,6 @@ module ApplicationCable
215
214
  end
216
215
  ```
217
216
 
218
- ## Upgrading to Challah 1.4+
219
-
220
- In Challah 1.4, the `active` boolean column changed to a `status` Rails enum with "active" as the default option. To upgrade a users table, use the following migration example:
221
-
222
- ```bash
223
- rails g migration ConvertUsersActiveToEnum
224
- ```
225
-
226
- ```ruby
227
- class ConvertUsersActiveToEnum < ActiveRecord::Migration
228
- def up
229
- add_column :users, :status, :integer, default: 0
230
-
231
- say_with_time "Converting users to status enum" do
232
- User.where(active: false).update_all(status: User.statuses[:inactive])
233
- end
234
-
235
- remove_column :users, :active
236
- end
237
-
238
- def down
239
- add_column :users, :active, :boolean, default: true
240
-
241
- say_with_time "Converting users to active boolean" do
242
- User.where(status: User.statuses[:inactive]).update_all(active: false)
243
- end
244
-
245
- remove_column :users, :status
246
- end
247
- end
248
- ```
249
-
250
217
  ## User Validations
251
218
 
252
219
  By default, the `first_name`, `last_name`, and `email` fields are required on the user model. If you'd prefer to add your own validations and leave the defaults off, you can use the following option within an initializer:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.6.1
1
+ 2.0.0.beta1
@@ -3,6 +3,7 @@ if File.exist?(Rails.root.join("controllers/application_controller"))
3
3
  end
4
4
 
5
5
  class SessionsController < (defined?(ApplicationController) ? ApplicationController : ActionController::Base)
6
+
6
7
  before_action :destroy_session, except: :create
7
8
 
8
9
  # GET /login
@@ -20,7 +21,7 @@ class SessionsController < (defined?(ApplicationController) ? ApplicationControl
20
21
  if @session.save
21
22
  redirect_to return_to_path
22
23
  else
23
- redirect_to signin_path, alert: I18n.translate('sessions.create.failed_login')
24
+ redirect_to signin_path, alert: I18n.translate("sessions.create.failed_login")
24
25
  end
25
26
  end
26
27
 
@@ -32,14 +33,14 @@ class SessionsController < (defined?(ApplicationController) ? ApplicationControl
32
33
 
33
34
  protected
34
35
 
35
- def destroy_session
36
- current_user_session.destroy
37
- end
36
+ def destroy_session
37
+ current_user_session.destroy
38
+ end
38
39
 
39
- def return_to_path(default_path = '/')
40
- result = session[:return_to]
41
- result = nil if result and result == "http://#{request.domain}/"
42
- result || default_path
43
- end
44
- end
40
+ def return_to_path(default_path = "/")
41
+ result = session[:return_to]
42
+ result = nil if result && (result == "http://#{ request.domain }/")
43
+ result || default_path
44
+ end
45
45
 
46
+ end
@@ -1,3 +1,5 @@
1
1
  class Authorization < ActiveRecord::Base
2
+
2
3
  include Challah::Authorizeable
4
+
3
5
  end
data/lib/challah/audit.rb CHANGED
@@ -28,6 +28,7 @@ module Challah
28
28
  # end
29
29
  #
30
30
  module Audit
31
+
31
32
  extend ActiveSupport::Concern
32
33
 
33
34
  included do
@@ -58,53 +59,54 @@ module Challah
58
59
 
59
60
  private
60
61
 
61
- def before_save_audit
62
- if new_record?
63
- all_audit_attributes.map(&:to_s).each do |column|
64
- if respond_to?(column) && respond_to?("#{ column }=")
65
- write_attribute(column, current_user_id)
62
+ def before_save_audit
63
+ if new_record?
64
+ all_audit_attributes.map(&:to_s).each do |column|
65
+ if respond_to?(column) && respond_to?("#{ column }=")
66
+ write_attribute(column, current_user_id)
67
+ end
66
68
  end
67
- end
68
- else
69
- audit_attributes_for_update.map(&:to_s).each do |column|
70
- if respond_to?(column) && respond_to?("#{ column }=")
71
- next if attribute_changed?(column) # don't update the column if we already manually did
72
- write_attribute(column, current_user_id)
69
+ else
70
+ audit_attributes_for_update.map(&:to_s).each do |column|
71
+ if respond_to?(column) && respond_to?("#{ column }=")
72
+ next if attribute_changed?(column) # don't update the column if we already manually did
73
+ write_attribute(column, current_user_id)
74
+ end
73
75
  end
74
76
  end
75
77
  end
76
- end
77
-
78
- # @private
79
- def audit_attributes_for_update
80
- [ :updated_by, :modifed_by, :updated_user_id ]
81
- end
82
78
 
83
- # @private
84
- def audit_attributes_for_create
85
- [ :created_by, :created_user_id ]
86
- end
79
+ # @private
80
+ def audit_attributes_for_update
81
+ [ :updated_by, :modifed_by, :updated_user_id ]
82
+ end
87
83
 
88
- # @private
89
- def all_audit_attributes
90
- audit_attributes_for_update + audit_attributes_for_create
91
- end
84
+ # @private
85
+ def audit_attributes_for_create
86
+ [ :created_by, :created_user_id ]
87
+ end
92
88
 
93
- # Clear attributes and changed_attributes
94
- def clear_audit_attributes
95
- all_audit_attributes.each do |attribute_name|
96
- if respond_to?(attribute_name) && respond_to?("#{ attribute_name }=")
97
- write_attribute(attribute_name, nil)
98
- end
89
+ # @private
90
+ def all_audit_attributes
91
+ audit_attributes_for_update + audit_attributes_for_create
99
92
  end
100
93
 
101
- @changed_attributes = changed_attributes.reduce(ActiveSupport::HashWithIndifferentAccess.new) do |result, (key, value)|
102
- unless all_audit_attributes.include?(key.to_sym)
103
- result[key] = value
94
+ # Clear attributes and changed_attributes
95
+ def clear_audit_attributes
96
+ all_audit_attributes.each do |attribute_name|
97
+ if respond_to?(attribute_name) && respond_to?("#{ attribute_name }=")
98
+ write_attribute(attribute_name, nil)
99
+ end
104
100
  end
105
101
 
106
- result
102
+ @changed_attributes = changed_attributes.reduce(ActiveSupport::HashWithIndifferentAccess.new) do |result, (key, value)|
103
+ unless all_audit_attributes.include?(key.to_sym)
104
+ result[key] = value
105
+ end
106
+
107
+ result
108
+ end
107
109
  end
108
- end
110
+
109
111
  end
110
112
  end
@@ -1,9 +1,11 @@
1
1
  module Challah
2
2
  module Authenticators
3
3
  class ApiKey
4
+
4
5
  def self.match?(user, provider, api_key)
5
- user.api_key == api_key.to_s.strip
6
+ user.api_key == api_key.to_s.strip
6
7
  end
8
+
7
9
  end
8
10
  end
9
- end
11
+ end
@@ -1,6 +1,7 @@
1
1
  module Challah
2
2
  module Authenticators
3
3
  class Password
4
+
4
5
  def self.match?(user, provider, plain_password)
5
6
  if !!provider
6
7
  crypted_password = provider.fetch(:token)
@@ -9,6 +10,7 @@ module Challah
9
10
 
10
11
  false
11
12
  end
13
+
12
14
  end
13
15
  end
14
- end
16
+ end
@@ -1,8 +1,9 @@
1
- require 'challah/authenticators/api_key'
2
- require 'challah/authenticators/password'
1
+ require "challah/authenticators/api_key"
2
+ require "challah/authenticators/password"
3
3
 
4
4
  module Challah
5
5
  module Authenticators
6
+
6
7
  # Register a new authenticator.
7
8
  #
8
9
  # Usage:
@@ -19,5 +20,6 @@ module Challah
19
20
  def authenticators
20
21
  @authenticators.dup
21
22
  end
23
+
22
24
  end
23
- end
25
+ end
@@ -1,5 +1,6 @@
1
1
  module Challah
2
2
  module Authorizeable
3
+
3
4
  extend ActiveSupport::Concern
4
5
 
5
6
  included do
@@ -12,6 +13,7 @@ module Challah
12
13
  end
13
14
 
14
15
  module ClassMethods
16
+
15
17
  def hashable_attributes
16
18
  protected_attributes = %w( user_id provider last_session_at last_session_ip session_count created_at updated_at )
17
19
  @hashable_attributes ||= self.columns.map(&:name) - protected_attributes
@@ -63,6 +65,8 @@ module Challah
63
65
  def user_model
64
66
  @user_model ||= Challah.user
65
67
  end
68
+
66
69
  end
70
+
67
71
  end
68
72
  end
@@ -1,5 +1,6 @@
1
1
  module Challah
2
2
  module UserAttributeable
3
+
3
4
  extend ActiveSupport::Concern
4
5
 
5
6
  included do
@@ -30,50 +31,51 @@ module Challah
30
31
 
31
32
  protected
32
33
 
33
- # Ensure that all system-generated columns aren't blank on each save
34
- def ensure_user_tokens
35
- ensure_api_key_presence
36
- ensure_email_hash_presence
37
- ensure_persistence_token_presence
38
- end
34
+ # Ensure that all system-generated columns aren't blank on each save
35
+ def ensure_user_tokens
36
+ ensure_api_key_presence
37
+ ensure_email_hash_presence
38
+ ensure_persistence_token_presence
39
+ end
39
40
 
40
- # Store a random seed for this user's api key
41
- def ensure_api_key_presence
42
- if respond_to?("api_key=")
43
- if self.api_key.to_s.blank?
44
- self.api_key = Random.token(50)
41
+ # Store a random seed for this user's api key
42
+ def ensure_api_key_presence
43
+ if respond_to?("api_key=")
44
+ if self.api_key.to_s.blank?
45
+ self.api_key = Random.token(50)
46
+ end
45
47
  end
46
48
  end
47
- end
48
49
 
49
- # Store a hashed email if the column exists
50
- def ensure_email_hash_presence
51
- if respond_to?("email_hash=")
52
- if email_changed?
53
- self.email_hash = generate_email_hash
50
+ # Store a hashed email if the column exists
51
+ def ensure_email_hash_presence
52
+ if respond_to?("email_hash=")
53
+ if email_changed?
54
+ self.email_hash = generate_email_hash
55
+ end
54
56
  end
55
57
  end
56
- end
57
58
 
58
- # Store a random token to identify user in persisted objects
59
- def ensure_persistence_token_presence
60
- if respond_to?("persistence_token=")
61
- if self.persistence_token.to_s.blank?
62
- self.persistence_token = Random.token(125)
59
+ # Store a random token to identify user in persisted objects
60
+ def ensure_persistence_token_presence
61
+ if respond_to?("persistence_token=")
62
+ if self.persistence_token.to_s.blank?
63
+ self.persistence_token = Random.token(125)
64
+ end
63
65
  end
64
66
  end
65
- end
66
67
 
67
- def generate_email_hash
68
- if self.email.present?
69
- Encrypter.md5(email.to_s.downcase.strip)
68
+ def generate_email_hash
69
+ if self.email.present?
70
+ Encrypter.md5(email.to_s.downcase.strip)
71
+ end
72
+ end
73
+
74
+ # Downcase email and strip if of whitespace
75
+ # Ex: " HELLO@example.com " => "hello@example.com"
76
+ def normalize_user_email
77
+ self.email = self.email.to_s.downcase.strip
70
78
  end
71
- end
72
79
 
73
- # Downcase email and strip if of whitespace
74
- # Ex: " HELLO@example.com " => "hello@example.com"
75
- def normalize_user_email
76
- self.email = self.email.to_s.downcase.strip
77
- end
78
80
  end
79
81
  end
@@ -1,5 +1,6 @@
1
1
  module Challah
2
2
  module UserAuthenticateable
3
+
3
4
  # Generic authentication method. By default, this just checks to see if the password
4
5
  # given matches this user. You can also pass in the first parameter as the method
5
6
  # to use for a different type of authentication.
@@ -39,5 +40,6 @@ module Challah
39
40
  self.save
40
41
  self.increment!(:session_count, 1)
41
42
  end
43
+
42
44
  end
43
45
  end
@@ -1,5 +1,6 @@
1
1
  module Challah
2
2
  module UserAuthorizable
3
+
3
4
  extend ActiveSupport::Concern
4
5
 
5
6
  included do
@@ -8,25 +9,28 @@ module Challah
8
9
  before_destroy :clear_authorizations_before_destroy
9
10
  end
10
11
 
11
- protected
12
-
13
12
  def authorizations
14
13
  return [] if new_record?
15
14
  self.class.authorization_model.where(user_id: self.id)
16
15
  end
17
16
 
18
- def clear_authorizations_before_destroy
19
- authorizations.destroy_all
20
- end
17
+ protected
21
18
 
22
- module ClassMethods
23
- def authorizations_table_name
24
- @authorizations_table_name ||= authorization_model.table_name
19
+ def clear_authorizations_before_destroy
20
+ authorizations.destroy_all
25
21
  end
26
22
 
27
- def authorization_model
28
- @authorization_model ||= ::Authorization
23
+ module ClassMethods
24
+
25
+ def authorizations_table_name
26
+ @authorizations_table_name ||= authorization_model.table_name
27
+ end
28
+
29
+ def authorization_model
30
+ @authorization_model ||= ::Authorization
31
+ end
32
+
29
33
  end
30
- end
34
+
31
35
  end
32
- end
36
+ end