Skip to content

Commit 0c0b070

Browse files
committed
Match consent vendors by host+path instead of host only
Allow URL matchers to include path segments so that vendors sharing a domain (e.g. google.com/maps/embed vs google.com) can be distinguished. The old consent_vendor_host_matchers setter is preserved for backwards compatibility, automatically rewriting trailing `$` anchors to `/`. REDMINE-21240
1 parent 861957b commit 0c0b070

8 files changed

Lines changed: 94 additions & 27 deletions

File tree

entry_types/scrolled/app/helpers/pageflow_scrolled/editor/entry_json_seed_helper.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def scrolled_entry_editor_json_seed(json, scrolled_entry)
1111
entry_config = Pageflow.config_for(scrolled_entry)
1212

1313
scrolled_entry_editor_legacy_typography_variants_seed(json, entry_config)
14-
scrolled_entry_editor_consent_vendor_host_matchers_seed(json, entry_config)
14+
scrolled_entry_editor_consent_vendor_url_matchers_seed(json, entry_config)
1515

1616
scrolled_entry_json_seed(json,
1717
scrolled_entry,
@@ -32,10 +32,10 @@ def scrolled_entry_editor_legacy_typography_variants_seed(json, entry_config)
3232
)
3333
end
3434

35-
def scrolled_entry_editor_consent_vendor_host_matchers_seed(json, entry_config)
36-
json.consent_vendor_host_matchers(
35+
def scrolled_entry_editor_consent_vendor_url_matchers_seed(json, entry_config)
36+
json.consent_vendor_url_matchers(
3737
entry_config
38-
.consent_vendor_host_matchers
38+
.consent_vendor_url_matchers
3939
.transform_keys { |regexp| regexp.inspect[1..-2] }
4040
)
4141
end

entry_types/scrolled/lib/pageflow_scrolled/configuration.rb

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,32 @@ class Configuration
8080
# @since 16.1
8181
attr_reader :content_element_consent_vendors
8282

83-
# Mapping from URL hosts to consent vendor names. Used for iframe
84-
# embed opt-in.
83+
# Mapping from URL host+path patterns to consent vendor names.
84+
# Used for iframe embed opt-in.
8585
#
8686
# @exmaple
8787
#
88-
# entry_type_config.consent_vendor_host_matchers = {
89-
# /\.some-vendor\.com$/ => 'someVendor'
88+
# entry_type_config.consent_vendor_url_matchers = {
89+
# /\.some-vendor\.com\// => 'someVendor',
90+
# /google\.com\/maps\/embed/ => 'googleMaps'
9091
# }
9192
#
9293
# @return [Hash<RegExp, String>]
94+
# @since edge
95+
attr_accessor :consent_vendor_url_matchers
96+
97+
# @deprecated Use {#consent_vendor_url_matchers=} instead.
98+
# Rewrites trailing `$` in patterns to `/` and merges
99+
# into {#consent_vendor_url_matchers}.
93100
# @since 16.1
94-
attr_accessor :consent_vendor_host_matchers
101+
def consent_vendor_host_matchers=(matchers)
102+
rewritten = matchers.transform_keys do |key|
103+
source = key.source.sub(/\$$/, '/')
104+
Regexp.new(source, key.options)
105+
end
106+
107+
@consent_vendor_url_matchers.merge!(rewritten)
108+
end
95109

96110
# Migrate typography variants to palette colors. Before palette
97111
# colors for text blocks and headings were introduced, it was
@@ -155,7 +169,7 @@ def initialize(*)
155169
@additional_frontend_seed_data = AdditionalSeedData.new
156170
@additional_theme_assets = AdditionalThemeAssets.new
157171
@content_element_consent_vendors = ContentElementConsentVendors.new
158-
@consent_vendor_host_matchers = {}
172+
@consent_vendor_url_matchers = {}
159173

160174
@legacy_typography_variants = {}
161175
end

entry_types/scrolled/lib/pageflow_scrolled/plugin.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,10 @@ def configure(config)
227227
return unless configuration['requireConsent']
228228

229229
uri = URI.parse(configuration['source'])
230-
host_matchers = Pageflow.config_for(entry).consent_vendor_host_matchers
230+
url_matchers = Pageflow.config_for(entry).consent_vendor_url_matchers
231231

232-
host_matchers.detect { |matcher, _|
233-
uri.host =~ matcher
232+
url_matchers.detect { |matcher, _|
233+
(uri.host + uri.path) =~ matcher
234234
}&.last
235235
rescue URI::InvalidURIError
236236
nil

entry_types/scrolled/package/spec/editor/models/ConsentVendors-spec.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import {ConsentVendors} from 'editor/models/ConsentVendors';
22

33
describe('ConsentVendors', () => {
44
describe('fromUrl', () => {
5-
it('detects vendor from seed data host matcher', () => {
5+
it('detects vendor from seed data url matcher', () => {
66
const consentVendors = new ConsentVendors({
7-
hostMatchers: {
8-
'\\.some-vendor.com$': 'someVendor'
7+
urlMatchers: {
8+
'\\.some-vendor\\.com/': 'someVendor'
99
}
1010
});
1111

@@ -14,5 +14,18 @@ describe('ConsentVendors', () => {
1414
expect(consentVendors.fromUrl('https://other.com/abc'))
1515
.toBeUndefined();
1616
});
17+
18+
it('detects vendor from path-based url matcher', () => {
19+
const consentVendors = new ConsentVendors({
20+
urlMatchers: {
21+
'google\\.com/maps/embed': 'googleMaps'
22+
}
23+
});
24+
25+
expect(consentVendors.fromUrl('https://www.google.com/maps/embed?pb=1234'))
26+
.toEqual('googleMaps');
27+
expect(consentVendors.fromUrl('https://www.google.com/search?q=test'))
28+
.toBeUndefined();
29+
});
1730
})
1831
})

entry_types/scrolled/package/src/editor/models/ConsentVendors.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
export function ConsentVendors({hostMatchers}) {
1+
export function ConsentVendors({urlMatchers}) {
22
return {
33
fromUrl(url) {
44
url = new URL(url);
55

6-
return Object.entries(hostMatchers).find(([matcher]) =>
7-
new RegExp(matcher).test(url.host)
6+
return Object.entries(urlMatchers).find(([matcher]) =>
7+
new RegExp(matcher).test(url.host + url.pathname)
88
)?.[1];
99
}
1010
}

entry_types/scrolled/package/src/editor/models/ScrolledEntry/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const defaultAspectRatios = [{
4747

4848
export const ScrolledEntry = Entry.extend({
4949
setupFromEntryTypeSeed(seed) {
50-
this.consentVendors = new ConsentVendors({hostMatchers: seed.consentVendorHostMatchers});
50+
this.consentVendors = new ConsentVendors({urlMatchers: seed.consentVendorUrlMatchers});
5151

5252
this.contentElements = new ContentElementsCollection(seed.collections.contentElements);
5353
this.sections = new SectionsCollection(seed.collections.sections,

entry_types/scrolled/spec/helpers/pageflow_scrolled/editor/entry_json_seed_helper_spec.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,11 @@ def render(helper, entry)
115115
})
116116
end
117117

118-
it 'renders consent vendor host matchers' do
118+
it 'renders consent vendor url matchers' do
119119
pageflow_configure do |config|
120120
config.for_entry_type(PageflowScrolled.entry_type) do |entry_type_config|
121-
entry_type_config.consent_vendor_host_matchers = {
122-
/\.some-vendor\.com$/ => 'someVendor'
121+
entry_type_config.consent_vendor_url_matchers = {
122+
/\.some-vendor\.com\// => 'someVendor'
123123
}
124124
end
125125
end
@@ -128,8 +128,8 @@ def render(helper, entry)
128128

129129
result = render(helper, entry)
130130

131-
expect(result).to include_json(consentVendorHostMatchers: {
132-
'\\.some-vendor\\.com$' => 'someVendor'
131+
expect(result).to include_json(consentVendorUrlMatchers: {
132+
'\\.some-vendor\\.com\\/' => 'someVendor'
133133
})
134134
end
135135

entry_types/scrolled/spec/pageflow_scrolled/plugin_spec.rb

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ def request(uri = 'https://example.com/some-entry')
4141
it 'returns nil if consent not required' do
4242
pageflow_configure do |config|
4343
config.for_entry_type(PageflowScrolled.entry_type) do |entry_type_config|
44-
entry_type_config.consent_vendor_host_matchers = {
45-
/\.typeform\.com$/ => 'typeform'
44+
entry_type_config.consent_vendor_url_matchers = {
45+
/\.typeform\.com\// => 'typeform'
4646
}
4747
end
4848
end
@@ -59,6 +59,46 @@ def request(uri = 'https://example.com/some-entry')
5959
end
6060

6161
it 'detects vendor from source when consent is required' do
62+
pageflow_configure do |config|
63+
config.for_entry_type(PageflowScrolled.entry_type) do |entry_type_config|
64+
entry_type_config.consent_vendor_url_matchers = {
65+
/\.typeform\.com\// => 'typeform'
66+
}
67+
end
68+
end
69+
70+
result = Plugin::IFRAME_EMBED_CONSENT_VENDOR.call(
71+
entry: create(:published_entry, type_name: 'scrolled'),
72+
configuration: {
73+
'requireConsent' => true,
74+
'source' => 'https://foo.typeform.com/to/1234'
75+
}
76+
)
77+
78+
expect(result).to eq('typeform')
79+
end
80+
81+
it 'detects vendor from path-based url matcher' do
82+
pageflow_configure do |config|
83+
config.for_entry_type(PageflowScrolled.entry_type) do |entry_type_config|
84+
entry_type_config.consent_vendor_url_matchers = {
85+
/google\.com\/maps\/embed/ => 'googleMaps'
86+
}
87+
end
88+
end
89+
90+
result = Plugin::IFRAME_EMBED_CONSENT_VENDOR.call(
91+
entry: create(:published_entry, type_name: 'scrolled'),
92+
configuration: {
93+
'requireConsent' => true,
94+
'source' => 'https://www.google.com/maps/embed?pb=1234'
95+
}
96+
)
97+
98+
expect(result).to eq('googleMaps')
99+
end
100+
101+
it 'supports deprecated consent_vendor_host_matchers setter' do
62102
pageflow_configure do |config|
63103
config.for_entry_type(PageflowScrolled.entry_type) do |entry_type_config|
64104
entry_type_config.consent_vendor_host_matchers = {

0 commit comments

Comments
 (0)