Skip to content

Commit

Permalink
Stripe global settings (#521)
Browse files Browse the repository at this point in the history
* Add fields to input stripe key global settings

* Update validator

* Hide sensitive data
  • Loading branch information
HungNgien authored Jan 25, 2025
1 parent accad6e commit 81866cd
Showing 1 changed file with 91 additions and 4 deletions.
95 changes: 91 additions & 4 deletions src/pretix/control/forms/global_settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from collections import OrderedDict
from typing import List, Union

from django import forms
from django.conf import settings
Expand Down Expand Up @@ -142,10 +143,53 @@ def __init__(self, *args, **kwargs):
self.fields['banner_message'].widget.attrs['rows'] = '2'
self.fields['banner_message_detail'].widget.attrs['rows'] = '3'
self.fields = OrderedDict(list(self.fields.items()) + [
('stripe_webhook_secret_key', SecretKeySettingsField(
label=_('Stripe Webhook: Signing secret'),
required=False,
)),
(
'payment_stripe_connect_secret_key',
SecretKeySettingsField(
label=_('Stripe Connect: Secret key'),
required=False,
validators=(
StripeKeyValidator(['sk_live_', 'rk_live_']),
),
)
),
(
'payment_stripe_connect_publishable_key',
forms.CharField(
label=_('Stripe Connect: Publishable key'),
required=False,
validators=(
StripeKeyValidator('pk_live_'),
),
)
),
(
'payment_stripe_connect_test_secret_key',
SecretKeySettingsField(
label=_('Stripe Connect: Secret key (test)'),
required=False,
validators=(
StripeKeyValidator(['sk_test_', 'rk_test_']),
),
)
),
(
'payment_stripe_connect_test_publishable_key',
forms.CharField(
label=_('Stripe Connect: Publishable key (test)'),
required=False,
validators=(
StripeKeyValidator('pk_test_'),
),
)
),
(
'stripe_webhook_secret_key',
SecretKeySettingsField(
label=_('Stripe Webhook: Secret key'),
required=False,
)
),
(
"ticket_fee_percentage",
forms.DecimalField(
Expand Down Expand Up @@ -195,3 +239,46 @@ class SSOConfigForm(SettingsForm):
def __init__(self, *args, **kwargs):
self.obj = GlobalSettingsObject()
super().__init__(*args, obj=self.obj, **kwargs)


class StripeKeyValidator:
"""
Validates that a given Stripe key starts with the expected prefix(es).
This validator ensures that Stripe API keys conform to the expected format
by checking their prefixes. It supports both single prefix validation and
multiple prefix validation.
"""
def __init__(self, prefix: Union[str, List[str]]) -> None:
if not prefix:
raise ValueError("Prefix cannot be empty")

if isinstance(prefix, list):
if not all(isinstance(p, str) and p for p in prefix):
raise ValueError("All prefixes must be non-empty strings")
self._prefixes = prefix
elif isinstance(prefix, str):
if not prefix.strip():
raise ValueError("Prefix cannot be whitespace")
self._prefixes = [prefix]

def __call__(self, value: str) -> None:
if not value:
raise forms.ValidationError(
_("The Stripe key cannot be empty."),
code='invalid-stripe-key'
)

if not any(value.startswith(p) for p in self._prefixes):
if len(self._prefixes) == 1:
message = _('The provided key does not look valid. It should start with "%(prefix)s".')
params = {'value': value, 'prefix': self._prefixes[0]}
else:
message = _('The provided key does not look valid. It should start with one of: %(prefixes)s')
params = {'value': value, 'prefixes': ', '.join(f'"{p}"' for p in self._prefixes)}

raise forms.ValidationError(
message,
code='invalid-stripe-key',
params=params
)

0 comments on commit 81866cd

Please sign in to comment.