lsa_tdx_feedback 1.0.2 → 1.0.3

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: 3cbc671304d3c3452ec0391cac7dbcb0a03cf3ce8ad49eed9381ea4ad91e0ecc
4
- data.tar.gz: 6f4df6c28cb3af52851e8c13b249e269f3eefed11cbe091d3b0161b0b3a9d3bd
3
+ metadata.gz: 2688de4eb43f66ca59ebecee11a93685a13b03b6f28dd49138748503b8266828
4
+ data.tar.gz: 780e62b78b1a4fca899e8a90dcbf9956189fef71c4008fe5d5b84eec807716a0
5
5
  SHA512:
6
- metadata.gz: a57274ebc7706e25024df0d1c496a6a2b41f7fa9b13bbfd92a60154a9e39c1343c306a0fbc8165e9237217b41d47cdcffc03cf84395c5dfccefd4ab76ca35ea0
7
- data.tar.gz: 717699dfeb877349310d492e04a36f70770a9c456c609358bf963bffbfcd9de0332edf6b74c4022ade130131b2df5c04b10beadbb0cb142264a57ba9ccf178f9
6
+ metadata.gz: b2934aef5a781f0454893c482f0bdea846c2cf6fed171d5677c0ce55dee93581221eff9c12b6345f5be8f61bc92493b87bb3a7e33a57244eca1eb9065d5f13de
7
+ data.tar.gz: ad7a6d864c9bee29a5cb311eebf4ad040bd57cd5db2505344fc16f9f4e7ef11344509cd42f6043e2bee3a746698d4d44630f4765d9c9355f841239639f83b5c5
data/CHANGELOG.md CHANGED
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Added
11
+ - **Documentation**: Added Rails 8 authentication setup instructions to README
12
+ - Step-by-step guide for generating Rails 8.1.1's built-in authentication system
13
+ - Instructions for creating `current_user` helper method to match Devise pattern
14
+ - Examples for protecting actions and excluding authentication for specific controllers
15
+ - Documentation on using `allow_unauthenticated_access` for public pages
16
+
17
+ ## [1.0.3] - 2025-12-08
18
+
19
+ ### Fixed
20
+ - **Turbo Drive Compatibility**: Fixed feedback button not working after Turbo navigation
21
+ - Added proper event listener cleanup to prevent duplicate handlers
22
+ - Added support for `turbo:load` and `turbo:frame-load` events
23
+ - Re-initializes feedback functionality on each Turbo navigation
24
+ - Prevents memory leaks by properly removing old event listeners before attaching new ones
25
+ - Maintains backward compatibility with traditional page loads
26
+
10
27
  ## [1.0.2] - 2025-01-27
11
28
 
12
29
  ### Fixed
@@ -16,7 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
33
 
17
34
  ### Fixed
18
35
  - **TDX API Integration Issues**: Resolved HTTP 422 errors when creating tickets
19
- - Fixed invalid Classification value (changed from 300 to 46)
36
+ - Fixed invalid Classification value
20
37
  - Updated configuration validation to handle both string and integer values for `default_classification`
21
38
  - Simplified ticket payload structure to include only essential fields
22
39
  - Fixed string interpolation in `build_description` method
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lsa_tdx_feedback (1.0.1)
4
+ lsa_tdx_feedback (1.0.2)
5
5
  httparty (~> 0.22)
6
6
  rails (>= 6.0)
7
7
  redis (>= 4.0)
@@ -174,7 +174,7 @@ GEM
174
174
  stringio
175
175
  public_suffix (6.0.2)
176
176
  racc (1.8.1)
177
- rack (3.2.1)
177
+ rack (3.2.3)
178
178
  rack-session (2.1.1)
179
179
  base64 (>= 0.1.0)
180
180
  rack (>= 3.0.0)
data/README.md CHANGED
@@ -238,6 +238,173 @@ class ApplicationController < ActionController::Base
238
238
  end
239
239
  ```
240
240
 
241
+ ## Rails 8 Authentication Setup
242
+
243
+ If you're using Rails 8.1.1's built-in authentication system, here's how to set it up and create a `current_user` helper method similar to Devise.
244
+
245
+ ### Step 1: Generate the Authentication System
246
+
247
+ Run the Rails generator:
248
+
249
+ ```bash
250
+ bin/rails generate authentication
251
+ ```
252
+
253
+ This creates:
254
+
255
+ - User model
256
+ - Session model
257
+ - Current class (for per-request attributes)
258
+ - Controllers (SessionsController, PasswordsController)
259
+ - Views for login/password reset
260
+ - Migrations
261
+
262
+ ### Step 2: Run Migrations
263
+
264
+ ```bash
265
+ bin/rails db:migrate
266
+ ```
267
+
268
+ ### Step 3: Add current_user initializer for Rails 8 internal controllers
269
+ Creating an initializer to make current_user available to all controllers, including Rails internals:
270
+
271
+ ```ruby
272
+ # config/initializers/current_user.rb
273
+ # Make current_user available to all controllers, including Rails internal controllers
274
+ # This is needed for gems like lsa_tdx_feedback that call current_user on all controllers
275
+ ActionController::Base.class_eval do
276
+ helper_method :current_user
277
+
278
+ private
279
+
280
+ def current_user
281
+ # Use Current.user if available (set by ApplicationController)
282
+ return Current.user if Current.user
283
+
284
+ # For controllers that don't inherit from ApplicationController,
285
+ # try to find the session manually
286
+ return nil unless respond_to?(:cookies, true)
287
+
288
+ begin
289
+ session_id = cookies.signed[:session_id] if cookies.signed
290
+ return nil unless session_id
291
+
292
+ session = Session.find_by(id: session_id)
293
+ session&.user
294
+ rescue => e
295
+ # If anything goes wrong (e.g., database not available), return nil
296
+ Rails.logger.debug("Error in current_user: #{e.message}") if defined?(Rails.logger)
297
+ nil
298
+ end
299
+ end
300
+ end
301
+ ```
302
+
303
+ This makes `current_user` available in all controllers and views, including Rails internals like ActionController::Base.
304
+
305
+ ### Step 3A: Create an initializer (config/initializers/lsa_tdx_feedback.rb) that skips authentication for the feedback controller, since feedback forms should be public
306
+
307
+ ```ruby
308
+ # Configure lsa_tdx_feedback gem to allow unauthenticated access
309
+ # Feedback forms should be accessible without authentication
310
+ Rails.application.config.to_prepare do
311
+ if defined?(LsaTdxFeedback::FeedbackController)
312
+ LsaTdxFeedback::FeedbackController.class_eval do
313
+ # Skip authentication for feedback submissions
314
+ # Use raise: false to prevent errors if the before_action doesn't exist
315
+ skip_before_action :require_authentication, raise: false
316
+ end
317
+ end
318
+ rescue => e
319
+ Rails.logger.warn("Could not configure LsaTdxFeedback: #{e.message}") if defined?(Rails.logger)
320
+ end
321
+ ```
322
+
323
+ and update request_authentication in the Authentication concern ( app/controllers/concerns/authentication.rb ) to use main_app.new_session_path so it works when called from engine controllers.
324
+
325
+ ```ruby
326
+ # Update request_authentication in the Authentication concern to use main_app.new_session_path so it works when called from engine controllers.
327
+ ...
328
+ redirect_to main_app.new_session_path # around line 34 in the Authentication concern
329
+ ...
330
+ ```
331
+
332
+
333
+ ### Step 4: Protect Actions (Optional)
334
+
335
+ To require authentication for specific actions:
336
+
337
+ ```ruby
338
+ class SomeController < ApplicationController
339
+ before_action :require_authentication
340
+
341
+ private
342
+
343
+ def require_authentication
344
+ redirect_to new_session_path unless current_user
345
+ end
346
+ end
347
+ ```
348
+
349
+ ### Excluding Authentication for Specific Controllers
350
+
351
+ If you need to exclude authentication for specific controllers or actions (e.g., a public home page), use the `allow_unauthenticated_access` method provided by the Authentication concern:
352
+
353
+ ```ruby
354
+ class HomeController < ApplicationController
355
+ allow_unauthenticated_access only: [:index]
356
+
357
+ def index
358
+ end
359
+ end
360
+ ```
361
+
362
+ This skips authentication only for the `index` action. The Authentication concern uses `skip_before_action :require_authentication` under the hood.
363
+
364
+ **Alternative options:**
365
+
366
+ If you want to skip authentication for all actions in the HomeController:
367
+
368
+ ```ruby
369
+ class HomeController < ApplicationController
370
+ allow_unauthenticated_access
371
+
372
+ def index
373
+ end
374
+ end
375
+ ```
376
+
377
+ Or if you want to skip for multiple specific actions:
378
+
379
+ ```ruby
380
+ class HomeController < ApplicationController
381
+ allow_unauthenticated_access only: [:index, :show]
382
+
383
+ def index
384
+ end
385
+ end
386
+ ```
387
+
388
+ The `only:` option limits it to specific actions, while omitting it skips authentication for all actions in that controller.
389
+
390
+ ### How It Works
391
+
392
+ - `Current` is an `ActiveSupport::CurrentAttributes` class that stores per-request attributes
393
+ - After login, `Current.user` is set to the authenticated user
394
+ - `current_user` wraps `Current.user` for Devise-like usage
395
+ - Works with authorization libraries like Pundit that expect `current_user`
396
+
397
+ ### Routes
398
+
399
+ The generator adds routes like:
400
+
401
+ - `new_session_path` - login page
402
+ - `session_path` - create/destroy session
403
+ - `new_password_path` - password reset request
404
+ - etc.
405
+
406
+ After running the generator, you can use `current_user` in controllers and views just like with Devise.
407
+
241
408
  ## TDX API Configuration
242
409
 
243
410
  ### Required TDX Settings
@@ -1,21 +1,33 @@
1
1
  /**
2
2
  * LsaTdxFeedback JavaScript - Self-contained feedback modal functionality
3
+ * Turbo Drive compatible
3
4
  */
4
5
  (function() {
5
6
  'use strict';
6
7
 
7
- // Ensure we don't initialize multiple times
8
- if (window.LsaTdxFeedback && window.LsaTdxFeedback.initialized) {
9
- return;
10
- }
11
-
12
8
  var LsaTdxFeedback = {
13
9
  initialized: false,
14
10
  modal: null,
15
11
  form: null,
12
+ handlers: {
13
+ triggerClick: null,
14
+ closeClick: null,
15
+ cancelClick: null,
16
+ backdropClick: null,
17
+ formSubmit: null,
18
+ escapeKey: null
19
+ },
16
20
 
17
21
  init: function() {
18
- if (this.initialized) return;
22
+ // Clean up existing listeners if already initialized (for Turbo navigation)
23
+ if (this.initialized) {
24
+ this.cleanup();
25
+ }
26
+
27
+ // Reset state for re-initialization
28
+ this.initialized = false;
29
+ this.modal = null;
30
+ this.form = null;
19
31
 
20
32
  // Wait for DOM to be ready
21
33
  if (document.readyState === 'loading') {
@@ -27,6 +39,52 @@
27
39
  this.initialized = true;
28
40
  },
29
41
 
42
+ cleanup: function() {
43
+ // Remove all event listeners before re-initializing
44
+ var self = this;
45
+
46
+ if (this.handlers.triggerClick) {
47
+ var triggerBtn = document.getElementById('lsa-tdx-feedback-trigger');
48
+ if (triggerBtn) {
49
+ triggerBtn.removeEventListener('click', this.handlers.triggerClick);
50
+ }
51
+ }
52
+
53
+ if (this.modal) {
54
+ var closeBtn = this.modal.querySelector('.lsa-tdx-feedback-close-btn');
55
+ var cancelBtn = this.modal.querySelector('.lsa-tdx-feedback-cancel-btn');
56
+ var backdrop = this.modal.querySelector('.lsa-tdx-feedback-modal-backdrop');
57
+
58
+ if (closeBtn && this.handlers.closeClick) {
59
+ closeBtn.removeEventListener('click', this.handlers.closeClick);
60
+ }
61
+ if (cancelBtn && this.handlers.cancelClick) {
62
+ cancelBtn.removeEventListener('click', this.handlers.cancelClick);
63
+ }
64
+ if (backdrop && this.handlers.backdropClick) {
65
+ backdrop.removeEventListener('click', this.handlers.backdropClick);
66
+ }
67
+ }
68
+
69
+ if (this.form && this.handlers.formSubmit) {
70
+ this.form.removeEventListener('submit', this.handlers.formSubmit);
71
+ }
72
+
73
+ if (this.handlers.escapeKey) {
74
+ document.removeEventListener('keydown', this.handlers.escapeKey);
75
+ }
76
+
77
+ // Clear handler references
78
+ this.handlers = {
79
+ triggerClick: null,
80
+ closeClick: null,
81
+ cancelClick: null,
82
+ backdropClick: null,
83
+ formSubmit: null,
84
+ escapeKey: null
85
+ };
86
+ },
87
+
30
88
  bindEvents: function() {
31
89
  var self = this;
32
90
 
@@ -42,10 +100,11 @@
42
100
  // Trigger button
43
101
  var triggerBtn = document.getElementById('lsa-tdx-feedback-trigger');
44
102
  if (triggerBtn) {
45
- triggerBtn.addEventListener('click', function(e) {
103
+ this.handlers.triggerClick = function(e) {
46
104
  e.preventDefault();
47
105
  self.showModal();
48
- });
106
+ };
107
+ triggerBtn.addEventListener('click', this.handlers.triggerClick);
49
108
  }
50
109
 
51
110
  // Close buttons
@@ -54,39 +113,44 @@
54
113
  var backdrop = this.modal.querySelector('.lsa-tdx-feedback-modal-backdrop');
55
114
 
56
115
  if (closeBtn) {
57
- closeBtn.addEventListener('click', function(e) {
116
+ this.handlers.closeClick = function(e) {
58
117
  e.preventDefault();
59
118
  self.hideModal();
60
- });
119
+ };
120
+ closeBtn.addEventListener('click', this.handlers.closeClick);
61
121
  }
62
122
 
63
123
  if (cancelBtn) {
64
- cancelBtn.addEventListener('click', function(e) {
124
+ this.handlers.cancelClick = function(e) {
65
125
  e.preventDefault();
66
126
  self.hideModal();
67
- });
127
+ };
128
+ cancelBtn.addEventListener('click', this.handlers.cancelClick);
68
129
  }
69
130
 
70
131
  if (backdrop) {
71
- backdrop.addEventListener('click', function(e) {
132
+ this.handlers.backdropClick = function(e) {
72
133
  if (e.target === backdrop) {
73
134
  self.hideModal();
74
135
  }
75
- });
136
+ };
137
+ backdrop.addEventListener('click', this.handlers.backdropClick);
76
138
  }
77
139
 
78
140
  // Form submission
79
- this.form.addEventListener('submit', function(e) {
141
+ this.handlers.formSubmit = function(e) {
80
142
  e.preventDefault();
81
143
  self.submitFeedback();
82
- });
144
+ };
145
+ this.form.addEventListener('submit', this.handlers.formSubmit);
83
146
 
84
147
  // Escape key to close modal
85
- document.addEventListener('keydown', function(e) {
86
- if (e.key === 'Escape' && self.modal.style.display !== 'none') {
148
+ this.handlers.escapeKey = function(e) {
149
+ if (e.key === 'Escape' && self.modal && self.modal.style.display !== 'none') {
87
150
  self.hideModal();
88
151
  }
89
- });
152
+ };
153
+ document.addEventListener('keydown', this.handlers.escapeKey);
90
154
  },
91
155
 
92
156
  showModal: function() {
@@ -226,6 +290,26 @@
226
290
  // Export to global scope
227
291
  window.LsaTdxFeedback = LsaTdxFeedback;
228
292
 
229
- // Auto-initialize
230
- LsaTdxFeedback.init();
293
+ // Initialize on DOM ready (for traditional page loads)
294
+ if (document.readyState === 'loading') {
295
+ document.addEventListener('DOMContentLoaded', function() {
296
+ LsaTdxFeedback.init();
297
+ });
298
+ } else {
299
+ // DOM already loaded
300
+ LsaTdxFeedback.init();
301
+ }
302
+
303
+ // Initialize on Turbo navigation (for Turbo Drive)
304
+ document.addEventListener('turbo:load', function() {
305
+ LsaTdxFeedback.init();
306
+ });
307
+
308
+ // Also handle turbo:frame-load for Turbo Frames (optional)
309
+ document.addEventListener('turbo:frame-load', function(e) {
310
+ // Only re-initialize if the frame contains our elements
311
+ if (e.target.querySelector && e.target.querySelector('#lsa-tdx-feedback-trigger')) {
312
+ LsaTdxFeedback.init();
313
+ }
314
+ });
231
315
  })();
@@ -1,3 +1,3 @@
1
1
  module LsaTdxFeedback
2
- VERSION = '1.0.2'
2
+ VERSION = '1.0.3'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lsa_tdx_feedback
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - LSA Rails Team