rodauth-rails 1.5.1 → 1.5.5

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: 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