Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions bedrock/mozorg/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ def render(self, name, value, attrs=None, renderer=None):
# semi-randomized in case we have more than one per page.
# this is maybe/probably overthought
honeypot_id = "office-fax-" + str(randrange(1001)) + "-" + str(datetime.now().strftime("%Y%m%d%H%M%S%f"))
tabindex_attr = 'tabindex="-1"'
return mark_safe(
'<div class="super-priority-field">'
'<label for="%s">%s</label>'
'<input type="text" name="office_fax" id="%s">'
"</div>" % (honeypot_id, honeypot_txt, honeypot_id)
'<input type="text" name="office_fax" id="%s" %s>'
"</div>" % (honeypot_id, honeypot_txt, honeypot_id, tabindex_attr)
)


Expand Down
9 changes: 8 additions & 1 deletion bedrock/newsletter/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from product_details import product_details

from bedrock.mozorg.forms import EmailInput, PrivacyWidget, strip_parenthetical
from bedrock.mozorg.forms import EmailInput, HoneyPotWidget, PrivacyWidget, strip_parenthetical
from bedrock.newsletter import utils
from lib.l10n_utils.fluent import ftl, ftl_lazy

Expand Down Expand Up @@ -186,6 +186,8 @@ class NewsletterFooterForm(forms.Form):
privacy = forms.BooleanField(widget=PrivacyWidget(attrs={"data-testid": "newsletter-privacy-checkbox"}))
source_url = forms.CharField(required=False)
newsletters = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple())
# office_fax is a honeypot field
office_fax = forms.CharField(widget=HoneyPotWidget(attrs={"tabindex": "-1"}), required=False, empty_value="")

# has to take a newsletters argument so it can figure
# out which languages to list in the form.
Expand Down Expand Up @@ -251,6 +253,11 @@ def clean_source_url(self):

return su

def clean_office_fax(self):
honeypot = self.cleaned_data.pop("office_fax", None)
if honeypot:
raise forms.ValidationError("Your submission could not be processed")


class EmailForm(forms.Form):
"""
Expand Down
3 changes: 3 additions & 0 deletions bedrock/newsletter/templates/newsletter/includes/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
{% endif %}
<input type="hidden" name="source_url" value="{{ request.build_absolute_uri() }}">

{# Honeypot field #}
{{ form.office_fax|safe }}

{% if include_title and is_multi_newsletter_form %}
<header class="mzp-c-newsletter-header">
<h3 class="mzp-c-newsletter-title">{{ title|d(ftl('multi-newsletter-form-title'), true) }}</h3>
Expand Down
25 changes: 25 additions & 0 deletions bedrock/newsletter/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,28 @@ def test_multiple_newsletters(self):
form = NewsletterFooterForm(spacey_newsletters, "en-US", data=data.copy())
self.assertTrue(form.is_valid())
self.assertEqual(form.cleaned_data["newsletters"], newsletters)

def test_honeypot_empty_valid(self):
"""Honeypot field should be valid when empty"""
data = {
"email": "[email protected]",
"lang": "fr",
"privacy": True,
"newsletters": [self.newsletter_name],
"office_fax": "", # honeypot field
}
form = NewsletterFooterForm(self.newsletter_name, locale="en-US", data=data.copy())
self.assertTrue(form.is_valid(), form.errors)

def test_honeypot_filled_invalid(self):
"""Honeypot field should be invalid when filled"""
data = {
"email": "[email protected]",
"lang": "fr",
"privacy": True,
"newsletters": [self.newsletter_name],
"office_fax": "some value", # honeypot field
}
form = NewsletterFooterForm(self.newsletter_name, locale="en-US", data=data.copy())
self.assertFalse(form.is_valid())
self.assertIn("office_fax", form.errors)
3 changes: 3 additions & 0 deletions bedrock/newsletter/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ def newsletter_subscribe(request):
errors.append(ftl("newsletter-form-please-enter-a-valid"))
if "privacy" in form.errors:
errors.append(ftl("newsletter-form-you-must-agree-to"))
if "office_fax" in form.errors:
# Honeypot field was filled
errors.append(ftl("newsletter-form-we-are-sorry-but-there"))
for fieldname in ("newsletters", "lang", "country"):
if fieldname in form.errors:
errors.extend(form.errors[fieldname])
Expand Down
10 changes: 9 additions & 1 deletion media/css/protocol/components/newsletter-form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,12 @@ $image-path: '/media/protocol/img';
}
}

/* stylelint-enable declaration-no-important */
// Honeypot field styling - hide from users but keep accessible to bots
.super-priority-field {
@include visually-hidden;

// Hide from screen readers
label {
display: none !important;
}
}