mirror of
https://github.com/pretix/pretix.git
synced 2026-10-22 22:43:44 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a969f0ee61 |
No files matched your search
+1
-1
@@ -77,7 +77,7 @@ dependencies = [
|
||||
"paypal-checkout-serversdk==1.0.*",
|
||||
"PyJWT==2.15.*",
|
||||
"phonenumberslite==9.0.*",
|
||||
"Pillow==13.0.*",
|
||||
"Pillow==12.3.*",
|
||||
"pretix-plugin-build",
|
||||
"protobuf==7.36.*",
|
||||
"psycopg2-binary",
|
||||
|
||||
@@ -76,7 +76,7 @@ class DeviceTokenAuthentication(TokenAuthentication):
|
||||
except DeviceLastSeen.DoesNotExist:
|
||||
# First request from device, create model, ignore result. Use get_or_create to be safe
|
||||
# against concurrent create requests
|
||||
DeviceLastSeen.objects.get_or_create(device=device, defaults={"last_seen": now()})
|
||||
DeviceLastSeen.objects.get_or_create(device=device, last_seen=now())
|
||||
else:
|
||||
if now() - last_seen_obj.last_seen < timedelta(seconds=10):
|
||||
# We don't need to know the last seen info of a device to more precision than this,
|
||||
|
||||
@@ -378,7 +378,7 @@ class ItemSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
|
||||
def validate_bundles(self, value):
|
||||
if not self.instance:
|
||||
for b_data in value:
|
||||
ItemBundle.clean_itemvar(self.context['event'], b_data.get('bundled_item'), b_data.get('bundled_variation'))
|
||||
ItemBundle.clean_itemvar(self.context['event'], b_data['bundled_item'], b_data['bundled_variation'])
|
||||
return value
|
||||
|
||||
def validate_addons(self, value):
|
||||
|
||||
@@ -1198,7 +1198,7 @@ OrganizerFooterLinkFormset = inlineformset_factory(
|
||||
class SSOProviderForm(I18nModelForm):
|
||||
|
||||
config_oidc_base_url = forms.URLField(
|
||||
label=pgettext_lazy('sso_oidc', 'Base URL / issuer'),
|
||||
label=pgettext_lazy('sso_oidc', 'Base URL'),
|
||||
required=False,
|
||||
)
|
||||
config_oidc_client_id = forms.CharField(
|
||||
@@ -1295,14 +1295,6 @@ class SSOProviderForm(I18nModelForm):
|
||||
|
||||
|
||||
class SSOClientForm(I18nModelForm):
|
||||
disp_base_url = forms.CharField(
|
||||
label=_('Base URL / issuer'),
|
||||
disabled=True,
|
||||
)
|
||||
disp_client_id = forms.CharField(
|
||||
label=_('Client ID'),
|
||||
disabled=True,
|
||||
)
|
||||
regenerate_client_secret = forms.BooleanField(
|
||||
label=_('Invalidate old client secret and generate a new one'),
|
||||
required=False,
|
||||
@@ -1310,8 +1302,7 @@ class SSOClientForm(I18nModelForm):
|
||||
|
||||
class Meta:
|
||||
model = CustomerSSOClient
|
||||
fields = ['is_active', 'name', 'disp_base_url', 'disp_client_id', 'regenerate_client_secret',
|
||||
'client_type', 'authorization_grant_type', 'redirect_uris',
|
||||
fields = ['is_active', 'name', 'client_id', 'client_type', 'authorization_grant_type', 'redirect_uris',
|
||||
'allowed_scopes', 'require_pkce']
|
||||
widgets = {
|
||||
'authorization_grant_type': forms.RadioSelect,
|
||||
@@ -1326,15 +1317,13 @@ class SSOClientForm(I18nModelForm):
|
||||
help_text=self.fields['allowed_scopes'].help_text,
|
||||
required=self.fields['allowed_scopes'].required,
|
||||
initial=self.fields['allowed_scopes'].initial,
|
||||
choices=[(val, format_html('<code>{}</code> – {}', val, label)) for val, label in CustomerSSOClient.SCOPE_CHOICES],
|
||||
choices=CustomerSSOClient.SCOPE_CHOICES,
|
||||
widget=forms.CheckboxSelectMultiple
|
||||
)
|
||||
organizer = kwargs['event']
|
||||
self.initial['disp_base_url'] = eventreverse_absolute(organizer, 'presale:organizer.index', {}).strip('/')
|
||||
if self.instance and self.instance.pk:
|
||||
self.initial['disp_client_id'] = self.instance.client_id
|
||||
self.fields['client_id'].disabled = True
|
||||
else:
|
||||
self.initial['disp_client_id'] = _('(will be generated)')
|
||||
del self.fields['client_id']
|
||||
del self.fields['regenerate_client_secret']
|
||||
|
||||
|
||||
|
||||
@@ -1,29 +1,12 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}
|
||||
{% if client %}
|
||||
{% trans "SSO client:" %} {{ client.name }}
|
||||
{% else %}
|
||||
{% trans "Create credentials for a new SSO client" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block inner %}
|
||||
{% if client %}
|
||||
<h1>{% trans "SSO client:" %} {{ client.name }}</h1>
|
||||
{% else %}
|
||||
<h1>{% trans "Create credentials for a new SSO client" %}</h1>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
After submitting this form, client credentials for your SSO client will be generated.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<h1>{% trans "Create a new SSO client" %}</h1>
|
||||
{% endif %}
|
||||
<p>
|
||||
{% blocktrans trimmed with url="https://docs.pretix.eu/guides/customer-accounts/#using-pretix-as-an-sso-provider" %}
|
||||
For more information, refer to our documentation on <a href="{{ url }}">Using pretix as an SSO provider with external SSO clients</a>.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<form class="form-horizontal" action="" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form layout="control" %}
|
||||
|
||||
@@ -3,23 +3,16 @@
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}{% trans "SSO clients" %}{% endblock %}
|
||||
{% block inner %}
|
||||
<h1>{% trans "SSO clients" %} <small> — {% blocktrans %}
|
||||
"Login with pretix" in external systems
|
||||
{% endblocktrans %}</small></h1>
|
||||
<h1>{% trans "SSO clients" %}</h1>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
You can allow your customers to log into other systems using their customer account credentials by setting up
|
||||
your other systems as a Single-Sign-On (SSO) client based on OpenID Connect.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans trimmed with url="https://docs.pretix.eu/guides/customer-accounts/#using-pretix-as-an-sso-provider" %}
|
||||
For more information, refer to our documentation on <a href="{{ url }}">Using pretix as an SSO provider with external SSO clients</a>.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<a href="{% url "control:organizer.ssoclient.add" organizer=request.organizer.slug %}" class="btn btn-default">
|
||||
<span class="fa fa-plus"></span>
|
||||
{% trans "Create credentials for a new SSO client" %}
|
||||
{% trans "Create a new SSO client" %}
|
||||
</a>
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}
|
||||
{% if provider %}
|
||||
{% trans "External SSO provider:" %} {{ provider.name }}
|
||||
{% else %}
|
||||
{% trans "Connect to an external SSO provider" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block inner %}
|
||||
{% if provider %}
|
||||
<h1>{% trans "External SSO provider:" %} {{ provider.name }}</h1>
|
||||
<h1>{% trans "SSO provider:" %} {{ provider.name }}</h1>
|
||||
{% else %}
|
||||
<h1>{% trans "Connect to an external SSO provider" %}</h1>
|
||||
<h1>{% trans "Create a new SSO provider" %}</h1>
|
||||
{% endif %}
|
||||
<p>
|
||||
{% blocktrans trimmed with url="https://docs.pretix.eu/guides/customer-accounts/#using-pretix-as-an-sso-client" %}
|
||||
For more information, refer to our documentation on <a href="{{ url }}" target="_blank">Using pretix as an SSO client</a>.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<form class="form-horizontal" action="" method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form layout="control" %}
|
||||
|
||||
@@ -3,23 +3,16 @@
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}{% trans "SSO providers" %}{% endblock %}
|
||||
{% block inner %}
|
||||
<h1>{% trans "SSO providers" %} <small> — {% blocktrans %}
|
||||
Connect to an external login provider
|
||||
{% endblocktrans %}</small></h1>
|
||||
<h1>{% trans "SSO providers" %}</h1>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
You can connect existing Single-Sign-On (SSO) providers to allow your customers to log in using your own
|
||||
account system.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans trimmed with url="https://docs.pretix.eu/guides/customer-accounts/#using-pretix-as-an-sso-client" %}
|
||||
For more information, refer to our documentation on <a href="{{ url }}" target="_blank">Using pretix as an SSO client</a>.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<a href="{% url "control:organizer.ssoprovider.add" organizer=request.organizer.slug %}" class="btn btn-default">
|
||||
<span class="fa fa-plus"></span>
|
||||
{% trans "Connect to an external SSO provider" %}
|
||||
{% trans "Create a new SSO provider" %}
|
||||
</a>
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
|
||||
@@ -2817,15 +2817,10 @@ class SSOProviderCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequire
|
||||
return get_object_or_404(CustomerSSOProvider, organizer=self.request.organizer, pk=self.kwargs.get('provider'))
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('control:organizer.ssoprovider.edit', kwargs={
|
||||
'organizer': self.request.organizer.slug, 'provider': self.object.pk,
|
||||
return reverse('control:organizer.ssoproviders', kwargs={
|
||||
'organizer': self.request.organizer.slug,
|
||||
})
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['redirect_uri'] = _('(will be generated)')
|
||||
return ctx
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['event'] = self.request.organizer
|
||||
@@ -2955,11 +2950,8 @@ class SSOClientCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredM
|
||||
secret = form.instance.set_client_secret()
|
||||
messages.success(
|
||||
self.request,
|
||||
_('The SSO client has been created.') + ' ' +
|
||||
_('Please note down the following client secret, it will never be shown again.') + '\n\n' +
|
||||
_('Base URL / issuer') + f': {form.initial["disp_base_url"]}\n\n' +
|
||||
_('Client ID') + f': {form.instance.client_id}\n\n' +
|
||||
_('Client secret') + f': {secret}'
|
||||
_('The SSO client has been created. Please note down the following client secret, it will never be shown '
|
||||
'again: {secret}').format(secret=secret)
|
||||
)
|
||||
form.instance.organizer = self.request.organizer
|
||||
ret = super().form_valid(form)
|
||||
@@ -3008,9 +3000,8 @@ class SSOClientUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredM
|
||||
secret = form.instance.set_client_secret()
|
||||
messages.success(
|
||||
self.request,
|
||||
_('Your changes have been saved.') + ' ' +
|
||||
_('Please note down the following client secret, it will never be shown again.') + '\n\n' +
|
||||
_('Client secret') + f': {secret}'
|
||||
_('Your changes have been saved. Please note down the following client secret, it will never be shown '
|
||||
'again: {secret}').format(secret=secret)
|
||||
)
|
||||
else:
|
||||
messages.success(
|
||||
|
||||
@@ -633,9 +633,6 @@ class ImportView(ListView):
|
||||
|
||||
class OrganizerBanktransferView:
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
# Users can use the bank transfer views if they have sufficient permission for at least one event.
|
||||
# Yes, this allows them to cauase changes in events they don't have access to. This is an accepted
|
||||
# risk because every other way, the bank transfer feature becomes basically unusable.
|
||||
has_any_event_perm = request.user.get_events_with_permission(
|
||||
"event.orders:write", request=request
|
||||
).filter(organizer=request.organizer).exists()
|
||||
|
||||
@@ -172,9 +172,6 @@ var pretixstripe = {
|
||||
})
|
||||
|
||||
pretixstripe.affirm.mount('#stripe-affirm')
|
||||
pretixstripe.affirm.on('ready', function () {
|
||||
$('.stripe-container').closest('form').find('.checkout-button-row .btn-primary').prop('disabled', false)
|
||||
})
|
||||
}
|
||||
if ($('#stripe-klarna').length) {
|
||||
try {
|
||||
@@ -186,9 +183,6 @@ var pretixstripe = {
|
||||
})
|
||||
|
||||
pretixstripe.klarna.mount('#stripe-klarna')
|
||||
pretixstripe.klarna.on('ready', function () {
|
||||
$('.stripe-container').closest('form').find('.checkout-button-row .btn-primary').prop('disabled', false)
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
$('#stripe-klarna').html('<div class=\'alert alert-danger\'>Technical error, please contact support: ' + e + '</div>')
|
||||
|
||||
@@ -20,7 +20,7 @@ function pgettext (context, msgid) {
|
||||
return msgid
|
||||
}
|
||||
|
||||
function interpolate (fmt, obj, named) {
|
||||
function interpolate (fmt, object, named) {
|
||||
if (named) {
|
||||
return fmt.replace(/%\(\w+\)s/g, function (match) { return String(obj[match.slice(2, -2)]) })
|
||||
} else {
|
||||
|
||||
@@ -74,6 +74,8 @@ $panel-default-heading-bg: #e5e5e5 !default;
|
||||
$link-hover-color: var(--pretix-brand-primary-darken-15);
|
||||
|
||||
$btn-default-border: #949494;
|
||||
$btn-default-border-disabled: #ccc !default;
|
||||
$btn-default-bg-disabled: $gray-lighter;
|
||||
|
||||
$btn-primary-border: var(--pretix-brand-primary-darken-5);
|
||||
$btn-primary-border-active: var(--pretix-brand-primary-darken-30);
|
||||
|
||||
@@ -44,12 +44,10 @@ input[type=number]::-webkit-outer-spin-button {
|
||||
box-shadow: 0px 0px 0px 1px $input-border inset;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.btn-default:hover, .btn-default:focus {
|
||||
box-shadow: 0px 0px 0px 1px $input-border inset, inset 0 1px 3px 0 #BFBFBF;
|
||||
background: $btn-default-bg;
|
||||
}
|
||||
|
||||
.btn-default:active, .btn-default:active:hover, .btn-default:active:focus {
|
||||
background: $btn-default-bg;
|
||||
outline: 0;
|
||||
@@ -57,6 +55,19 @@ input[type=number]::-webkit-outer-spin-button {
|
||||
.btn-default.active, .btn-default.active:hover, .btn-default.active:focus {
|
||||
box-shadow: 0px 0px 0px 1px $input-border inset, inset 0 1px 8px 0 #BFBFBF;
|
||||
}
|
||||
.btn-default.disabled, .btn-default[disabled], fieldset[disabled] .btn-default {
|
||||
&, &:hover, &:focus {
|
||||
box-shadow: 0px 0px 0px 1px $btn-default-border-disabled inset, inset 0 1px 3px 0 #d9d9d9;
|
||||
background: $btn-default-bg-disabled;
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-link.disabled, .btn-link[disabled], fieldset[disabled] .btn-link {
|
||||
box-shadow: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
|
||||
.btn-primary:hover, .btn-primary:focus {
|
||||
box-shadow: inset 0 1px 3px 0 var(--pretix-brand-primary-shade-25);
|
||||
@@ -117,16 +128,6 @@ input[type=number]::-webkit-outer-spin-button {
|
||||
border: transparent;
|
||||
}
|
||||
|
||||
.btn.disabled, .btn[disabled], fieldset[disabled] .btn {
|
||||
box-shadow: 0px 0px 0px 1px #ccc inset, inset 0 1px 3px 0 #d9d9d9;
|
||||
background: #eee;
|
||||
opacity: 0.7;
|
||||
}
|
||||
.btn-link.disabled, .btn-link[disabled], fieldset[disabled] .btn-link {
|
||||
box-shadow: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.btn-group-flex { display: flex; }
|
||||
.btn-group-flex > .btn { flex: 1; }
|
||||
|
||||
|
||||
@@ -1000,6 +1000,7 @@ def test_item_create_with_bundle(token_client, organizer, event, item, category,
|
||||
"bundles": [
|
||||
{
|
||||
"bundled_item": i.pk,
|
||||
"bundled_variation": None,
|
||||
"count": 2,
|
||||
"designated_price": "3.00",
|
||||
}
|
||||
|
||||
@@ -642,8 +642,6 @@ def assert_mail_connection(res, should_connect, use_ssl):
|
||||
True, False
|
||||
])
|
||||
def test_private_smtp_ip(res, use_ssl, settings):
|
||||
settings.EMAIL_HOST_USER = ''
|
||||
settings.EMAIL_HOST_PASSWORD = ''
|
||||
settings.EMAIL_CUSTOM_SMTP_BACKEND = 'pretix.base.email.CheckPrivateNetworkSmtpBackend'
|
||||
settings.MAIL_CUSTOM_SMTP_ALLOW_PRIVATE_NETWORKS = False
|
||||
with assert_mail_connection(res=res, should_connect=False, use_ssl=use_ssl), pytest.raises(match="Request to .* blocked"):
|
||||
@@ -667,8 +665,6 @@ def test_private_smtp_ip(res, use_ssl, settings):
|
||||
True, False
|
||||
])
|
||||
def test_public_smtp_ip(use_ssl, allow_private, settings):
|
||||
settings.EMAIL_HOST_USER = ''
|
||||
settings.EMAIL_HOST_PASSWORD = ''
|
||||
settings.EMAIL_CUSTOM_SMTP_BACKEND = 'pretix.base.email.CheckPrivateNetworkSmtpBackend'
|
||||
settings.MAIL_CUSTOM_SMTP_ALLOW_PRIVATE_NETWORKS = allow_private
|
||||
|
||||
|
||||
Reference in new issue
Block a user