Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schedule menu in ticket shop should consider schedule state from talk #354

Open
wants to merge 1 commit into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/pretix/api/serializers/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,9 +724,6 @@ class EventSettingsSerializer(SettingsSerializer):
'logo_image_large',
'logo_show_title',
'og_image',
'schedule_link',
'session_link',
'speaker_link',
]

def __init__(self, *args, **kwargs):
Expand Down
1 change: 1 addition & 0 deletions src/pretix/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,5 @@
url(r"^me$", user.MeView.as_view(), name="user.me"),
url(r"^version$", version.VersionView.as_view(), name="version"),
url(r"(?P<organizer>[^/]+)/(?P<event>[^/]+)/customer/(?P<customer_id>[^/]+)/ticket-check", event.CustomerOrderCheckView.as_view()),
url(r"(?P<organizer>[^/]+)/(?P<event>[^/]+)/schedule-public", event.talk_schedule_public),
]
64 changes: 63 additions & 1 deletion src/pretix/api/views/event.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import json
import logging

import django_filters
import jwt
from django.conf import settings
from django.db import transaction
from django.db.models import ProtectedError, Q
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from django.utils.timezone import now
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
from django_scopes import scopes_disabled
from rest_framework import filters, serializers, views, viewsets
Expand All @@ -16,14 +24,16 @@
)
from pretix.api.views import ConditionalListView
from pretix.base.models import (
CartPosition, Device, Event, TaxRule, TeamAPIToken, Organizer, Customer, Order,
CartPosition, Device, Event, TaxRule, TeamAPIToken, Organizer, Customer, Order, User,
)
from pretix.base.models.event import SubEvent
from pretix.base.settings import SETTINGS_AFFECTING_CSS
from pretix.helpers.dicts import merge_dicts
from pretix.presale.style import regenerate_css
from pretix.presale.views.organizer import filter_qs_by_attr

logger = logging.getLogger(__name__)

with scopes_disabled():
class EventFilter(FilterSet):
is_past = django_filters.rest_framework.BooleanFilter(method='is_past_qs')
Expand Down Expand Up @@ -439,3 +449,55 @@ def get(self, request, *args, **kwargs):
return JsonResponse(status=200, data={"message": "Customer has paid orders."})

return JsonResponse(status=400, data={"message": "Customer did not paid orders."})


def check_token_permission(token, permission_required):
# Decode and validate the JWT token
decoded_data = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
# Check if user existed
User.objects.get(email=decoded_data["email"])
if decoded_data.get("has_perms") not in permission_required:
return False
return True


@csrf_exempt
@require_POST
@scopes_disabled()
def talk_schedule_public(request, *args, **kwargs):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Refine exception handling and function structure

Consider catching specific exceptions instead of using bare except clauses. This function is quite long; consider breaking it down into smaller, more focused functions for better readability and maintainability.

def talk_schedule_public(request, *args, **kwargs):
    try:
        return _process_talk_schedule(request, *args, **kwargs)
    except InvalidToken:
        return JsonResponse({"error": "Invalid token"}, status=401)
    except PermissionDenied:
        return JsonResponse({"error": "Permission denied"}, status=403)
    except Exception as e:
        logger.error(f"Error processing talk schedule: {str(e)}")
        return JsonResponse({"error": "Internal server error"}, status=500)

def _process_talk_schedule(request, *args, **kwargs):

auth_header = request.headers.get("Authorization")
if auth_header and auth_header.startswith("Bearer "):
token = auth_header.split(" ")[1]
try:
if not check_token_permission(token, 'orga.edit_schedule'):
return JsonResponse(
{"status": "User does not have permission to show schedule on menu"},
status=403,
)
organiser = get_object_or_404(Organizer, slug=kwargs['organizer'])
event = get_object_or_404(Event, slug=kwargs['event'], organizer=organiser)
request_data = json.loads(request.body)
event.settings.talk_schedule_public = request_data.get('is_show_schedule') or False

return JsonResponse({"status": "success"}, status=200)

except jwt.ExpiredSignatureError:
logger.error("Token has expired")
return JsonResponse({"status": "Token has expired"}, status=401)
except jwt.InvalidTokenError:
logger.error("Invalid token")
return JsonResponse({"status": "Invalid token"}, status=401)
except Organizer.DoesNotExist:
logger.error("Organizer not found")
return JsonResponse({"status": "Organizer not found"}, status=404)
except Event.DoesNotExist:
logger.error("Event not found")
return JsonResponse({"status": "Event not found"}, status=404)
except Exception as e:
logger.error("Internal server error: %s", e)
return JsonResponse({"status": "Internal server error"}, status=500)
else:
logger.error("Authorization header missing or invalid")
return JsonResponse(
{"status": "Authorization header missing or invalid"}, status=403
)
30 changes: 0 additions & 30 deletions src/pretix/base/configurations/default_setting.py
Original file line number Diff line number Diff line change
Expand Up @@ -2390,36 +2390,6 @@ def primary_font_kwargs():
),
'serializer_class': I18nURLField,
},
'schedule_link': {
'default': None,
'type': str,
'form_class': forms.URLField,
'serializer_class': serializers.URLField,
'form_kwargs': dict(
label=_("Schedule URL"),
help_text=_("This should point to your session schedule."),
),
},
'session_link': {
'default': None,
'type': str,
'form_class': forms.URLField,
'serializer_class': serializers.URLField,
'form_kwargs': dict(
label=_("Session URL"),
help_text=_("This should point to your session list."),
),
},
'speaker_link': {
'default': None,
'type': str,
'form_class': forms.URLField,
'serializer_class': serializers.URLField,
'form_kwargs': dict(
label=_("Speaker URL"),
help_text=_("This should point to your speakers."),
),
},
'seating_choice': {
'default': 'True',
'form_class': forms.BooleanField,
Expand Down
18 changes: 18 additions & 0 deletions src/pretix/base/models/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,24 @@ def has_paid_things(self):
return Item.objects.filter(event=self, default_price__gt=0).exists()\
or ItemVariation.objects.filter(item__event=self, default_price__gt=0).exists()

@property
def talk_schedule_url(self):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Improve URL construction for talk-related properties

Ensure that settings.TALK_HOSTNAME is properly defined. Consider using Django's reverse() function or a similar URL construction method instead of string concatenation for more robust URL generation.

    def talk_schedule_url(self):
        from django.urls import reverse
        return reverse('talk:schedule', kwargs={'event_slug': self.slug})

talk_host = settings.TALK_HOSTNAME
url = urljoin(talk_host, f"{self.slug}/schedule")
return url

@property
def talk_session_url(self):
talk_host = settings.TALK_HOSTNAME
url = urljoin(talk_host, f"{self.slug}/talk")
return url

@property
def talk_speaker_url(self):
talk_host = settings.TALK_HOSTNAME
url = urljoin(talk_host, f"{self.slug}/speaker")
return url

@cached_property
def live_issues(self):
from pretix.base.signals import event_live_issues
Expand Down
18 changes: 0 additions & 18 deletions src/pretix/control/forms/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,9 +495,6 @@ class EventSettingsForm(SettingsForm):
'logo_image_large',
'logo_show_title',
'og_image',
'schedule_link',
'session_link',
'speaker_link',
]

def clean(self):
Expand Down Expand Up @@ -1329,21 +1326,6 @@ class QuickSetupForm(I18nForm):
"information."),
required=False,
)
schedule_link = forms.URLField(
label=_("Schedule URL"),
help_text=_("This should point to your session schedule."),
required=False,
)
session_link = forms.URLField(
label=_("Session URL"),
help_text=_("This should point to your session list."),
required=False,
)
speaker_link = forms.URLField(
label=_("Speaker URL"),
help_text=_("This should point to your speakers."),
required=False,
)
contact_mail = forms.EmailField(
label=_("Contact address"),
required=False,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ <h1>{% trans "General settings" %}</h1>
{% bootstrap_field sform.imprint_url layout="control" %}
{% bootstrap_field form.is_public layout="control" %}
{% bootstrap_field form.sales_channels layout="control" %}
{% bootstrap_field sform.schedule_link layout="control" %}
{% bootstrap_field sform.session_link layout="control" %}
{% bootstrap_field sform.speaker_link layout="control" %}

{% if meta_forms %}
<div class="form-group metadata-group">
Expand Down
12 changes: 4 additions & 8 deletions src/pretix/presale/templates/pretixpresale/event/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,19 @@
<main aria-label="{% if show_cart %}{% trans "Your cart, general information, add products to your cart" %}{% else %}{% trans "General information, add products to your cart" %}{% endif %}">
<nav id="schedule-nav"{% if with_margin %} class="p-3"{% endif %}>
<div class="navigation">
{% if request.event.settings.schedule_link %}
{% if request.event.settings.talk_schedule_public %}
<div class="navigation-button">
<a href="{{ request.event.settings.schedule_link }}" class="header-nav btn btn-outline-success">
<a href="{{ request.event.talk_schedule_url }}" class="header-nav btn btn-outline-success">
<i class="fa fa-calendar"></i> {% trans "Schedule" %}
</a>
</div>
{% endif %}
{% if request.event.settings.session_link %}
<div class="navigation-button">
<a href="{{ request.event.settings.session_link }}" class="header-nav btn btn-outline-success">
<a href="{{ request.event.talk_session_url }}" class="header-nav btn btn-outline-success">
<i class="fa fa-comments-o"></i> {% trans "Sessions" %}
</a>
</div>
{% endif %}
{% if request.event.settings.speaker_link %}
<div class="navigation-button">
<a href="{{ request.event.settings.speaker_link }}" class="header-nav btn btn-outline-success">
<a href="{{ request.event.talk_speaker_url }}" class="header-nav btn btn-outline-success">
<i class="fa fa-group"></i> {% trans "Speakers" %}
</a>
</div>
Expand Down
Loading