Compare commits

..

4 Commits

Author SHA1 Message Date
luelista
dac3230930 Fix markup of error template 2026-06-09 18:45:47 +02:00
Richard Schreiber
07d27e66d1 Use HTTP-REFERER as fallback for vite_origins (#6246) 2026-06-09 13:24:46 +02:00
Richard Schreiber
b404316dfd [SECURITY] Reusable media export: Respect giftcard permissions (CVE-2026-11764) (#6261) 2026-06-09 13:20:48 +02:00
luelista
edf97a13cd Don't show warning if inactive products are used in checkin-rules (Z#23236197) (#6242) 2026-06-09 12:48:03 +02:00
7 changed files with 23 additions and 11 deletions

View File

@@ -93,7 +93,7 @@ dependencies = [
"redis==7.4.*",
"reportlab==4.5.*",
"requests==2.32.*",
"sentry-sdk==2.62.*",
"sentry-sdk==2.61.*",
"sepaxml==2.7.*",
"stripe==7.9.*",
"text-unidecode==1.*",

View File

@@ -64,7 +64,13 @@ class ReusableMediaExporter(OrganizerLevelExportMixin, ListExporter):
yield headers
yield self.ProgressSetTotal(total=media.count())
can_read_giftcards = self.permission_holder.has_organizer_permission(self.organizer, 'organizer.giftcards:read')
for medium in media.iterator(chunk_size=1000):
giftcard_secret = medium.linked_giftcard.secret if medium.linked_giftcard_id else ''
if giftcard_secret and not can_read_giftcards:
giftcard_secret = giftcard_secret[:3] + ""
yield [
medium.type,
medium.identifier,
@@ -72,7 +78,7 @@ class ReusableMediaExporter(OrganizerLevelExportMixin, ListExporter):
date_format(medium.expires, 'SHORT_DATETIME_FORMAT') if medium.expires else '',
medium.customer.identifier if medium.customer_id else '',
', '.join([f"{op.order.code}-{op.positionid}" for op in medium.linked_orderpositions.all()]),
medium.linked_giftcard.secret if medium.linked_giftcard_id else '',
giftcard_secret,
medium.notes,
]

View File

@@ -20,6 +20,6 @@
<div class="container">
{% block content %}{% endblock %}
</div>
</body>
<script src="{% static "pretixbase/js/errors.js" %}"></script>
</body>
</html>

View File

@@ -401,13 +401,14 @@ class CheckinListUpdate(EventPermissionRequiredMixin, UpdateView):
{
'id': i.pk,
'name': str(i),
'active': i.active,
'variations': [
{
'id': v.pk,
'name': str(v.value)
} for v in i.variations.all()
]
} for i in self.request.event.items.filter(active=True).prefetch_related('variations')
} for i in self.request.event.items.prefetch_related('variations')
],
**super().get_context_data(),
}

View File

@@ -128,6 +128,9 @@ def _use_vite(request):
origin = request.META.get('HTTP_ORIGIN', '')
gs = GlobalSettingsObject()
vite_origins = gs.settings.get('widget_vite_origins', as_type=str, default='')
if vite_origins and not origin:
referer = request.META.get('HTTP_REFERER', '')
origin = '/'.join(referer.split('/', 3)[:3])
if origin and vite_origins:
origins_list = [o.strip() for o in vite_origins.strip().splitlines() if o.strip()]
return origin in origins_list

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { computed } from 'vue'
import { rules as rawRules, items, allProducts, limitProducts } from './django-interop'
import { rules as rawRules, allItems, activeItems, allProducts, limitProducts } from './django-interop'
import { convertToDNF } from './jsonlogic-boolalg'
import RulesEditor from './checkin-rules-editor.vue'
@@ -53,7 +53,7 @@ const missingItems = computed(() => {
}
let missing = []
for (const item of items.value) {
for (const item of activeItems.value) {
if (productsSeen[item.id]) continue
if (!allProducts.value && !limitProducts.value.includes(item.id)) continue
if (item.variations.length > 0) {
@@ -87,7 +87,7 @@ const missingItems = computed(() => {
//- Tab panes
.tab-content
#rules-edit.tab-pane.active(v-if="items", role="tabpanel")
#rules-edit.tab-pane.active(v-if="allItems", role="tabpanel")
RulesEditor
#rules-viz.tab-pane(role="tabpanel")
RulesVisualization

View File

@@ -26,11 +26,13 @@ watch(rules, (newVal) => {
rulesInput.value = JSON.stringify(newVal)
}, { deep: true })
export const items = ref<any[]>([])
export const activeItems = ref<any[]>([])
export const allItems = ref<any[]>([])
const itemsEl = document.querySelector('#items')
if (itemsEl?.textContent) {
items.value = JSON.parse(itemsEl.textContent || '[]')
allItems.value = JSON.parse(itemsEl.textContent || '[]')
activeItems.value = allItems.value.filter(item => item.active)
function checkForInvalidIds (validProducts: Record<string, string>, validVariations: Record<string, string>, rule: any) {
if (rule['and']) {
@@ -57,8 +59,8 @@ if (itemsEl?.textContent) {
}
checkForInvalidIds(
Object.fromEntries(items.value.map(p => [p.id, p.name])),
Object.fromEntries(items.value.flatMap(p => p.variations?.map(v => [v.id, p.name + ' ' + v.name]) ?? [])),
Object.fromEntries(allItems.value.map(p => [p.id, p.name])),
Object.fromEntries(allItems.value.flatMap(p => p.variations?.map(v => [v.id, p.name + ' ' + v.name]) ?? [])),
rules.value
)
}