rodauth-rails 1.5.1 → 1.5.5

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: 496b2621170adf123079ae52341d3f6d0b3a120c3fa9f81e1bd26886735c6808
4
- data.tar.gz: eb1001f7835561714a134649b989c9cb0f09a5091e4b8d009650134f03d60470
3
+ metadata.gz: b9640fa912cb535846cd94b3df3361e9763f2267107205287783885e587e774b
4
+ data.tar.gz: d135e8e958f0210b22fe694ba2a77e6d4fde74df339b8ec06440ac0f83771c90
5
5
  SHA512:
6
- metadata.gz: e6681a10e0d724656c2b27be02a59eebc107f8a13ebf39b5732696da9df6c6631fe8ac23601db12bb568923b339ee790800b96bb3a3c71a9978c8aa02becea9d
7
- data.tar.gz: e802cd53015dc736395e5cdf1e7f2df3cb0174075da18af1ca5317867e33ad79d695c7d01d22acc2f581d33b578c2da88af0c91259db79bae85183a9316a2334
6
+ metadata.gz: 1067a2467e0f7dacbfe3a703d6f1e4ad561c9dc7a72fbe3942a20b43b8892211c2509ec3b71c47ba30bf16bea0f7163f8ecb82a5aceaabb23f01a5705d256d12
7
+ data.tar.gz: ce2464227d1c0a5e5bc3452f05c392787b61fd6b3c530a89c99047c69a4bcceabf08778aaa169c57fa39dbae80efdb455b334881f04b069099fab7b666dc1cfe
data/CHANGELOG.md CHANGED
@@ -1,3 +1,39 @@
1
+ ## 1.5.5 (2022-08-04)
2
+
3
+ * Don't raise `ArgumentError` when calling `#current_account` without being logged in (@benkoshy)
4
+
5
+ * Abort `rodauth:views` generator when unknown feature was specified (@janko)
6
+
7
+ * Abort `rodauth:migration` generator when unknown feature was specified (@janko)
8
+
9
+ ## 1.5.4 (2022-07-21)
10
+
11
+ * Generate account fixtures in `spec/fixtures` directory when using RSpec (@benkoshy)
12
+
13
+ * Generate account fixtures in `test/fixtures` directory instead of `app/test/fixtures` (@benkoshy)
14
+
15
+ * Use string status column values in generated accounts fixture (@janko)
16
+
17
+ * Create integer status column in generated Sequel migration (@janko)
18
+
19
+ * Store password hash in accounts table in generated Sequel migration (@janko)
20
+
21
+ ## 1.5.3 (2022-07-21)
22
+
23
+ *Yanked*
24
+
25
+ ## 1.5.2 (2022-07-03)
26
+
27
+ * Bump Rodauth dependency version to 2.25+ (@janko)
28
+
29
+ * Generate fixture file for accounts on `rodauth:install` (@benkoshy)
30
+
31
+ * Fix error about undefined `controller_path` method in `newrelic_rpm` gem instrumentation (@janko)
32
+
33
+ * Don't display disabled routes in `rodauth:routes` (@janko)
34
+
35
+ * Display HTTP verbs of endpoints in `rodauth:routes` rake task (@janko)
36
+
1
37
  ## 1.5.1 (2022-06-19)
2
38
 
3
39
  * Fix syntax for creating `citext` PG extension in Sequel base migration (@Empact)
data/README.md CHANGED
@@ -14,6 +14,7 @@ Provides Rails integration for the [Rodauth] authentication framework.
14
14
  🎥 Screencasts:
15
15
 
16
16
  * [Rails Authentication with Rodauth](https://www.youtube.com/watch?v=2hDpNikacf0)
17
+ * [Multifactor Authentication with Rodauth](https://www.youtube.com/watch?v=9ON-kgXpz2A&list=PLkGQXZLACDTGKsaRWstkHQdm2CUmT3SZ-) ([TOTP](https://youtu.be/9ON-kgXpz2A), [Recovery Codes](https://youtu.be/lkFCcE1Q5-w))
17
18
 
18
19
  📚 Articles:
19
20
 
@@ -66,7 +67,7 @@ Next, run the install generator:
66
67
  $ rails generate rodauth:install
67
68
  ```
68
69
 
69
- Or if you want Rodauth endpoints to be exposed via JSON API:
70
+ Or if you want Rodauth endpoints to be exposed via [JSON API]:
70
71
 
71
72
  ```sh
72
73
  $ rails generate rodauth:install --json # regular authentication using the Rails session
@@ -110,18 +111,18 @@ $ rails rodauth:routes
110
111
  ```
111
112
  Routes handled by RodauthApp:
112
113
 
113
- /login rodauth.login_path
114
- /create-account rodauth.create_account_path
115
- /verify-account-resend rodauth.verify_account_resend_path
116
- /verify-account rodauth.verify_account_path
117
- /change-password rodauth.change_password_path
118
- /change-login rodauth.change_login_path
119
- /logout rodauth.logout_path
120
- /remember rodauth.remember_path
121
- /reset-password-request rodauth.reset_password_request_path
122
- /reset-password rodauth.reset_password_path
123
- /verify-login-change rodauth.verify_login_change_path
124
- /close-account rodauth.close_account_path
114
+ GET/POST /login rodauth.login_path
115
+ GET/POST /create-account rodauth.create_account_path
116
+ GET/POST /verify-account-resend rodauth.verify_account_resend_path
117
+ GET/POST /verify-account rodauth.verify_account_path
118
+ GET/POST /change-password rodauth.change_password_path
119
+ GET/POST /change-login rodauth.change_login_path
120
+ GET/POST /logout rodauth.logout_path
121
+ GET/POST /remember rodauth.remember_path
122
+ GET/POST /reset-password-request rodauth.reset_password_request_path
123
+ GET/POST /reset-password rodauth.reset_password_path
124
+ GET/POST /verify-login-change rodauth.verify_login_change_path
125
+ GET/POST /close-account rodauth.close_account_path
125
126
  ```
126
127
 
127
128
  Using this information, you can add some basic authentication links to your
@@ -381,6 +382,7 @@ class RodauthController < ApplicationController
381
382
  when rodauth.login_path,
382
383
  rodauth.create_account_path,
383
384
  rodauth.verify_account_path,
385
+ rodauth.verify_account_resend_path,
384
386
  rodauth.reset_password_path,
385
387
  rodauth.reset_password_request_path
386
388
  "authentication"
@@ -1178,7 +1180,7 @@ License](https://opensource.org/licenses/MIT).
1178
1180
 
1179
1181
  Everyone interacting in the rodauth-rails project's codebases, issue trackers,
1180
1182
  chat rooms and mailing lists is expected to follow the [code of
1181
- conduct](https://github.com/janko/rodauth-rails/blob/master/CODE_OF_CONDUCT.md).
1183
+ conduct](CODE_OF_CONDUCT.md).
1182
1184
 
1183
1185
  [Rodauth]: https://github.com/jeremyevans/rodauth
1184
1186
  [Sequel]: https://github.com/jeremyevans/sequel
@@ -1214,3 +1216,4 @@ conduct](https://github.com/janko/rodauth-rails/blob/master/CODE_OF_CONDUCT.md).
1214
1216
  [custom mailer worker]: https://github.com/janko/rodauth-rails/wiki/Custom-Mailer-Worker
1215
1217
  [Turbo]: https://turbo.hotwired.dev/
1216
1218
  [rodauth-model]: https://github.com/janko/rodauth-model
1219
+ [JSON API]: https://github.com/janko/rodauth-rails/wiki/JSON-API
@@ -70,6 +70,17 @@ module Rodauth
70
70
  end
71
71
  end
72
72
 
73
+ def create_fixtures
74
+ test_unit_options = ::Rails.application.config.generators.options[:test_unit]
75
+ if test_unit_options[:fixture] && test_unit_options[:fixture_replacement].nil?
76
+ if ::Rails.application.config.generators.options[:rails][:test_framework] == :rspec
77
+ template "test/fixtures/accounts.yml", "spec/fixtures/accounts.yml"
78
+ else
79
+ template "test/fixtures/accounts.yml", "test/fixtures/accounts.yml"
80
+ end
81
+ end
82
+ end
83
+
73
84
  def show_instructions
74
85
  readme "INSTRUCTIONS" if behavior == :invoke
75
86
  end
@@ -77,8 +88,8 @@ module Rodauth
77
88
  private
78
89
 
79
90
  def migration_features
80
- features = [:base, :reset_password, :verify_account, :verify_login_change]
81
- features << :remember unless jwt?
91
+ features = ["base", "reset_password", "verify_account", "verify_login_change"]
92
+ features << "remember" unless jwt?
82
93
  features
83
94
  end
84
95
 
@@ -13,16 +13,11 @@ create_table :accounts do
13
13
  <% else -%>
14
14
  String :email, null: false
15
15
  <% end -%>
16
- String :status, null: false, default: "unverified"
16
+ Integer :status, null: false, default: 1
17
17
  <% if db.supports_partial_indexes? -%>
18
- index :email, unique: true, where: { status: ["unverified", "verified"] }
18
+ index :email, unique: true, where: { status: [1, 2] }
19
19
  <% else -%>
20
20
  index :email, unique: true
21
21
  <% end -%>
22
- end
23
-
24
- # Used if storing password hashes in a separate table (default)
25
- create_table :account_password_hashes do
26
- foreign_key :id, :accounts, primary_key: true, type: :Bignum
27
- String :password_hash, null: false
22
+ String :password_hash
28
23
  end
@@ -17,7 +17,7 @@ module Rodauth
17
17
  desc: "Name of the generated migration file"
18
18
 
19
19
  def create_rodauth_migration
20
- return if features.empty?
20
+ validate_features or return
21
21
 
22
22
  migration_template "db/migrate/create_rodauth.rb", File.join(db_migrate_path, "#{migration_name}.rb")
23
23
  end
@@ -30,7 +30,6 @@ module Rodauth
30
30
 
31
31
  def migration_content
32
32
  features
33
- .select { |feature| File.exist?(migration_chunk(feature)) }
34
33
  .map { |feature| File.read(migration_chunk(feature)) }
35
34
  .map { |content| erb_eval(content) }
36
35
  .join("\n")
@@ -45,19 +44,37 @@ module Rodauth
45
44
  end
46
45
  end
47
46
 
47
+ def migration_chunk(feature)
48
+ "#{MIGRATION_DIR}/#{feature}.erb"
49
+ end
50
+
51
+ def validate_features
52
+ if features.empty?
53
+ say "No features specified!", :yellow
54
+ false
55
+ elsif (features - valid_features).any?
56
+ say "No available migration for feature(s): #{(features - valid_features).join(", ")}", :red
57
+ false
58
+ else
59
+ true
60
+ end
61
+ end
62
+
63
+ def valid_features
64
+ Dir["#{MIGRATION_DIR}/*.erb"].map { |filename| File.basename(filename, ".erb") }
65
+ end
66
+
48
67
  if defined?(::ActiveRecord::Railtie) # Active Record
49
68
  include ::ActiveRecord::Generators::Migration
50
69
 
70
+ MIGRATION_DIR = "#{__dir__}/migration/active_record"
71
+
51
72
  def db_migrate_path
52
73
  return "db/migrate" unless ActiveRecord.version >= Gem::Version.new("5.0")
53
74
 
54
75
  super
55
76
  end
56
77
 
57
- def migration_chunk(feature)
58
- "#{__dir__}/migration/active_record/#{feature}.erb"
59
- end
60
-
61
78
  def migration_version
62
79
  return unless ActiveRecord.version >= Gem::Version.new("5.0")
63
80
 
@@ -95,6 +112,8 @@ module Rodauth
95
112
  else # Sequel
96
113
  include ::Rails::Generators::Migration
97
114
 
115
+ MIGRATION_DIR = "#{__dir__}/migration/sequel"
116
+
98
117
  def self.next_migration_number(dirname)
99
118
  next_migration_number = current_migration_number(dirname) + 1
100
119
  [Time.now.utc.strftime('%Y%m%d%H%M%S'), format('%.14d', next_migration_number)].max
@@ -104,10 +123,6 @@ module Rodauth
104
123
  "db/migrate"
105
124
  end
106
125
 
107
- def migration_chunk(feature)
108
- "#{__dir__}/migration/sequel/#{feature}.erb"
109
- end
110
-
111
126
  def db
112
127
  db = ::Sequel::DATABASES.first if defined?(::Sequel)
113
128
  db or fail Rodauth::Rails::Error, "missing Sequel database connection"
@@ -0,0 +1,10 @@
1
+ # Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2
+ one:
3
+ email: freddie@queen.com
4
+ password_hash: <%%= BCrypt::Password.create("password", cost: BCrypt::Engine::MIN_COST) %>
5
+ status: verified
6
+
7
+ two:
8
+ email: brian@queen.com
9
+ password_hash: <%%= BCrypt::Password.create("password", cost: BCrypt::Engine::MIN_COST) %>
10
+ status: verified
@@ -46,10 +46,7 @@ module Rodauth
46
46
  }
47
47
 
48
48
  def create_views
49
- views = features.inject([]) do |list, feature|
50
- list |= VIEWS[feature] || []
51
- list |= VIEWS[DEPENDENCIES[feature]] || []
52
- end
49
+ validate_features or return
53
50
 
54
51
  views.each do |view|
55
52
  copy_file "app/views/rodauth/#{view}.html.erb", "app/views/#{directory}/#{view}.html.erb" do |content|
@@ -63,13 +60,29 @@ module Rodauth
63
60
 
64
61
  private
65
62
 
63
+ def views
64
+ features.inject([]) do |list, feature|
65
+ list |= VIEWS.fetch(feature)
66
+ list |= VIEWS[DEPENDENCIES[feature]] || []
67
+ end
68
+ end
69
+
70
+ def validate_features
71
+ if (features - VIEWS.keys).any?
72
+ say "No available view template for feature(s): #{(features - VIEWS.keys).join(", ")}", :error
73
+ false
74
+ else
75
+ true
76
+ end
77
+ end
78
+
66
79
  def features
67
80
  if options[:all]
68
81
  VIEWS.keys
69
82
  elsif selected_features
70
83
  selected_features.map(&:to_sym)
71
84
  else
72
- rodauth_configuration.features
85
+ rodauth_configuration.features & VIEWS.keys
73
86
  end
74
87
  end
75
88
 
@@ -59,6 +59,12 @@ module Rodauth
59
59
  rodauth(name) or fail ArgumentError, "unknown rodauth configuration: #{name.inspect}"
60
60
  end
61
61
 
62
+ # The newrelic_rpm gem expects this when we pass the roda class as
63
+ # :controller in instrumentation payload.
64
+ def self.controller_path
65
+ name.underscore
66
+ end
67
+
62
68
  module RequestMethods
63
69
  def rodauth(name = nil)
64
70
  prefix = scope.rodauth(name).prefix
@@ -9,10 +9,12 @@ module Rodauth
9
9
  end
10
10
 
11
11
  def rails_account
12
+ return unless logged_in?
13
+
12
14
  account_from_session unless account
13
15
 
14
16
  unless account
15
- clear_session if logged_in?
17
+ clear_session
16
18
  return
17
19
  end
18
20
 
@@ -32,7 +32,7 @@ module Rodauth
32
32
  request = rails_request
33
33
 
34
34
  raw_payload = {
35
- controller: scope.class.superclass.name,
35
+ controller: self.class.roda_class.name,
36
36
  action: "call",
37
37
  request: request,
38
38
  params: request.filtered_parameters,
@@ -6,20 +6,34 @@ namespace :rodauth do
6
6
 
7
7
  app.opts[:rodauths].each do |configuration_name, auth_class|
8
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
9
22
 
10
- routes = auth_class.routes.map do |handle_method|
11
23
  path_method = "#{handle_method.to_s.sub(/\Ahandle_/, "")}_path"
12
24
 
13
25
  [
14
- rodauth.public_send(path_method),
26
+ verbs.join("/"),
27
+ "#{rodauth.prefix}#{path}",
15
28
  "rodauth#{configuration_name && "(:#{configuration_name})"}.#{path_method}",
16
29
  ]
17
30
  end
18
31
 
19
- padding = routes.map { |path, _| path.length }.max
32
+ verbs_padding = routes.map { |verbs, _, _| verbs.length }.max
33
+ path_padding = routes.map { |_, path, _| path.length }.max
20
34
 
21
- route_lines = routes.map do |path, code|
22
- "#{path.ljust(padding)} #{code}"
35
+ route_lines = routes.map do |verbs, path, code|
36
+ "#{verbs.ljust(verbs_padding)} #{path.ljust(path_padding)} #{code}"
23
37
  end
24
38
 
25
39
  puts "\n #{route_lines.join("\n ")}" unless route_lines.empty?
@@ -1,5 +1,5 @@
1
1
  module Rodauth
2
2
  module Rails
3
- VERSION = "1.5.1"
3
+ VERSION = "1.5.5"
4
4
  end
5
5
  end
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.require_paths = ["lib"]
18
18
 
19
19
  spec.add_dependency "railties", ">= 4.2", "< 8"
20
- spec.add_dependency "rodauth", "~> 2.23"
20
+ spec.add_dependency "rodauth", "~> 2.25"
21
21
  spec.add_dependency "roda", "~> 3.55"
22
22
  spec.add_dependency "sequel-activerecord_connection", "~> 1.1"
23
23
  spec.add_dependency "rodauth-model", "~> 0.2"
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.5.1
4
+ version: 1.5.5
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-06-19 00:00:00.000000000 Z
11
+ date: 2022-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -36,14 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '2.23'
39
+ version: '2.25'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '2.23'
46
+ version: '2.25'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: roda
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -271,6 +271,7 @@ files:
271
271
  - lib/generators/rodauth/templates/config/initializers/rodauth.rb
272
272
  - lib/generators/rodauth/templates/config/initializers/sequel.rb
273
273
  - lib/generators/rodauth/templates/db/migrate/create_rodauth.rb
274
+ - lib/generators/rodauth/templates/test/fixtures/accounts.yml
274
275
  - lib/generators/rodauth/views_generator.rb
275
276
  - lib/rodauth-rails.rb
276
277
  - lib/rodauth/rails.rb