authtown 0.2.0 → 0.3.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: 5618c4b915887279ad6bfd3ba639756a63b92d1361fe3c5ef7d64fc1a9787f08
4
- data.tar.gz: 488925cf2004d158d77893acfa68566469e19b29e03abfe48d6469b4a00ebbf8
3
+ metadata.gz: 1d2619b2daf3aa55e9406234f5ebffcc6120db6b88c11b86f220349e3b1f55fc
4
+ data.tar.gz: 27d16fd12a96f4e4cda4d0c642b780768df4380132c1b93ad1c2de354ff5e58b
5
5
  SHA512:
6
- metadata.gz: 89644f9c86b9202faa8616c868956aa59a1f668418737092cb27181ba2a4d147886b6566a24c7110f3d91176acb279b92999c2cdd07b476b16466a9d4cdca1ea
7
- data.tar.gz: 7323afa6ab4142c31a4eaf5f3e22d64fa8a7b0a106075328b299413bf2e7569ddad1017c7b428ca00a44938fd1a703b722def67e258c772816f75b8b3118b9cb
6
+ metadata.gz: 0afe6909ccf879aba4e28484f3f83b035613e80e43940e1a4aba3c0b3dd67f9aae7cc3f55122ce4276eaf21426829e9c515b57b6293a431beb8acd1ab416641d
7
+ data.tar.gz: 37e8e4f7b0c438050eee6321cea152c0f776667262dee23859698c902184b6d8f69fdfd628d2e28e410e1aa40df050bd3ed43e1d0f03dba82fd5e108c3a250b8
data/.rubocop.yml CHANGED
@@ -21,3 +21,6 @@ AllCops:
21
21
  - script/**/*
22
22
  - test/fixtures/**/*
23
23
  - vendor/**/*
24
+
25
+ Metrics/ParameterLists:
26
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.0] - 2024-04-07
11
+
12
+ - Refactor how Bridgetown's view layer is integrated with Rodauth, improve performance
13
+
10
14
  ## [0.2.0] - 2024-04-03
11
15
 
12
16
  - Integration with new bridgetown_sequel gem tested
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Metrics/BlockLength
4
+ # @param config [Bridgetown::Configuration::ConfigurationDSL]
5
+ # @param rodauth_config [Proc]
6
+ # @param account_landing_page [String] relative URL to redirect to upon login / create account
7
+ # @param user_class_resolver [Proc] return the class of the user model
8
+ # @param user_name_field [String] save a name when creating a new user, or set to nil to skip
9
+ Bridgetown.initializer :authtown do |
10
+ config,
11
+ rodauth_config: nil,
12
+ account_landing_page: "/account/profile",
13
+ user_class_resolver: -> { User },
14
+ user_name_field: :first_name
15
+ |
16
+
17
+ config.authtown ||= {}
18
+ config.authtown.user_class_resolver ||= user_class_resolver
19
+
20
+ config.only :server do
21
+ require "authtown/routes/rodauth"
22
+
23
+ # @param app [Class<Roda>]
24
+ config.roda do |app|
25
+ app.prepend Authtown::ViewMixin
26
+
27
+ secret = ENV.fetch("RODA_SECRET_KEY")
28
+ app.plugin(:sessions, secret:)
29
+
30
+ app.plugin :rodauth, render: false do
31
+ enable :login, :logout, :create_account, :remember, :reset_password, :internal_request
32
+ hmac_secret secret
33
+
34
+ base_url config.url
35
+
36
+ prefix "/auth"
37
+
38
+ login_redirect account_landing_page
39
+ create_account_redirect account_landing_page
40
+ logout_redirect "/"
41
+
42
+ set_deadline_values? true # for remember, etc.
43
+ # TODO: why isn't this working? might be a schema issue with old AR:
44
+ remember_deadline_interval days: 30
45
+ extend_remember_deadline? true
46
+
47
+ login_label "Email Address"
48
+ login_button "Sign In"
49
+
50
+ accounts_table :users
51
+ account_password_hash_column :password_hash
52
+
53
+ require_login_confirmation? false
54
+ require_password_confirmation? false
55
+
56
+ # Require passwords to have at least 8 characters
57
+ password_minimum_length 8
58
+
59
+ # Don't allow passwords to be too long, to prevent long password DoS attacks
60
+ password_maximum_length 64
61
+
62
+ reset_password_email_sent_redirect "/account/reset-link-sent"
63
+ reset_password_autologin? true
64
+ reset_password_redirect account_landing_page
65
+
66
+ before_create_account do
67
+ # Ensure timestamps get saved
68
+ account[:created_at] = account[:updated_at] = Time.now
69
+ next unless user_name_field
70
+
71
+ # Save name details
72
+ account[user_name_field] = param(user_name_field) if param(user_name_field)
73
+ end
74
+
75
+ after_login do
76
+ remember_login
77
+ end
78
+
79
+ instance_exec(&rodauth_config) if rodauth_config
80
+ end
81
+ end
82
+ end
83
+
84
+ # Register your builder:
85
+ config.builder Authtown::Builder
86
+ end
87
+ # rubocop:enable Metrics/BlockLength
@@ -10,9 +10,10 @@ module Authtown
10
10
 
11
11
  init_current_user
12
12
 
13
- # hook :authtown, :initialized do |rodauth|
14
- # Lifeform::Form.rodauth = rodauth
15
- # end
13
+ # @example hook usage:
14
+ # hook :authtown, :initialized do |rodauth|
15
+ # Lifeform::Form.rodauth = rodauth
16
+ # end
16
17
  Bridgetown::Hooks.trigger(:authtown, :initialized, rodauth)
17
18
 
18
19
  r.on "auth" do
@@ -23,9 +24,8 @@ module Authtown
23
24
  def init_current_user
24
25
  Authtown::Current.user =
25
26
  if rodauth.logged_in?
26
- account_id = rodauth.account_from_session[:id]
27
- user_class = bridgetown_site.config.authtown.user_class_resolver.()
28
- user_class[account_id]
27
+ # load existing account hash into Model:
28
+ bridgetown_site.config.authtown.user_class_resolver.().(rodauth.account_from_session)
29
29
  end
30
30
  end
31
31
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Authtown
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
@@ -3,44 +3,64 @@
3
3
  module Authtown::ViewMixin
4
4
  def locals = @_route_locals
5
5
 
6
- # TODO: this is super hacky
6
+ def current_user = Authtown::Current.user
7
+
8
+ ### Compatibility layer to translate Rodauth view calls to Bridgetown Routing
9
+
10
+ # Return a single hash combining the template and opts arguments.
11
+ def parse_template_opts(template, opts)
12
+ opts = opts.to_h
13
+ if template.is_a?(Hash)
14
+ opts.merge!(template)
15
+ else
16
+ opts[:template] = template
17
+ opts
18
+ end
19
+ end
20
+
21
+ def find_template(opts) = opts
22
+
23
+ def template_path(opts) = opts[:template]
24
+
25
+ def login_failed_reset_password_request_form
26
+ # part of reset_password internals…no-op since we're rendering our own forms
27
+ end
28
+
7
29
  def view(*args, view_class: Bridgetown::ERBView, **kwargs) # rubocop:disable Metrics
8
30
  kwargs = args.first if args.first.is_a?(Hash)
9
31
 
10
- # If we're farming out to another view, let's go!
11
- unless kwargs.empty?
12
- response["X-Bridgetown-SSR"] = "1"
32
+ return super if kwargs.empty? # regular Bridgetown behavior
13
33
 
14
- # UGH, hate special casing this
15
- if kwargs.dig(:locals, :rodauth)&.prefix
16
- kwargs[:template] =
17
- "#{kwargs.dig(:locals, :rodauth).prefix.delete_prefix("/")}/#{kwargs[:template]}"
18
- end
34
+ unless kwargs.dig(:locals, :rodauth)
35
+ raise "The `view' method with keyword arguments should only be used by Rodauth internally. " \
36
+ "It is not supported by Bridgetown's view layer."
37
+ end
19
38
 
20
- Bridgetown::Routes::Manifest.generate_manifest(bridgetown_site).each do |route|
21
- file, localized_file_slugs = route
39
+ if kwargs.dig(:locals, :rodauth)&.prefix
40
+ kwargs[:template] =
41
+ "#{kwargs.dig(:locals, :rodauth).prefix.delete_prefix("/")}/#{kwargs[:template]}"
42
+ end
22
43
 
23
- file_slug = localized_file_slugs.first
44
+ # TODO: this should really be some sort of exposed method from the routes plugin
45
+ response["X-Bridgetown-SSR"] = "1"
24
46
 
25
- next unless file_slug == kwargs[:template]
47
+ Bridgetown::Routes::Manifest.generate_manifest(bridgetown_site).each do |route|
48
+ file, localized_file_slugs = route
26
49
 
27
- Bridgetown::Routes::CodeBlocks.eval_route_file file, file_slug, self
28
- route_block = Bridgetown::Routes::CodeBlocks.route_block(file_slug)
29
- response.instance_variable_set(
30
- :@_route_file_code, route_block.instance_variable_get(:@_route_file_code)
31
- ) # could be nil
32
- @_route_locals = kwargs[:locals]
33
- return instance_exec(request, &route_block)
34
- end
50
+ file_slug = localized_file_slugs.first
35
51
 
36
- Bridgetown.logger.warn("Template not found: #{kwargs[:template]}")
37
- return nil # couldn't find template, 404
52
+ next unless file_slug == kwargs[:template]
53
+
54
+ Bridgetown::Routes::CodeBlocks.eval_route_file file, file_slug, self
55
+ route_block = Bridgetown::Routes::CodeBlocks.route_block(file_slug)
56
+ response.instance_variable_set(
57
+ :@_route_file_code, route_block.instance_variable_get(:@_route_file_code)
58
+ ) # could be nil
59
+ @_route_locals = kwargs[:locals]
60
+ return instance_exec(request, &route_block)
38
61
  end
39
62
 
40
- response._fake_resource_view(
41
- view_class:, roda_app: self, bridgetown_site:
42
- )
63
+ Bridgetown.logger.warn("Rodauth template not found: #{kwargs[:template]}")
64
+ nil # couldn't find template, 404
43
65
  end
44
-
45
- def current_user = Authtown::Current.user
46
66
  end
data/lib/authtown.rb CHANGED
@@ -51,81 +51,4 @@ class Authtown::Current
51
51
  end
52
52
  end
53
53
 
54
- # rubocop:disable Metrics/BlockLength
55
- # @param config [Bridgetown::Configuration::ConfigurationDSL]
56
- # @param rodauth_config [Proc]
57
- Bridgetown.initializer :authtown do |
58
- config,
59
- rodauth_config: nil,
60
- account_landing_page: "/account/profile",
61
- user_class_resolver: -> { User }
62
- |
63
-
64
- config.authtown ||= {}
65
- config.authtown.user_class_resolver ||= user_class_resolver
66
-
67
- config.only :server do
68
- require "authtown/routes/rodauth"
69
-
70
- # @param app [Class<Roda>]
71
- config.roda do |app|
72
- app.prepend Authtown::ViewMixin
73
-
74
- secret = ENV.fetch("RODA_SECRET_KEY")
75
- app.plugin(:sessions, secret:)
76
-
77
- app.plugin :rodauth do
78
- enable :login, :logout, :create_account, :remember, :reset_password, :internal_request
79
- hmac_secret secret
80
-
81
- base_url config.url
82
-
83
- prefix "/auth"
84
-
85
- login_redirect account_landing_page
86
- create_account_redirect account_landing_page
87
- logout_redirect "/"
88
-
89
- set_deadline_values? true # for remember, etc.
90
- remember_deadline_interval days: 30 # TODO: why isn't this working?!
91
- extend_remember_deadline? true
92
-
93
- login_label "Email Address"
94
- login_button "Sign In"
95
-
96
- accounts_table :users
97
- account_password_hash_column :password_hash
98
-
99
- require_login_confirmation? false
100
- require_password_confirmation? false
101
-
102
- # Require passwords to have at least 8 characters
103
- password_minimum_length 8
104
-
105
- # Don't allow passwords to be too long, to prevent long password DoS attacks
106
- password_maximum_length 64
107
-
108
- reset_password_email_sent_redirect "/account/reset-link-sent"
109
- reset_password_autologin? true
110
- reset_password_redirect account_landing_page
111
-
112
- before_create_account do
113
- # Make sure timestamps get saved
114
- account[:created_at] = account[:updated_at] = Time.now
115
-
116
- account[:first_name] = param(:first_name) if param(:first_name)
117
- end
118
-
119
- after_login do
120
- remember_login
121
- end
122
-
123
- instance_exec(&rodauth_config) if rodauth_config
124
- end
125
- end
126
- end
127
-
128
- # Register your builder:
129
- config.builder Authtown::Builder
130
- end
131
- # rubocop:enable Metrics/BlockLength
54
+ require "authtown/initializer"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authtown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bridgetown Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-03 00:00:00.000000000 Z
11
+ date: 2024-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bridgetown
@@ -132,6 +132,7 @@ files:
132
132
  - bridgetown.automation.rb
133
133
  - lib/authtown.rb
134
134
  - lib/authtown/builder.rb
135
+ - lib/authtown/initializer.rb
135
136
  - lib/authtown/routes/rodauth.rb
136
137
  - lib/authtown/version.rb
137
138
  - lib/authtown/view_mixin.rb