Skip to content

Commit 4b8c00b

Browse files
Clean up Lookbook-related alerts (#2846)
Co-authored-by: Cameron Dutro <[email protected]>
1 parent 1c11520 commit 4b8c00b

File tree

15 files changed

+53
-52
lines changed

15 files changed

+53
-52
lines changed

.changeset/heavy-radios-confess.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/view-components": patch
3+
---
4+
5+
Clean up Lookbook-related security alerts.

app/components/primer/alpha/toggle_switch.rb

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,6 @@ def initialize(src: nil, csrf_token: nil, checked: false, enabled: true, size: S
5656
}
5757

5858
@system_arguments[:src] = @src if @src
59-
60-
return unless @src && @csrf_token
61-
62-
@system_arguments[:csrf] = @csrf_token
6359
end
6460

6561
def on?
@@ -73,6 +69,22 @@ def enabled?
7369
def disabled?
7470
!enabled?
7571
end
72+
73+
private
74+
75+
def before_render
76+
@csrf_token ||= view_context.form_authenticity_token(
77+
form_options: {
78+
method: :post,
79+
action: @src
80+
}
81+
)
82+
83+
@system_arguments[:data] = merge_data(
84+
@system_arguments,
85+
{ data: { csrf: @csrf_token } }
86+
)
87+
end
7688
end
7789
end
7890
end

app/components/primer/alpha/toggle_switch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class ToggleSwitchElement extends HTMLElement {
1919

2020
get csrf(): string | null {
2121
const csrfElement = this.querySelector('[data-csrf]')
22-
return this.getAttribute('csrf') || (csrfElement instanceof HTMLInputElement && csrfElement.value) || null
22+
return this.getAttribute('data-csrf') || (csrfElement instanceof HTMLInputElement && csrfElement.value) || null
2323
}
2424

2525
get csrfField(): string {

app/lib/primer/attributes_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def merge_aria(*hashes)
5454
# It's designed to be used to normalize and merge data information from system_arguments
5555
# hashes. Consider using this pattern in component initializers:
5656
#
57-
# @system_arguments[:data] = merge_aria(
57+
# @system_arguments[:data] = merge_data(
5858
# @system_arguments,
5959
# { data: { foo: "bar" } }
6060
# )

demo/app/controllers/application_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
# :nodoc:
44
class ApplicationController < ActionController::Base
5-
protect_from_forgery
5+
protect_from_forgery with: :exception
66
end

demo/app/controllers/auto_check_controller.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
# For auto-check previews
44
# :nocov:
55
class AutoCheckController < ApplicationController
6-
skip_before_action :verify_authenticity_token
7-
86
def error
97
render partial: "auto_check/error_message",
108
locals: { input_value: params[:value] },

demo/app/controllers/toggle_switch_controller.rb

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,37 @@ class << self
77
attr_accessor :last_request
88
end
99

10-
skip_before_action :verify_authenticity_token
10+
rescue_from ActionController::InvalidAuthenticityToken, with: :handle_invalid_authenticity_token
1111

1212
before_action :reject_non_ajax_request
13-
before_action :verify_artificial_authenticity_token
1413

1514
def create
1615
# lol this is so not threadsafe
1716
self.class.last_request = request
1817

1918
sleep 1 unless Rails.env.test?
2019

20+
if params[:fail] == "true"
21+
render status: :internal_server_error, plain: "Something went wrong."
22+
return
23+
end
24+
2125
head :accepted
2226
end
2327

2428
private
2529

30+
def handle_invalid_authenticity_token
31+
render status: :unauthorized, plain: "Bad CSRF token."
32+
end
33+
2634
# this mimics dotcom behavior
2735
def reject_non_ajax_request
2836
return if request.headers["HTTP_REQUESTED_WITH"] == "XMLHttpRequest"
2937

3038
head :unprocessable_entity
3139
end
3240

33-
def verify_artificial_authenticity_token
34-
# don't check token if not provided
35-
return unless form_params[:authenticity_token]
36-
37-
# if provided, check token
38-
return if form_params[:authenticity_token] == "let_me_in"
39-
40-
render status: :unauthorized, plain: "Bad CSRF token"
41-
end
42-
4341
def form_params
4442
params.permit(:value, :authenticity_token)
4543
end

demo/app/views/lookbook/panels/_assets.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
<h4 class="asset-title font-mono"><%= asset[:path].relative_path_from(Primer::ViewComponents.root) %></h4>
3535
</header>
3636
<div class="asset-contents">
37-
<%= code language: asset[:language], line_numbers: true do %><%== File.read(asset[:path]) %><% end %>
37+
<%= code language: asset[:language], line_numbers: true do %><%= File.read(asset[:path]) %><% end %>
3838
</div>
3939
</div>
4040
<% end %>

demo/config/environments/test.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
config.action_dispatch.show_exceptions = false
3232

3333
# Disable request forgery protection in test environment.
34-
config.action_controller.allow_forgery_protection = false
34+
config.action_controller.allow_forgery_protection = true
3535

3636
# Print deprecation notices to the stderr.
3737
config.active_support.deprecation = :stderr
@@ -48,9 +48,7 @@
4848
config.autoload_paths << Rails.root.join("..", "test", "forms")
4949
config.view_component.preview_paths << Rails.root.join("..", "test", "previews")
5050

51-
# rubocop:disable Style/IfUnlessModifier
5251
if ENV.fetch("VC_COMPAT_PATCH_ENABLED", "false") == "true"
5352
config.view_component.capture_compatibility_patch_enabled = true
5453
end
55-
# rubocop:enable Style/IfUnlessModifier
5654
end

lib/primer/forms/toggle_switch.html.erb

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,5 @@
1010

1111
<div><%= render(Caption.new(input: @input)) %></div>
1212
</span>
13-
<%
14-
csrf = @input.csrf || @view_context.form_authenticity_token(
15-
form_options: {
16-
method: :post,
17-
action: @input.src
18-
}
19-
)
20-
%>
21-
<%= render(Primer::Alpha::ToggleSwitch.new(src: @input.src, csrf: csrf, **@input.input_arguments)) %>
13+
<%= render(Primer::Alpha::ToggleSwitch.new(src: @input.src, csrf_token: @input.csrf, **@input.input_arguments)) %>
2214
<% end %>

previews/primer/alpha/toggle_switch_preview.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def with_no_src
5252
end
5353

5454
def with_csrf_token
55-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.toggle_switch_index_path, csrf_token: "let_me_in"))
55+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.toggle_switch_index_path))
5656
end
5757

5858
def with_bad_csrf_token
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
<%= render(ExampleToggleSwitchForm.new(csrf: "let_me_in", label: "Good example", src: toggle_switch_index_path, id: "success-toggle")) %>
1+
<%= render(ExampleToggleSwitchForm.new(label: "Good example", src: toggle_switch_index_path, id: "success-toggle")) %>
22
<hr>
3-
<%= render(ExampleToggleSwitchForm.new(csrf: "a_bad_value", label: "Bad example", src: toggle_switch_index_path, id: "error-toggle")) %>
3+
<%= render(ExampleToggleSwitchForm.new(label: "Bad example", src: toggle_switch_index_path(fail: true), id: "error-toggle")) %>

test/components/alpha/toggle_switch_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def test_small
6666
def test_csrf_token
6767
render_inline(Primer::Alpha::ToggleSwitch.new(src: "/foo", csrf_token: "abc123"))
6868

69-
assert_selector("[csrf]")
69+
assert_selector("[data-csrf]")
7070
end
7171
end
7272
end

test/lib/primer/forms/integration_forms_test.rb

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,12 @@ def test_toggle_switch_form_errors
4747
wait_for_toggle_switch_spinner
4848

4949
assert_selector("#error-toggle [data-target='toggle-switch.errorIcon']")
50-
assert_selector(".FormControl-inlineValidation", text: "Bad CSRF token")
50+
assert_selector(".FormControl-inlineValidation", text: "Something went wrong.")
5151

52-
page.evaluate_script(<<~JAVASCRIPT)
53-
document
54-
.querySelector('toggle-switch#error-toggle')
55-
.setAttribute('csrf', 'let_me_in');
56-
JAVASCRIPT
57-
58-
find("#error-toggle").click
52+
find("#success-toggle").click
5953
wait_for_toggle_switch_spinner
6054

61-
refute_selector("#error-toggle [data-target='toggle-switch.errorIcon']")
62-
refute_selector("#error-toggle", text: "Bad CSRF token")
55+
refute_selector("#success-toggle [data-target='toggle-switch.errorIcon']")
6356
end
6457

6558
def test_action_menu_form_input

test/lib/primer/forms/toggle_switch_form_test.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,19 @@
55
class Primer::Forms::ToggleSwitchFormTest < Minitest::Test
66
include Primer::ComponentTestHelpers
77

8-
def test_it_renders_with_a_name
9-
bogus_csrf = "let me in"
10-
render_inline(ExampleToggleSwitchForm.new(csrf: bogus_csrf, src: "/toggle_switch"))
8+
def test_it_renders
9+
render_inline(ExampleToggleSwitchForm.new(src: "/toggle_switch"))
1110

12-
assert_selector "toggle-switch[src='/toggle_switch'][csrf='#{bogus_csrf}']"
11+
assert_selector "toggle-switch[src='/toggle_switch']"
1312
assert_selector "em", text: "favorite"
1413
end
1514

15+
def test_accepts_custom_csrf_token
16+
bogus_csrf = "let me in"
17+
render_inline(ExampleToggleSwitchForm.new(csrf: bogus_csrf, src: "/toggle_switch"))
18+
assert_selector "toggle-switch[data-csrf='#{bogus_csrf}']"
19+
end
20+
1621
def test_can_render_without_subclass
1722
render_inline(
1823
Primer::Forms::ToggleSwitchForm.new(

0 commit comments

Comments
 (0)