Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add recaptcha to registration form #13232

Merged
merged 4 commits into from
Mar 17, 2023
Merged
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
4 changes: 4 additions & 0 deletions dev/environment
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,7 @@ TWOFACTORMANDATE_AVAILABLE=true
TWOFACTORMANDATE_ENABLED=true
OIDC_ENABLED=true
OIDC_AUDIENCE=pypi

# Default to the reCAPTCHA testing keys from https://developers.google.com/recaptcha/docs/faq
RECAPTCHA_SITE_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
RECAPTCHA_SECRET_KEY=6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe
82 changes: 81 additions & 1 deletion tests/unit/accounts/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import pytest
import wtforms

from warehouse import recaptcha
from warehouse.accounts import forms
from warehouse.accounts.interfaces import (
BurnedRecoveryCode,
Expand Down Expand Up @@ -344,19 +345,26 @@ def test_validate_password_notok_ip_banned(self, db_session):
class TestRegistrationForm:
def test_create(self):
user_service = pretend.stub()
recaptcha_service = pretend.stub(enabled=True)
breach_service = pretend.stub()

form = forms.RegistrationForm(
data={}, user_service=user_service, breach_service=breach_service
data={},
user_service=user_service,
recaptcha_service=recaptcha_service,
breach_service=breach_service,
)

assert form.user_service is user_service
assert form.recaptcha_service is recaptcha_service

def test_password_confirm_required_error(self):
form = forms.RegistrationForm(
data={"password_confirm": ""},
user_service=pretend.stub(
find_userid_by_email=pretend.call_recorder(lambda _: pretend.stub())
),
recaptcha_service=pretend.stub(enabled=True),
breach_service=pretend.stub(check_password=lambda pw: False),
)

Expand All @@ -370,6 +378,7 @@ def test_passwords_mismatch_error(self, pyramid_config):
form = forms.RegistrationForm(
data={"new_password": "password", "password_confirm": "mismatch"},
user_service=user_service,
recaptcha_service=pretend.stub(enabled=True),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)

Expand All @@ -389,6 +398,7 @@ def test_passwords_match_success(self):
"password_confirm": "MyStr0ng!shPassword",
},
user_service=user_service,
recaptcha_service=pretend.stub(enabled=True),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)

Expand All @@ -402,6 +412,7 @@ def test_email_required_error(self):
user_service=pretend.stub(
find_userid_by_email=pretend.call_recorder(lambda _: pretend.stub())
),
recaptcha_service=pretend.stub(enabled=True),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)

Expand All @@ -415,6 +426,7 @@ def test_invalid_email_error(self, pyramid_config, email):
user_service=pretend.stub(
find_userid_by_email=pretend.call_recorder(lambda _: None)
),
recaptcha_service=pretend.stub(enabled=True),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)

Expand All @@ -429,6 +441,7 @@ def test_exotic_email_success(self):
user_service=pretend.stub(
find_userid_by_email=pretend.call_recorder(lambda _: None)
),
recaptcha_service=pretend.stub(enabled=True),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)

Expand All @@ -441,6 +454,7 @@ def test_email_exists_error(self, pyramid_config):
user_service=pretend.stub(
find_userid_by_email=pretend.call_recorder(lambda _: pretend.stub())
),
recaptcha_service=pretend.stub(enabled=True),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)

Expand All @@ -457,6 +471,7 @@ def test_prohibited_email_error(self, pyramid_config):
user_service=pretend.stub(
find_userid_by_email=pretend.call_recorder(lambda _: None)
),
recaptcha_service=pretend.stub(enabled=True),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)

Expand All @@ -467,13 +482,58 @@ def test_prohibited_email_error(self, pyramid_config):
"different email."
)

def test_recaptcha_disabled(self):
form = forms.RegistrationForm(
data={"g_recpatcha_response": ""},
user_service=pretend.stub(),
recaptcha_service=pretend.stub(
enabled=False,
verify_response=pretend.call_recorder(lambda _: None),
),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)
assert not form.validate()
# there shouldn't be any errors for the recaptcha field if it's
# disabled
assert not form.g_recaptcha_response.errors

def test_recaptcha_required_error(self):
form = forms.RegistrationForm(
data={"g_recaptcha_response": ""},
user_service=pretend.stub(),
recaptcha_service=pretend.stub(
enabled=True,
verify_response=pretend.call_recorder(lambda _: None),
),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)
assert not form.validate()
assert form.g_recaptcha_response.errors.pop() == "Recaptcha error."

def test_recaptcha_error(self):
form = forms.RegistrationForm(
data={"g_recaptcha_response": "asd"},
user_service=pretend.stub(),
recaptcha_service=pretend.stub(
verify_response=pretend.raiser(recaptcha.RecaptchaError),
enabled=True,
),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)
assert not form.validate()
assert form.g_recaptcha_response.errors.pop() == "Recaptcha error."

def test_username_exists(self, pyramid_config):
form = forms.RegistrationForm(
data={"username": "foo"},
user_service=pretend.stub(
find_userid=pretend.call_recorder(lambda name: 1),
username_is_prohibited=lambda a: False,
),
recaptcha_service=pretend.stub(
enabled=False,
verify_response=pretend.call_recorder(lambda _: None),
),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)
assert not form.validate()
Expand All @@ -489,6 +549,10 @@ def test_username_prohibted(self, pyramid_config):
user_service=pretend.stub(
username_is_prohibited=lambda a: True,
),
recaptcha_service=pretend.stub(
enabled=False,
verify_response=pretend.call_recorder(lambda _: None),
),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)
assert not form.validate()
Expand All @@ -506,6 +570,10 @@ def test_username_is_valid(self, username, pyramid_config):
find_userid=pretend.call_recorder(lambda _: None),
username_is_prohibited=lambda a: False,
),
recaptcha_service=pretend.stub(
enabled=False,
verify_response=pretend.call_recorder(lambda _: None),
),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)
assert not form.validate()
Expand All @@ -527,6 +595,10 @@ def test_password_strength(self):
form = forms.RegistrationForm(
data={"new_password": pwd, "password_confirm": pwd},
user_service=pretend.stub(),
recaptcha_service=pretend.stub(
enabled=False,
verify_response=pretend.call_recorder(lambda _: None),
),
breach_service=pretend.stub(check_password=lambda pw, tags=None: False),
)
form.validate()
Expand All @@ -538,6 +610,10 @@ def test_password_breached(self):
user_service=pretend.stub(
find_userid=pretend.call_recorder(lambda _: None)
),
recaptcha_service=pretend.stub(
enabled=False,
verify_response=pretend.call_recorder(lambda _: None),
),
breach_service=pretend.stub(
check_password=lambda pw, tags=None: True,
failure_message=(
Expand All @@ -558,6 +634,10 @@ def test_name_too_long(self, pyramid_config):
user_service=pretend.stub(
find_userid=pretend.call_recorder(lambda _: None)
),
recaptcha_service=pretend.stub(
enabled=False,
verify_response=pretend.call_recorder(lambda _: None),
),
breach_service=pretend.stub(check_password=lambda pw, tags=None: True),
)
assert not form.validate()
Expand Down
16 changes: 12 additions & 4 deletions tests/unit/accounts/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1347,8 +1347,10 @@ def test_register_redirect(self, db_request, monkeypatch):
lambda *args: None
)
db_request.session.record_password_timestamp = lambda ts: None
db_request.find_service = pretend.call_recorder(
lambda svc, name=None, context=None: {

def _find_service(service=None, name=None, context=None):
key = service or name
return {
IUserService: pretend.stub(
username_is_prohibited=lambda a: False,
find_userid=pretend.call_recorder(lambda _: None),
Expand All @@ -1364,8 +1366,13 @@ def test_register_redirect(self, db_request, monkeypatch):
check_password=lambda pw, tags=None: False,
),
IRateLimiter: pretend.stub(hit=lambda user_id: None),
}.get(svc)
)
"csp": pretend.stub(merge=lambda *a, **kw: {}),
"recaptcha": pretend.stub(
csp_policy={}, enabled=True, verify_response=lambda a: True
),
}[key]

db_request.find_service = pretend.call_recorder(_find_service)
db_request.route_path = pretend.call_recorder(lambda name: "/")
db_request.POST.update(
{
Expand All @@ -1374,6 +1381,7 @@ def test_register_redirect(self, db_request, monkeypatch):
"password_confirm": "MyStr0ng!shP455w0rd",
"email": "foo@bar.com",
"full_name": "full_name",
"g_recaptcha_response": "captchavalue",
}
)

Expand Down
1 change: 1 addition & 0 deletions tests/unit/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ def __init__(self):
pretend.call(".sentry"),
pretend.call(".csp"),
pretend.call(".referrer_policy"),
pretend.call(".recaptcha"),
pretend.call(".http"),
]
+ [pretend.call(x) for x in [configurator_settings.get("warehouse.theme")] if x]
Expand Down
Loading