diff --git a/src/pretix/plugins/stripe/payment.py b/src/pretix/plugins/stripe/payment.py index a05966964b..9f270fd99e 100644 --- a/src/pretix/plugins/stripe/payment.py +++ b/src/pretix/plugins/stripe/payment.py @@ -33,6 +33,24 @@ class RefundForm(forms.Form): ) +class StripeKeyValidator(): + def __init__(self, prefix): + assert isinstance(prefix, str) + assert len(prefix) > 0 + self._prefix = prefix + + def __call__(self, value): + if not value.startswith(self._prefix): + raise forms.ValidationError( + _('The provided key "%(value)s" does not look valid. It should start with "%(prefix)s".'), + code='invalid-stripe-secret-key', + params={ + 'value': value, + 'prefix': self._prefix, + }, + ) + + class StripeSettingsHolder(BasePaymentProvider): identifier = 'stripe_settings' verbose_name = _('Stripe') @@ -60,11 +78,17 @@ class StripeSettingsHolder(BasePaymentProvider): help_text=_('{text}').format( text=_('Click here for a tutorial on how to obtain the required keys'), docs_url='https://docs.pretix.eu/en/latest/user/payments/stripe.html' - ) + ), + validators=( + StripeKeyValidator('sk_'), + ), )), ('publishable_key', forms.CharField( label=_('Publishable key'), + validators=( + StripeKeyValidator('pk_'), + ), )), ('ui', forms.ChoiceField( diff --git a/src/tests/plugins/stripe/test_settings.py b/src/tests/plugins/stripe/test_settings.py index 91eb7301bd..dc84048fba 100644 --- a/src/tests/plugins/stripe/test_settings.py +++ b/src/tests/plugins/stripe/test_settings.py @@ -4,6 +4,28 @@ import pytest from pretix.base.models import Event, Organizer, Team, User +valid_secret_key_values = [ + 'sk_', + 'sk_foo', +] + +valid_publishable_key_values = [ + 'pk_', + 'pk_foo', +] + +invalid_secret_key_values = [ + 'skihaspartialprefix', + 'ihasnoprefix', + 'ihaspostfixsk_', +] + +invalid_publishable_key_values = [ + 'pkihaspartialprefix', + 'ihasnoprefix', + 'ihaspostfixpk_', +] + @pytest.fixture def env(client): @@ -21,12 +43,48 @@ def env(client): t.members.add(user) t.limit_events.add(event) client.force_login(user) - return client, event + url = '/control/event/%s/%s/settings/payment' % (event.organizer.slug, event.slug) + return client, event, url @pytest.mark.django_db def test_settings(env): - client, event = env - response = client.get('/control/event/%s/%s/settings/payment' % (event.organizer.slug, event.slug), follow=True) + client, event, url = env + response = client.get(url, follow=True) assert response.status_code == 200 assert 'stripe__enabled' in response.rendered_content + + +def _stripe_key_test(env, field, value, is_valid): + client, event, url = env + data = {'payment_stripe_' + field: value} + response = client.post(url, data) + + if not is_valid: + assert 'does not look valid' in response.rendered_content + else: + assert 'does not look valid' not in response.rendered_content + + +@pytest.mark.django_db +@pytest.mark.parametrize("value", invalid_secret_key_values) +def test_settings_secret_key_invalid(env, value): + _stripe_key_test(env, 'secret_key', value, False) + + +@pytest.mark.django_db +@pytest.mark.parametrize("value", invalid_publishable_key_values) +def test_settings_publishable_key_invalid(env, value): + _stripe_key_test(env, 'publishable_key', value, False) + + +@pytest.mark.django_db +@pytest.mark.parametrize("value", valid_secret_key_values) +def test_settings_secret_key_valid(env, value): + _stripe_key_test(env, 'secret_key', value, True) + + +@pytest.mark.django_db +@pytest.mark.parametrize("value", valid_publishable_key_values) +def test_settings_publishable_key_valid(env, value): + _stripe_key_test(env, 'publishable_key', value, True)