Skip to content

Commit 81866cd

Browse files
authored
Stripe global settings (#521)
* Add fields to input stripe key global settings * Update validator * Hide sensitive data
1 parent accad6e commit 81866cd

File tree

1 file changed

+91
-4
lines changed

1 file changed

+91
-4
lines changed

src/pretix/control/forms/global_settings.py

+91-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from collections import OrderedDict
2+
from typing import List, Union
23

34
from django import forms
45
from django.conf import settings
@@ -142,10 +143,53 @@ def __init__(self, *args, **kwargs):
142143
self.fields['banner_message'].widget.attrs['rows'] = '2'
143144
self.fields['banner_message_detail'].widget.attrs['rows'] = '3'
144145
self.fields = OrderedDict(list(self.fields.items()) + [
145-
('stripe_webhook_secret_key', SecretKeySettingsField(
146-
label=_('Stripe Webhook: Signing secret'),
147-
required=False,
148-
)),
146+
(
147+
'payment_stripe_connect_secret_key',
148+
SecretKeySettingsField(
149+
label=_('Stripe Connect: Secret key'),
150+
required=False,
151+
validators=(
152+
StripeKeyValidator(['sk_live_', 'rk_live_']),
153+
),
154+
)
155+
),
156+
(
157+
'payment_stripe_connect_publishable_key',
158+
forms.CharField(
159+
label=_('Stripe Connect: Publishable key'),
160+
required=False,
161+
validators=(
162+
StripeKeyValidator('pk_live_'),
163+
),
164+
)
165+
),
166+
(
167+
'payment_stripe_connect_test_secret_key',
168+
SecretKeySettingsField(
169+
label=_('Stripe Connect: Secret key (test)'),
170+
required=False,
171+
validators=(
172+
StripeKeyValidator(['sk_test_', 'rk_test_']),
173+
),
174+
)
175+
),
176+
(
177+
'payment_stripe_connect_test_publishable_key',
178+
forms.CharField(
179+
label=_('Stripe Connect: Publishable key (test)'),
180+
required=False,
181+
validators=(
182+
StripeKeyValidator('pk_test_'),
183+
),
184+
)
185+
),
186+
(
187+
'stripe_webhook_secret_key',
188+
SecretKeySettingsField(
189+
label=_('Stripe Webhook: Secret key'),
190+
required=False,
191+
)
192+
),
149193
(
150194
"ticket_fee_percentage",
151195
forms.DecimalField(
@@ -195,3 +239,46 @@ class SSOConfigForm(SettingsForm):
195239
def __init__(self, *args, **kwargs):
196240
self.obj = GlobalSettingsObject()
197241
super().__init__(*args, obj=self.obj, **kwargs)
242+
243+
244+
class StripeKeyValidator:
245+
"""
246+
Validates that a given Stripe key starts with the expected prefix(es).
247+
248+
This validator ensures that Stripe API keys conform to the expected format
249+
by checking their prefixes. It supports both single prefix validation and
250+
multiple prefix validation.
251+
"""
252+
def __init__(self, prefix: Union[str, List[str]]) -> None:
253+
if not prefix:
254+
raise ValueError("Prefix cannot be empty")
255+
256+
if isinstance(prefix, list):
257+
if not all(isinstance(p, str) and p for p in prefix):
258+
raise ValueError("All prefixes must be non-empty strings")
259+
self._prefixes = prefix
260+
elif isinstance(prefix, str):
261+
if not prefix.strip():
262+
raise ValueError("Prefix cannot be whitespace")
263+
self._prefixes = [prefix]
264+
265+
def __call__(self, value: str) -> None:
266+
if not value:
267+
raise forms.ValidationError(
268+
_("The Stripe key cannot be empty."),
269+
code='invalid-stripe-key'
270+
)
271+
272+
if not any(value.startswith(p) for p in self._prefixes):
273+
if len(self._prefixes) == 1:
274+
message = _('The provided key does not look valid. It should start with "%(prefix)s".')
275+
params = {'value': value, 'prefix': self._prefixes[0]}
276+
else:
277+
message = _('The provided key does not look valid. It should start with one of: %(prefixes)s')
278+
params = {'value': value, 'prefixes': ', '.join(f'"{p}"' for p in self._prefixes)}
279+
280+
raise forms.ValidationError(
281+
message,
282+
code='invalid-stripe-key',
283+
params=params
284+
)

0 commit comments

Comments
 (0)