Skip to content

Commit 38a59ce

Browse files
Raise on override defined config (#436)
* Raise exception when trying to override an existing config * Raise exception when trying to set a named append more than once * Update documentation * Raise an exception when a named append or override with the same name exists Co-authored-by: Neil Matatall <[email protected]>
1 parent d3fe69c commit 38a59ce

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

docs/named_overrides_and_appends.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## Named Appends
22

3-
Named Appends are blocks of code that can be reused and composed during requests. e.g. If a certain partial is rendered conditionally, and the csp needs to be adjusted for that partial, you can create a named append for that situation. The value returned by the block will be passed into `append_content_security_policy_directives`. The current request object is passed as an argument to the block for even more flexibility.
3+
Named Appends are blocks of code that can be reused and composed during requests. e.g. If a certain partial is rendered conditionally, and the csp needs to be adjusted for that partial, you can create a named append for that situation. The value returned by the block will be passed into `append_content_security_policy_directives`. The current request object is passed as an argument to the block for even more flexibility. Reusing a configuration name is not allowed and will throw an exception.
44

55
```ruby
66
def show
@@ -91,6 +91,8 @@ class MyController < ApplicationController
9191
end
9292
```
9393

94+
Reusing a configuration name is not allowed and will throw an exception.
95+
9496
By default, a no-op configuration is provided. No headers will be set when this default override is used.
9597

9698
```ruby

lib/secure_headers/configuration.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ def default(&block)
4343
def override(name, &block)
4444
@overrides ||= {}
4545
raise "Provide a configuration block" unless block_given?
46+
if named_append_or_override_exists?(name)
47+
raise AlreadyConfiguredError, "Configuration already exists"
48+
end
4649
@overrides[name] = block
4750
end
4851

@@ -59,6 +62,9 @@ def named_appends(name)
5962
def named_append(name, &block)
6063
@appends ||= {}
6164
raise "Provide a configuration block" unless block_given?
65+
if named_append_or_override_exists?(name)
66+
raise AlreadyConfiguredError, "Configuration already exists"
67+
end
6268
@appends[name] = block
6369
end
6470

@@ -68,6 +74,11 @@ def dup
6874

6975
private
7076

77+
def named_append_or_override_exists?(name)
78+
(defined?(@appends) && @appends.key?(name)) ||
79+
(defined?(@overrides) && @overrides.key?(name))
80+
end
81+
7182
# Public: perform a basic deep dup. The shallow copy provided by dup/clone
7283
# can lead to modifying parent objects.
7384
def deep_copy(config)

spec/lib/secure_headers/configuration_spec.rb

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,60 @@ module SecureHeaders
3434
expect(Configuration.overrides(:test_override)).to_not be_nil
3535
end
3636

37+
describe "#override" do
38+
it "raises on configuring an existing override" do
39+
set_override = Proc.new {
40+
Configuration.override(:test_override) do |config|
41+
config.x_frame_options = "DENY"
42+
end
43+
}
44+
45+
set_override.call
46+
47+
expect { set_override.call }
48+
.to raise_error(Configuration::AlreadyConfiguredError, "Configuration already exists")
49+
end
50+
51+
it "raises when a named append with the given name exists" do
52+
Configuration.named_append(:test_override) do |config|
53+
config.x_frame_options = "DENY"
54+
end
55+
56+
expect do
57+
Configuration.override(:test_override) do |config|
58+
config.x_frame_options = "SAMEORIGIN"
59+
end
60+
end.to raise_error(Configuration::AlreadyConfiguredError, "Configuration already exists")
61+
end
62+
end
63+
64+
describe "#named_append" do
65+
it "raises on configuring an existing append" do
66+
set_override = Proc.new {
67+
Configuration.named_append(:test_override) do |config|
68+
config.x_frame_options = "DENY"
69+
end
70+
}
71+
72+
set_override.call
73+
74+
expect { set_override.call }
75+
.to raise_error(Configuration::AlreadyConfiguredError, "Configuration already exists")
76+
end
77+
78+
it "raises when an override with the given name exists" do
79+
Configuration.override(:test_override) do |config|
80+
config.x_frame_options = "DENY"
81+
end
82+
83+
expect do
84+
Configuration.named_append(:test_override) do |config|
85+
config.x_frame_options = "SAMEORIGIN"
86+
end
87+
end.to raise_error(Configuration::AlreadyConfiguredError, "Configuration already exists")
88+
end
89+
end
90+
3791
it "deprecates the secure_cookies configuration" do
3892
expect {
3993
Configuration.default do |config|

spec/spec_helper.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,20 @@ class << self
4545
def clear_default_config
4646
remove_instance_variable(:@default_config) if defined?(@default_config)
4747
end
48+
49+
def clear_overrides
50+
remove_instance_variable(:@overrides) if defined?(@overrides)
51+
end
52+
53+
def clear_appends
54+
remove_instance_variable(:@appends) if defined?(@appends)
55+
end
4856
end
4957
end
5058
end
5159

5260
def reset_config
5361
SecureHeaders::Configuration.clear_default_config
62+
SecureHeaders::Configuration.clear_overrides
63+
SecureHeaders::Configuration.clear_appends
5464
end

0 commit comments

Comments
 (0)