rodauth-rails 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 402cbf2f62d93eae97353a3aed436ce742b41421e880176649a7271c5516b39c
4
- data.tar.gz: ca035e7a60c54b4e1b6f2a42ea6405f43811146141c30c5a6d14fd7c0600669e
3
+ metadata.gz: b1f519c5d15eb6c70585c8cfa625106dec267b4e7f666daeeb9499ef61c656e7
4
+ data.tar.gz: 1bc84d1dba6ab9ab884a56f47419e207655c90f1d71d32b009575ab169fc0b3d
5
5
  SHA512:
6
- metadata.gz: 888fd37f380d6f4896b544374c6681445dbb0e90d692dd7c0239aa043c9d6c0cb2aaafa9b47f271cd6cc70ad3a6c88693c988901aed1e5bc0f77ed5c92cb4ab1
7
- data.tar.gz: 48fe23bfbd3d78c3378ab47ecf92ffd7f87fe768f996764a71b8534a2cab8731ebc080998b03ea9a78f1fecd949548782ca8e38dc17c56fa2606ea11f7a7fbe9
6
+ metadata.gz: 88ccdb974fe6b6dd0e797cf5307656c80d7038c820eab897b277b6c22bd1bc61cc00e7e39295d2a98fc313530ad658c6be80e043dde595d3514c3a51fa0572a4
7
+ data.tar.gz: d17fc8142a16f18ff485446d94e68ed4672faa64edfa8aaac3b400e9060f9638575a577ff232b83a1360a58e8655199c1ab88972f77a3af0f45d76f3514b7df5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 1.3.0 (2022-04-01)
2
+
3
+ * Store password hash on the `accounts` table in generated Rodauth migration and configuration (@janko)
4
+
5
+ * Add support for controller testing with Minitest or RSpec (@janko)
6
+
7
+ * Fix `enum` declaration in generated `Account` model for Active Record < 7.0 (@janko)
8
+
9
+ * Ensure `require_login_redirect` points to the login page even if the login route changes (@janko)
10
+
1
11
  ## 1.2.2 (2022-02-22)
2
12
 
3
13
  * Fix flash messages not being preserved through consecutive redirects (@janko)
data/README.md CHANGED
@@ -10,7 +10,6 @@ Provides Rails integration for the [Rodauth] authentication framework.
10
10
  * [Rails demo](https://github.com/janko/rodauth-demo-rails)
11
11
  * [JSON API guide](https://github.com/janko/rodauth-rails/wiki/JSON-API)
12
12
  * [OmniAuth guide](https://github.com/janko/rodauth-rails/wiki/OmniAuth)
13
- * [Testing guide](https://github.com/janko/rodauth-rails/wiki/Testing)
14
13
 
15
14
  🎥 Screencasts:
16
15
 
@@ -40,7 +39,7 @@ of the advantages that stand out for me:
40
39
  * consistent before/after hooks around everything
41
40
  * dedicated object encapsulating all authentication logic
42
41
 
43
- One commmon concern is the fact that, unlike most other authentication
42
+ One common concern is the fact that, unlike most other authentication
44
43
  frameworks for Rails, Rodauth uses [Sequel] for database interaction instead of
45
44
  Active Record. There are good reasons for this, and to make Rodauth work
46
45
  smoothly alongside Active Record, rodauth-rails configures Sequel to [reuse
@@ -783,6 +782,86 @@ Rodauth::Rails.rodauth(session: { two_factor_auth_setup: true })
783
782
  Rodauth::Rails.rodauth(:admin, params: { "param" => "value" })
784
783
  ```
785
784
 
785
+ ## Testing
786
+
787
+ For system and integration tests, which run the whole middleware stack,
788
+ authentication can be exercised normally via HTTP endpoints. See [this wiki
789
+ page](https://github.com/janko/rodauth-rails/wiki/Testing) for some examples.
790
+
791
+ For controller tests, you can log in accounts by modifying the session:
792
+
793
+ ```rb
794
+ # app/controllers/articles_controller.rb
795
+ class ArticlesController < ApplicationController
796
+ before_action -> { rodauth.require_authentication }
797
+
798
+ def index
799
+ # ...
800
+ end
801
+ end
802
+ ```
803
+ ```rb
804
+ # test/controllers/articles_controller_test.rb
805
+ class ArticlesControllerTest < ActionController::TestCase
806
+ test "required authentication" do
807
+ get :index
808
+
809
+ assert_response 302
810
+ assert_redirected_to "/login"
811
+ assert_equal "Please login to continue", flash[:alert]
812
+
813
+ account = Account.create!(email: "user@example.com", password: "secret", status: "verified")
814
+ login(account)
815
+
816
+ get :index
817
+ assert_response 200
818
+
819
+ logout
820
+
821
+ get :index
822
+ assert_response 302
823
+ assert_equal "Please login to continue", flash[:alert]
824
+ end
825
+
826
+ private
827
+
828
+ # Manually modify the session into what Rodauth expects.
829
+ def login(account)
830
+ session[:account_id] = account.id
831
+ session[:authenticated_by] = ["password"] # or ["password", "totp"] for MFA
832
+ end
833
+
834
+ def logout
835
+ session.clear
836
+ end
837
+ end
838
+ ```
839
+
840
+ If you're using multiple configurations with different session prefixes, you'll need
841
+ to make sure to use those in controller tests as well:
842
+
843
+ ```rb
844
+ class RodauthAdmin < Rodauth::Rails::Auth
845
+ configure do
846
+ session_key_prefix "admin_"
847
+ end
848
+ end
849
+ ```
850
+ ```rb
851
+ # in a controller test:
852
+ session[:admin_account_id] = account.id
853
+ session[:admin_authenticated_by] = ["password"]
854
+ ```
855
+
856
+ If you want to access the Rodauth instance in controller tests, you can do so
857
+ through the controller instance:
858
+
859
+ ```rb
860
+ # in a controller test:
861
+ @controller.rodauth #=> #<RodauthMain ...>
862
+ @controller.rodauth(:admin) #=> #<RodauthAdmin ...>
863
+ ```
864
+
786
865
  ## Configuring
787
866
 
788
867
  ### Configuration methods
@@ -3,23 +3,18 @@ enable_extension "citext"
3
3
 
4
4
  <% end -%>
5
5
  create_table :accounts<%= primary_key_type %> do |t|
6
+ t.integer :status, null: false, default: 1
6
7
  <% case activerecord_adapter -%>
7
8
  <% when "postgresql" -%>
8
9
  t.citext :email, null: false
9
10
  <% else -%>
10
11
  t.string :email, null: false
11
12
  <% end -%>
12
- t.integer :status, null: false, default: 1
13
13
  <% case activerecord_adapter -%>
14
14
  <% when "postgresql", "sqlite3" -%>
15
15
  t.index :email, unique: true, where: "status IN (1, 2)"
16
16
  <% else -%>
17
17
  t.index :email, unique: true
18
18
  <% end -%>
19
- end
20
-
21
- # Used if storing password hashes in a separate table (default)
22
- create_table :account_password_hashes<%= primary_key_type %> do |t|
23
- t.foreign_key :accounts, column: :id
24
- t.string :password_hash, null: false
19
+ t.string :password_hash
25
20
  end
@@ -35,7 +35,7 @@ class RodauthMain < Rodauth::Rails::Auth
35
35
  account_status_column :status
36
36
 
37
37
  # Store password hash in a column instead of a separate table.
38
- # account_password_hash_column :password_digest
38
+ account_password_hash_column :password_hash
39
39
 
40
40
  # Set password when creating account instead of when verifying.
41
41
  verify_account_set_password? false
@@ -138,6 +138,9 @@ class RodauthMain < Rodauth::Rails::Auth
138
138
 
139
139
  # Redirect to login page after password reset.
140
140
  reset_password_redirect { login_path }
141
+
142
+ # Ensure requiring login follows login route changes.
143
+ require_login_redirect { login_path }
141
144
  <% end -%>
142
145
 
143
146
  # ==> Deadlines
@@ -1,4 +1,8 @@
1
1
  class Account < ApplicationRecord
2
2
  include Rodauth::Rails.model
3
+ <% if ActiveRecord.version >= Gem::Version.new("7.0") -%>
3
4
  enum :status, unverified: 1, verified: 2, closed: 3
5
+ <% else -%>
6
+ enum status: { unverified: 1, verified: 2, closed: 3 }
7
+ <% end -%>
4
8
  end
@@ -1,5 +1,6 @@
1
1
  require "rodauth/rails/middleware"
2
2
  require "rodauth/rails/controller_methods"
3
+ require "rodauth/rails/test"
3
4
 
4
5
  require "rails"
5
6
 
@@ -21,6 +22,14 @@ module Rodauth
21
22
  initializer "rodauth.test" do
22
23
  # Rodauth uses RACK_ENV to set the default bcrypt hash cost
23
24
  ENV["RACK_ENV"] = "test" if ::Rails.env.test?
25
+
26
+ if ActionPack.version >= Gem::Version.new("5.0")
27
+ ActiveSupport.on_load(:action_controller_test_case) do
28
+ include Rodauth::Rails::Test::Controller
29
+ end
30
+ else
31
+ ActionController::TestCase.include Rodauth::Rails::Test::Controller
32
+ end
24
33
  end
25
34
 
26
35
  rake_tasks do
@@ -0,0 +1,41 @@
1
+ require "active_support/concern"
2
+
3
+ module Rodauth
4
+ module Rails
5
+ module Test
6
+ module Controller
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ setup :setup_rodauth
11
+ end
12
+
13
+ def process(*)
14
+ catch_rodauth { super }
15
+ end
16
+ ruby2_keywords(:process) if respond_to?(:ruby2_keywords, true)
17
+
18
+ private
19
+
20
+ def setup_rodauth
21
+ Rodauth::Rails.app.opts[:rodauths].each do |name, auth_class|
22
+ scope = auth_class.roda_class.new(request.env)
23
+ request.env[["rodauth", *name].join(".")] = auth_class.new(scope)
24
+ end
25
+ end
26
+
27
+ def catch_rodauth(&block)
28
+ result = catch(:halt, &block)
29
+
30
+ if result.is_a?(Array) # rodauth response
31
+ response.status = result[0]
32
+ response.headers.merge! result[1]
33
+ response.body = result[2]
34
+ end
35
+
36
+ response
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,7 @@
1
+ module Rodauth
2
+ module Rails
3
+ module Test
4
+ autoload :Controller, "rodauth/rails/test/controller"
5
+ end
6
+ end
7
+ end
@@ -1,5 +1,5 @@
1
1
  module Rodauth
2
2
  module Rails
3
- VERSION = "1.2.2"
3
+ VERSION = "1.3.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rodauth-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janko Marohnić
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-22 00:00:00.000000000 Z
11
+ date: 2022-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -247,6 +247,8 @@ files:
247
247
  - lib/rodauth/rails/model/associations.rb
248
248
  - lib/rodauth/rails/railtie.rb
249
249
  - lib/rodauth/rails/tasks.rake
250
+ - lib/rodauth/rails/test.rb
251
+ - lib/rodauth/rails/test/controller.rb
250
252
  - lib/rodauth/rails/version.rb
251
253
  - rodauth-rails.gemspec
252
254
  homepage: https://github.com/janko/rodauth-rails