rodauth-rails 1.10.0 → 1.11.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: adfcbce27e52d0a53b5cd670489635c841dff9e2809c92be059286943894db6c
4
- data.tar.gz: e98584823e926c810bc66366496df5fb3c8eed0f38e291b76b9f132480941a9c
3
+ metadata.gz: 8f902ae05472454543304221221b9681c7dab3d231d6551c7e82b6c4c1570dc8
4
+ data.tar.gz: b3a1948fb603be978bddea73a44b8109f4e3c76e132b2da3a8e6aad1b36f3d14
5
5
  SHA512:
6
- metadata.gz: 845b037926a9372522da9b3507b5fd2959454bc24198f72a7832d9025ccd27f9bac3790823577e1e68c3a1e1a076472e1629825973c37cc932e2b63299e1408b
7
- data.tar.gz: af417d7bbe9732c677ca15c6796817554fe68d5f8f3db8001b56a736db33382f3efd8f86952509d038f45f449f76d3c9ea61f1a7f5a29c1cef5f45e72cf1c9ce
6
+ metadata.gz: 8547335032c3e0851406932463cd62e2377c16db2145e0da6abb8a7f20745c20f9e8d54bd2b57599e335a4f9b37078cf7f1c17caa53b4dab60105c410a401469
7
+ data.tar.gz: dd84bd6d57a4e8e78a6412a7ac38befa7d75ef693a6788014d383d3800a4535af71fa24239f8b0521cecc7c598766f48b2034a016a2a15235cfa9f9d2dd52761
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## 1.11.0 (2023-08-21)
2
+
3
+ * Exclude WebAuthn JS routes in `rodauth:routes`, since those stop being relevant with custom JS (@janko)
4
+
5
+ * Separate HTTP verbs with `|` symbol in `rodauth:routes` for consistency with `rails routes` (@janko)
6
+
7
+ * Include two factor manage & auth JSON POST routes in `rodauth:routes` task (@janko)
8
+
9
+ * Make `rodauth:routes` rake task appear in `rails -T` list (@janko)
10
+
11
+ * Accept plugin options in `Rodauth::Rails.lib` (@janko)
12
+
13
+ * Support skipping loading Roda `render` plugin by passing `render: false` (@janko)
14
+
1
15
  ## 1.10.0 (2023-07-26)
2
16
 
3
17
  * Add `Rodauth::Rails.lib` for easier usage of Rodauth as a library in Rails apps (@janko)
data/README.md CHANGED
@@ -134,18 +134,18 @@ $ rails rodauth:routes
134
134
  ```
135
135
  Routes handled by RodauthApp:
136
136
 
137
- GET/POST /login rodauth.login_path
138
- GET/POST /create-account rodauth.create_account_path
139
- GET/POST /verify-account-resend rodauth.verify_account_resend_path
140
- GET/POST /verify-account rodauth.verify_account_path
141
- GET/POST /change-password rodauth.change_password_path
142
- GET/POST /change-login rodauth.change_login_path
143
- GET/POST /logout rodauth.logout_path
144
- GET/POST /remember rodauth.remember_path
145
- GET/POST /reset-password-request rodauth.reset_password_request_path
146
- GET/POST /reset-password rodauth.reset_password_path
147
- GET/POST /verify-login-change rodauth.verify_login_change_path
148
- GET/POST /close-account rodauth.close_account_path
137
+ GET|POST /login rodauth.login_path
138
+ GET|POST /create-account rodauth.create_account_path
139
+ GET|POST /verify-account-resend rodauth.verify_account_resend_path
140
+ GET|POST /verify-account rodauth.verify_account_path
141
+ GET|POST /change-password rodauth.change_password_path
142
+ GET|POST /change-login rodauth.change_login_path
143
+ GET|POST /logout rodauth.logout_path
144
+ GET|POST /remember rodauth.remember_path
145
+ GET|POST /reset-password-request rodauth.reset_password_request_path
146
+ GET|POST /reset-password rodauth.reset_password_path
147
+ GET|POST /verify-login-change rodauth.verify_login_change_path
148
+ GET|POST /close-account rodauth.close_account_path
149
149
  ```
150
150
 
151
151
  Using this information, you can add some basic authentication links to your
@@ -236,7 +236,7 @@ level. You can do this via the built-in `authenticated` routing constraint:
236
236
  ```rb
237
237
  # config/routes.rb
238
238
  Rails.application.routes.draw do
239
- constraints Rodauth::Rails.authenticated do
239
+ constraints Rodauth::Rails.authenticate do
240
240
  # ... authenticated routes ...
241
241
  end
242
242
  end
@@ -249,7 +249,7 @@ called with the Rodauth instance:
249
249
  # config/routes.rb
250
250
  Rails.application.routes.draw do
251
251
  # require multifactor authentication to be setup
252
- constraints Rodauth::Rails.authenticated { |rodauth| rodauth.uses_two_factor_authentication? } do
252
+ constraints Rodauth::Rails.authenticate { |rodauth| rodauth.uses_two_factor_authentication? } do
253
253
  # ...
254
254
  end
255
255
  end
@@ -260,7 +260,7 @@ You can specify a different Rodauth configuration by passing the configuration n
260
260
  ```rb
261
261
  # config/routes.rb
262
262
  Rails.application.routes.draw do
263
- constraints Rodauth::Rails.authenticated(:admin) do
263
+ constraints Rodauth::Rails.authenticate(:admin) do
264
264
  # ...
265
265
  end
266
266
  end
@@ -712,12 +712,22 @@ RodauthMain.login(login: "email@example.com", password: "secret123")
712
712
  RodauthMain.close_account(account_login: "email@example.com")
713
713
  ```
714
714
 
715
- Note that you'll want to skip requiring `rodauth-rails` on Rails boot, so that it doesn't insert the middleware automatically, and remove the initializer.
715
+ Note that you'll want to skip requiring `rodauth-rails` on Rails boot, to avoid it automatically inserting the Rodauth middleware, and remove some unnecessary files generated by the install generator.
716
716
 
717
717
  ```rb
718
718
  # Gemfile
719
719
  gem "rodauth-rails", require: false
720
720
  ```
721
+ ```sh
722
+ $ rm config/initializers/rodauth.rb app/misc/rodauth_app.rb app/controllers/rodauth_controller.rb
723
+ ```
724
+
725
+ The `Rodauth::Rails.lib` call will forward any Rodauth [plugin options] passed to it:
726
+
727
+ ```rb
728
+ # skips loading Roda render plugin and Tilt gem (used for rendering built-in templates)
729
+ Rodauth::Rails.lib(render: false) { ... }
730
+ ```
721
731
 
722
732
  ## Testing
723
733
 
@@ -929,7 +939,7 @@ class RodauthApp < Rodauth::Rails::App
929
939
  configure(:admin) { ... }
930
940
 
931
941
  # plugin options
932
- configure(RodauthMain, json: :only)
942
+ configure(RodauthMain, json: :only, render: false)
933
943
  end
934
944
  ```
935
945
 
@@ -18,16 +18,17 @@ module Rodauth
18
18
  end
19
19
 
20
20
  plugin :hooks
21
- plugin :render, layout: false
22
21
  plugin :pass
23
22
 
24
23
  def self.configure(*args, **options, &block)
25
24
  auth_class = args.shift if args[0].is_a?(Class)
26
- name = args.shift if args[0].is_a?(Symbol)
25
+ auth_class ||= Class.new(Rodauth::Rails::Auth)
26
+ name = args.shift if args[0].is_a?(Symbol)
27
27
 
28
28
  fail ArgumentError, "need to pass optional Rodauth::Auth subclass and optional configuration name" if args.any?
29
29
 
30
- auth_class ||= Class.new(Rodauth::Rails::Auth)
30
+ # we'll render Rodauth's built-in view templates within Rails layouts
31
+ plugin :render, layout: false unless options[:render] == false
31
32
 
32
33
  plugin :rodauth, auth_class: auth_class, name: name, csrf: false, flash: false, json: true, **options, &block
33
34
 
@@ -0,0 +1,70 @@
1
+ module Rodauth
2
+ module Rails
3
+ module Tasks
4
+ class Routes
5
+ IGNORE = [:webauthn_setup_js, :webauthn_auth_js, :webauthn_autofill_js]
6
+ JSON_POST = [:two_factor_manage, :two_factor_auth]
7
+
8
+ attr_reader :auth_class
9
+
10
+ def initialize(auth_class)
11
+ @auth_class = auth_class
12
+ end
13
+
14
+ def call
15
+ routes = auth_class.route_hash.map do |path, handle_method|
16
+ route_name = handle_method.to_s.sub(/\Ahandle_/, "").to_sym
17
+ next if IGNORE.include?(route_name)
18
+ verbs = route_verbs(route_name)
19
+
20
+ [
21
+ verbs.join("|"),
22
+ "#{rodauth.prefix}#{path}",
23
+ "rodauth#{configuration_name && "(:#{configuration_name})"}.#{route_name}_path",
24
+ ]
25
+ end
26
+
27
+ routes.compact!
28
+ padding = routes.transpose.map { |string| string.map(&:length).max }
29
+
30
+ output_lines = routes.map do |columns|
31
+ [columns[0].ljust(padding[0]), columns[1].ljust(padding[1]), columns[2]].join(" ")
32
+ end
33
+
34
+ puts "\n #{output_lines.join("\n ")}"
35
+ end
36
+
37
+ private
38
+
39
+ def route_verbs(route_name)
40
+ file_path, start_line = rodauth.method(:"_handle_#{route_name}").source_location
41
+ lines = File.foreach(file_path).to_a
42
+ indentation = lines[start_line - 1][/^\s+/]
43
+ verbs = []
44
+
45
+ lines[start_line..-1].each do |code|
46
+ verbs << :GET if code.include?("r.get") && !rodauth.only_json?
47
+ verbs << :POST if code.include?("r.post")
48
+ break if code.start_with?("#{indentation}end")
49
+ end
50
+
51
+ verbs << :POST if rodauth.features.include?(:json) && JSON_POST.include?(route_name)
52
+ verbs
53
+ end
54
+
55
+ def rodauth
56
+ auth_class.new(scope)
57
+ end
58
+
59
+ def scope
60
+ auth_class.roda_class.new({})
61
+ end
62
+
63
+ def configuration_name
64
+ auth_class.configuration_name
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+
@@ -1,42 +1,12 @@
1
+ require "rodauth/rails/tasks/routes"
2
+
1
3
  namespace :rodauth do
4
+ desc "Lists endpoints that will be routed by your Rodauth app"
2
5
  task routes: :environment do
3
- app = Rodauth::Rails.app
4
-
5
- puts "Routes handled by #{app}:"
6
-
7
- app.opts[:rodauths].each do |configuration_name, auth_class|
8
- rodauth = auth_class.allocate
9
- only_json = rodauth.method(:only_json?).owner != Rodauth::Base && rodauth.only_json?
10
-
11
- routes = auth_class.route_hash.map do |path, handle_method|
12
- file_path, start_line = rodauth.method(:"_#{handle_method}").source_location
13
- lines = File.foreach(file_path).to_a
14
- indentation = lines[start_line - 1][/^\s+/]
15
- verbs = []
16
-
17
- lines[start_line..-1].each do |code|
18
- verbs << :GET if code.include?("r.get") && !only_json
19
- verbs << :POST if code.include?("r.post")
20
- break if code.start_with?("#{indentation}end")
21
- end
22
-
23
- path_method = "#{handle_method.to_s.sub(/\Ahandle_/, "")}_path"
24
-
25
- [
26
- verbs.join("/"),
27
- "#{rodauth.prefix}#{path}",
28
- "rodauth#{configuration_name && "(:#{configuration_name})"}.#{path_method}",
29
- ]
30
- end
31
-
32
- verbs_padding = routes.map { |verbs, _, _| verbs.length }.max
33
- path_padding = routes.map { |_, path, _| path.length }.max
34
-
35
- route_lines = routes.map do |verbs, path, code|
36
- "#{verbs.ljust(verbs_padding)} #{path.ljust(path_padding)} #{code}"
37
- end
6
+ puts "Routes handled by #{Rodauth::Rails.app}:"
38
7
 
39
- puts "\n #{route_lines.join("\n ")}" unless route_lines.empty?
8
+ Rodauth::Rails.app.opts[:rodauths].each_value do |auth_class|
9
+ Rodauth::Rails::Tasks::Routes.new(auth_class).call
40
10
  end
41
11
  end
42
12
  end
@@ -1,5 +1,5 @@
1
1
  module Rodauth
2
2
  module Rails
3
- VERSION = "1.10.0"
3
+ VERSION = "1.11.0"
4
4
  end
5
5
  end
data/lib/rodauth/rails.rb CHANGED
@@ -16,9 +16,9 @@ module Rodauth
16
16
  @middleware = true
17
17
 
18
18
  class << self
19
- def lib(&block)
19
+ def lib(**options, &block)
20
20
  c = Class.new(Rodauth::Rails::App)
21
- c.configure(json: false) do
21
+ c.configure(json: false, **options) do
22
22
  enable :internal_request
23
23
  instance_exec(&block)
24
24
  end
@@ -57,8 +57,17 @@ module Rodauth
57
57
  Rodauth::Model.new(app.rodauth!(name), **options)
58
58
  end
59
59
 
60
- # routing constraint that requires authentication
60
+ # Routing constraint that requires authenticated account.
61
+ def authenticate(name = nil, &condition)
62
+ lambda do |request|
63
+ rodauth = request.env.fetch ["rodauth", *name].join(".")
64
+ rodauth.require_account
65
+ condition.nil? || condition.call(rodauth)
66
+ end
67
+ end
68
+
61
69
  def authenticated(name = nil, &condition)
70
+ warn "Rodauth::Rails.authenticated has been deprecated in favor of Rodauth::Rails.authenticate, which additionally requires existence of the account record."
62
71
  lambda do |request|
63
72
  rodauth = request.env.fetch ["rodauth", *name].join(".")
64
73
  rodauth.require_authentication
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.10.0
4
+ version: 1.11.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: 2023-07-26 00:00:00.000000000 Z
11
+ date: 2023-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -328,6 +328,7 @@ files:
328
328
  - lib/rodauth/rails/model.rb
329
329
  - lib/rodauth/rails/railtie.rb
330
330
  - lib/rodauth/rails/tasks.rake
331
+ - lib/rodauth/rails/tasks/routes.rb
331
332
  - lib/rodauth/rails/test.rb
332
333
  - lib/rodauth/rails/test/controller.rb
333
334
  - lib/rodauth/rails/version.rb
@@ -351,7 +352,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
351
352
  - !ruby/object:Gem::Version
352
353
  version: '0'
353
354
  requirements: []
354
- rubygems_version: 3.4.12
355
+ rubygems_version: 3.4.10
355
356
  signing_key:
356
357
  specification_version: 4
357
358
  summary: Provides Rails integration for Rodauth.