From ecd2a5c7b9626510357bf5d7cfac271264a141a5 Mon Sep 17 00:00:00 2001 From: odkhang Date: Mon, 2 Dec 2024 15:59:15 +0700 Subject: [PATCH 01/31] Enable video plugin --- src/pretalx/eventyay_common/tasks.py | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/pretalx/eventyay_common/tasks.py b/src/pretalx/eventyay_common/tasks.py index 82791a01c..8ab8a3114 100644 --- a/src/pretalx/eventyay_common/tasks.py +++ b/src/pretalx/eventyay_common/tasks.py @@ -1,5 +1,7 @@ +import importlib.util import logging from datetime import datetime +from importlib import import_module from celery import shared_task from django.core.exceptions import ValidationError @@ -138,6 +140,7 @@ def process_event_webhook(event_data): locale=event_data.get("locale"), date_from=datetime.fromisoformat(event_data.get("date_from")), date_to=datetime.fromisoformat(event_data.get("date_to")), + plugins=enable_video_plugin() if event_data.get("is_video_creation") else None, ) event.save() elif action == Action.UPDATE: @@ -154,6 +157,7 @@ def process_event_webhook(event_data): event.content_locale_array = ",".join(event_data.get("locales")) event.timezone = event_data.get("timezone") event.locale = event_data.get("locale") + event.plugins = add_plugin(event, enable_video_plugin()) if event_data.get("is_video_creation") else None event.save() logger.info(f"Event for organiser {organiser.name} created successfully.") @@ -166,3 +170,40 @@ def process_event_webhook(event_data): logger.error("Validation error:", e.message_dict) except Exception as e: logger.error("Error saving organiser:", e) + + +def enable_video_plugin(): + video_plugin = get_installed_plugin('pretalx_venueless') + if video_plugin: + plugins = 'pretalx_venueless' + return plugins + else: + logger.error("Video plugin not installed.") + return None + + +def get_installed_plugin(plugin_name): + """ + Check if a plugin is installed. + @param plugin_name: A string representing the name of the plugin to check. + @return: The installed plugin if it exists, otherwise None. + """ + if importlib.util.find_spec(plugin_name) is not None: + installed_plugin = import_module(plugin_name) + else: + installed_plugin = None + return installed_plugin + + +def add_plugin(event, plugin_name): + """ + Add a plugin + @param event: The event instance to which the plugin should be added. + @param plugin_name: A string representing the name of the plugin to add. + @return: The updated list of plugins for the event. + """ + if not event.plugins: + return plugin_name + plugins = set(event.plugins.split(',')) + plugins.add(plugin_name) + return ','.join(plugins) From 257988078fe9068dcdc1d7b542741220b99e8944 Mon Sep 17 00:00:00 2001 From: odkhang Date: Mon, 2 Dec 2024 16:32:40 +0700 Subject: [PATCH 02/31] Fix black in pipeline --- src/pretalx/eventyay_common/tasks.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/pretalx/eventyay_common/tasks.py b/src/pretalx/eventyay_common/tasks.py index 8ab8a3114..0079abbd1 100644 --- a/src/pretalx/eventyay_common/tasks.py +++ b/src/pretalx/eventyay_common/tasks.py @@ -140,7 +140,11 @@ def process_event_webhook(event_data): locale=event_data.get("locale"), date_from=datetime.fromisoformat(event_data.get("date_from")), date_to=datetime.fromisoformat(event_data.get("date_to")), - plugins=enable_video_plugin() if event_data.get("is_video_creation") else None, + plugins=( + enable_video_plugin() + if event_data.get("is_video_creation") + else None + ), ) event.save() elif action == Action.UPDATE: @@ -157,7 +161,11 @@ def process_event_webhook(event_data): event.content_locale_array = ",".join(event_data.get("locales")) event.timezone = event_data.get("timezone") event.locale = event_data.get("locale") - event.plugins = add_plugin(event, enable_video_plugin()) if event_data.get("is_video_creation") else None + event.plugins = ( + add_plugin(event, enable_video_plugin()) + if event_data.get("is_video_creation") + else None + ) event.save() logger.info(f"Event for organiser {organiser.name} created successfully.") @@ -173,9 +181,9 @@ def process_event_webhook(event_data): def enable_video_plugin(): - video_plugin = get_installed_plugin('pretalx_venueless') + video_plugin = get_installed_plugin("pretalx_venueless") if video_plugin: - plugins = 'pretalx_venueless' + plugins = "pretalx_venueless" return plugins else: logger.error("Video plugin not installed.") @@ -204,6 +212,6 @@ def add_plugin(event, plugin_name): """ if not event.plugins: return plugin_name - plugins = set(event.plugins.split(',')) + plugins = set(event.plugins.split(",")) plugins.add(plugin_name) - return ','.join(plugins) + return ",".join(plugins) From 07fc00bca3c942108bd868efc266fc076fff6648 Mon Sep 17 00:00:00 2001 From: odkhang Date: Mon, 2 Dec 2024 16:38:48 +0700 Subject: [PATCH 03/31] Fix black in pipeline --- src/pretalx/eventyay_common/views/auth.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/pretalx/eventyay_common/views/auth.py b/src/pretalx/eventyay_common/views/auth.py index 444fb5c60..8e0d351d5 100644 --- a/src/pretalx/eventyay_common/views/auth.py +++ b/src/pretalx/eventyay_common/views/auth.py @@ -25,8 +25,11 @@ def oauth2_login_view(request, *args, **kwargs): provider=settings.EVENTYAY_SSO_PROVIDER ).first() if not sso_provider: - messages.error(request, "SSO not configured yet, please contact the " - "administrator or come back later.") + messages.error( + request, + "SSO not configured yet, please contact the " + "administrator or come back later.", + ) return redirect(reverse("orga:login")) # Create an OAuth2 session using the client ID and redirect URI oauth2_session = OAuth2Session( @@ -52,8 +55,11 @@ def oauth2_callback(request): provider=settings.EVENTYAY_SSO_PROVIDER ).first() if not sso_provider: - messages.error(request, "SSO not configured yet, please contact the " - "administrator or come back later.") + messages.error( + request, + "SSO not configured yet, please contact the " + "administrator or come back later.", + ) return redirect(reverse("orga:login")) oauth2_session = OAuth2Session( sso_provider.client_id, From af2191eb5ff099f286045f347043fd463008a8f1 Mon Sep 17 00:00:00 2001 From: odkhang Date: Mon, 2 Dec 2024 17:33:14 +0700 Subject: [PATCH 04/31] Add comment --- src/pretalx/eventyay_common/tasks.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pretalx/eventyay_common/tasks.py b/src/pretalx/eventyay_common/tasks.py index 0079abbd1..5972d6c60 100644 --- a/src/pretalx/eventyay_common/tasks.py +++ b/src/pretalx/eventyay_common/tasks.py @@ -181,6 +181,10 @@ def process_event_webhook(event_data): def enable_video_plugin(): + """ + Enable the video plugin if it is installed. + @return: The plugin if it is installed, otherwise None. + """ video_plugin = get_installed_plugin("pretalx_venueless") if video_plugin: plugins = "pretalx_venueless" From c5d487acc72a18d622f260cbf5f6fd499f28d5c8 Mon Sep 17 00:00:00 2001 From: odkhang Date: Tue, 3 Dec 2024 15:37:46 +0700 Subject: [PATCH 05/31] Update code --- src/pretalx/eventyay_common/tasks.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/pretalx/eventyay_common/tasks.py b/src/pretalx/eventyay_common/tasks.py index 5972d6c60..4c5af7842 100644 --- a/src/pretalx/eventyay_common/tasks.py +++ b/src/pretalx/eventyay_common/tasks.py @@ -141,7 +141,7 @@ def process_event_webhook(event_data): date_from=datetime.fromisoformat(event_data.get("date_from")), date_to=datetime.fromisoformat(event_data.get("date_to")), plugins=( - enable_video_plugin() + get_video_plugin() if event_data.get("is_video_creation") else None ), @@ -162,9 +162,9 @@ def process_event_webhook(event_data): event.timezone = event_data.get("timezone") event.locale = event_data.get("locale") event.plugins = ( - add_plugin(event, enable_video_plugin()) + add_plugin(event, get_video_plugin()) if event_data.get("is_video_creation") - else None + else event.plugins ) event.save() logger.info(f"Event for organiser {organiser.name} created successfully.") @@ -180,10 +180,10 @@ def process_event_webhook(event_data): logger.error("Error saving organiser:", e) -def enable_video_plugin(): +def get_video_plugin(): """ - Enable the video plugin if it is installed. - @return: The plugin if it is installed, otherwise None. + Check if the video plugin is installed. + @return: If the video plugin is installed, return the plugin name, otherwise None. """ video_plugin = get_installed_plugin("pretalx_venueless") if video_plugin: @@ -214,6 +214,8 @@ def add_plugin(event, plugin_name): @param plugin_name: A string representing the name of the plugin to add. @return: The updated list of plugins for the event. """ + if plugin_name is None: + return event.plugins if not event.plugins: return plugin_name plugins = set(event.plugins.split(",")) From b57dda0f562d81f6cfe2e6858b8554a06a5f2156 Mon Sep 17 00:00:00 2001 From: odkhang Date: Fri, 6 Dec 2024 11:28:07 +0700 Subject: [PATCH 06/31] Configure video settings for talk --- src/pretalx/api/urls.py | 1 + src/pretalx/api/views/event.py | 98 ++++++++++++++++++++++++++++++++++ src/pretalx/settings.py | 3 ++ 3 files changed, 102 insertions(+) diff --git a/src/pretalx/api/urls.py b/src/pretalx/api/urls.py index d706e8dc1..ebbb1c79f 100644 --- a/src/pretalx/api/urls.py +++ b/src/pretalx/api/urls.py @@ -30,4 +30,5 @@ "events//favourite-talk/", submission.SubmissionFavouriteDeprecatedView.as_view(), ), + path("configure-video-settings/", event.configure_video_settings), ] diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index dfeb0deb2..9afa28a14 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -1,9 +1,25 @@ +import logging + +import jwt +from django.conf import settings from django.http import Http404 +from django_scopes import scopes_disabled +from pretalx_venueless.forms import VenuelessSettingsForm from rest_framework import viewsets +from rest_framework.authentication import get_authorization_header +from rest_framework.decorators import ( + api_view, + authentication_classes, + permission_classes, +) +from rest_framework.response import Response from pretalx.api.serializers.event import EventSerializer +from pretalx.common import exceptions from pretalx.event.models import Event +logger = logging.getLogger(__name__) + class EventViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = EventSerializer @@ -24,3 +40,85 @@ def get_object(self): if self.request.user.has_perm(self.permission_required, self.request.event): return self.request.event raise Http404() + + +@api_view(http_method_names=["POST"]) +@authentication_classes([]) +@permission_classes([]) +def configure_video_settings(request): + """ + Configure video settings for an event + @param request: request object + @return response object + """ + video_settings = request.data.get("video_settings") + payload = get_payload_from_token(request, video_settings) + event_slug = payload.get("event_slug") + video_tokens = payload.get("video_tokens") + + try: + with scopes_disabled(): + event_instance = Event.objects.get(slug=event_slug) + video_settings_data = { + "token": video_tokens[0], + "url": "{}/api/v1/worlds/{}/".format(settings.EVENTYAY_VIDEO_BASE_PATH, event_slug), + } + + video_settings_form = VenuelessSettingsForm( + event=event_instance, + data=video_settings_data + ) + + if video_settings_form.is_valid(): + video_settings_form.save() + logger.info("Video settings configured successfully for event '%s'.", + event_slug) + return Response({"status": "success"}, status=200) + else: + logger.error( + "Failed to configure video settings for event '%s' - Validation errors: %s", + event_slug, video_settings_form.errors) + return Response({ + "status": "error", + "message": "Validation errors", + "errors": video_settings_form.errors + }, status=400) + except Event.DoesNotExist: + logger.error("Event with slug '%s' does not exist.", event_slug) + return Response({ + "status": "error", + "message": f"Event with slug '{event_slug}' not found." + }, status=404) + + +def get_payload_from_token(request, video_settings): + """ + Verify the token and return the payload + @param request: request object + @param video_settings: dict containing video settings + @return: dict containing payload data from the token + """ + auth_header = get_authorization_header(request).split() + if not auth_header: + raise Http404 + if auth_header and auth_header[0].lower() == b"bearer": + if len(auth_header) == 1: + raise exceptions.AuthenticationFailedError( + "Invalid token header. No credentials provided." + ) + elif len(auth_header) > 2: + raise exceptions.AuthenticationFailedError( + "Invalid token header. Token string should not contain spaces." + ) + token_decode = jwt.decode( + auth_header[1], + video_settings.get("secret"), + algorithms=["HS256"], + ) + event_slug = token_decode.get("slug") + video_tokens = token_decode.get("video_tokens") + + return { + "event_slug": event_slug, + "video_tokens": video_tokens + } diff --git a/src/pretalx/settings.py b/src/pretalx/settings.py index 851ec1c6e..bcb822210 100644 --- a/src/pretalx/settings.py +++ b/src/pretalx/settings.py @@ -689,6 +689,9 @@ def merge_csp(*options, config=None): EVENTYAY_TICKET_BASE_PATH = config.get( "urls", "eventyay-ticket", fallback="https://app-test.eventyay.com/tickets" ) +EVENTYAY_VIDEO_BASE_PATH = config.get( + "urls", "eventyay-video", fallback="https://app-test.eventyay.com/video" +) SITE_ID = 1 # for now, customer must verified their email at eventyay-ticket, so this check not required From 0adbf205585eb57a97dfd795af24d2e44d57cf21 Mon Sep 17 00:00:00 2001 From: odkhang Date: Fri, 6 Dec 2024 12:00:23 +0700 Subject: [PATCH 07/31] Fix black pipeline --- src/pretalx/api/views/event.py | 55 +++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 9afa28a14..63be47a47 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -16,6 +16,7 @@ from pretalx.api.serializers.event import EventSerializer from pretalx.common import exceptions +from pretalx.common.exceptions import AuthenticationFailedError from pretalx.event.models import Event logger = logging.getLogger(__name__) @@ -61,34 +62,49 @@ def configure_video_settings(request): event_instance = Event.objects.get(slug=event_slug) video_settings_data = { "token": video_tokens[0], - "url": "{}/api/v1/worlds/{}/".format(settings.EVENTYAY_VIDEO_BASE_PATH, event_slug), + "url": "{}/api/v1/worlds/{}/".format( + settings.EVENTYAY_VIDEO_BASE_PATH, event_slug + ), } video_settings_form = VenuelessSettingsForm( - event=event_instance, - data=video_settings_data + event=event_instance, data=video_settings_data ) if video_settings_form.is_valid(): video_settings_form.save() - logger.info("Video settings configured successfully for event '%s'.", - event_slug) + logger.info( + "Video settings configured successfully for event %s.", event_slug + ) return Response({"status": "success"}, status=200) else: logger.error( - "Failed to configure video settings for event '%s' - Validation errors: %s", - event_slug, video_settings_form.errors) - return Response({ - "status": "error", - "message": "Validation errors", - "errors": video_settings_form.errors - }, status=400) + "Failed to configure video settings for event %s - Validation errors: %s.", + event_slug, + video_settings_form.errors, + ) + return Response( + { + "status": "error", + "message": "Validation errors", + "errors": video_settings_form.errors, + }, + status=400, + ) except Event.DoesNotExist: - logger.error("Event with slug '%s' does not exist.", event_slug) - return Response({ - "status": "error", - "message": f"Event with slug '{event_slug}' not found." - }, status=404) + logger.error("Event with slug %s does not exist.", event_slug) + return Response( + { + "status": "error", + "message": "Event with slug {} not found.".format(event_slug), + }, + status=404, + ) + except AuthenticationFailedError as e: + logger.error("Authentication failed: %s", e) + return Response( + {"status": "error", "message": "Authentication failed."}, status=401 + ) def get_payload_from_token(request, video_settings): @@ -118,7 +134,4 @@ def get_payload_from_token(request, video_settings): event_slug = token_decode.get("slug") video_tokens = token_decode.get("video_tokens") - return { - "event_slug": event_slug, - "video_tokens": video_tokens - } + return {"event_slug": event_slug, "video_tokens": video_tokens} From 2b1831974ed2e2026b04987524bd792b7c5b44f0 Mon Sep 17 00:00:00 2001 From: odkhang Date: Fri, 6 Dec 2024 16:09:29 +0700 Subject: [PATCH 08/31] Update code --- src/pretalx/api/views/event.py | 57 ++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 63be47a47..550c5c5ac 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -57,6 +57,9 @@ def configure_video_settings(request): event_slug = payload.get("event_slug") video_tokens = payload.get("video_tokens") + if not video_tokens: + raise ValueError("Video tokens not found in the payload") + try: with scopes_disabled(): event_instance = Event.objects.get(slug=event_slug) @@ -100,6 +103,12 @@ def configure_video_settings(request): }, status=404, ) + except ValueError as e: + logger.error("Error configuring video settings: %s", e) + return Response( + {"status": "error", "message": "Error configuring video settings."}, + status=400, + ) except AuthenticationFailedError as e: logger.error("Authentication failed: %s", e) return Response( @@ -114,24 +123,34 @@ def get_payload_from_token(request, video_settings): @param video_settings: dict containing video settings @return: dict containing payload data from the token """ - auth_header = get_authorization_header(request).split() - if not auth_header: - raise Http404 - if auth_header and auth_header[0].lower() == b"bearer": - if len(auth_header) == 1: - raise exceptions.AuthenticationFailedError( - "Invalid token header. No credentials provided." - ) - elif len(auth_header) > 2: + try: + auth_header = get_authorization_header(request).split() + if not auth_header: + raise exceptions.AuthenticationFailedError("No authorization header") + + if len(auth_header) != 2 or auth_header[0].lower() != b"bearer": raise exceptions.AuthenticationFailedError( - "Invalid token header. Token string should not contain spaces." + "Invalid token format. Must be 'Bearer '" ) - token_decode = jwt.decode( - auth_header[1], - video_settings.get("secret"), - algorithms=["HS256"], - ) - event_slug = token_decode.get("slug") - video_tokens = token_decode.get("video_tokens") - - return {"event_slug": event_slug, "video_tokens": video_tokens} + + token_decode = jwt.decode( + auth_header[1], + video_settings.get("secret"), + algorithms=["HS256"] + ) + + event_slug = token_decode.get("slug") + video_tokens = token_decode.get("video_tokens") + + if not event_slug or not video_tokens: + raise exceptions.AuthenticationFailedError("Invalid token payload") + + return { + "event_slug": event_slug, + "video_tokens": video_tokens + } + + except jwt.ExpiredSignatureError: + raise exceptions.AuthenticationFailedError("Token has expired") + except jwt.InvalidTokenError: + raise exceptions.AuthenticationFailedError("Invalid token") From d0d81cdfffd4305cc8f6b725663af63fe64a6102 Mon Sep 17 00:00:00 2001 From: odkhang Date: Fri, 6 Dec 2024 16:17:10 +0700 Subject: [PATCH 09/31] Update code --- src/pretalx/api/views/event.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 550c5c5ac..661da89fc 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -134,9 +134,7 @@ def get_payload_from_token(request, video_settings): ) token_decode = jwt.decode( - auth_header[1], - video_settings.get("secret"), - algorithms=["HS256"] + auth_header[1], video_settings.get("secret"), algorithms=["HS256"] ) event_slug = token_decode.get("slug") @@ -145,10 +143,7 @@ def get_payload_from_token(request, video_settings): if not event_slug or not video_tokens: raise exceptions.AuthenticationFailedError("Invalid token payload") - return { - "event_slug": event_slug, - "video_tokens": video_tokens - } + return {"event_slug": event_slug, "video_tokens": video_tokens} except jwt.ExpiredSignatureError: raise exceptions.AuthenticationFailedError("Token has expired") From 06ee69e18d4f5e5a7ee56d438e48c7cbdbcb1b39 Mon Sep 17 00:00:00 2001 From: odkhang Date: Fri, 6 Dec 2024 17:35:55 +0700 Subject: [PATCH 10/31] Update code --- src/pretalx/api/views/event.py | 70 ++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 661da89fc..51af1d6d0 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -61,39 +61,7 @@ def configure_video_settings(request): raise ValueError("Video tokens not found in the payload") try: - with scopes_disabled(): - event_instance = Event.objects.get(slug=event_slug) - video_settings_data = { - "token": video_tokens[0], - "url": "{}/api/v1/worlds/{}/".format( - settings.EVENTYAY_VIDEO_BASE_PATH, event_slug - ), - } - - video_settings_form = VenuelessSettingsForm( - event=event_instance, data=video_settings_data - ) - - if video_settings_form.is_valid(): - video_settings_form.save() - logger.info( - "Video settings configured successfully for event %s.", event_slug - ) - return Response({"status": "success"}, status=200) - else: - logger.error( - "Failed to configure video settings for event %s - Validation errors: %s.", - event_slug, - video_settings_form.errors, - ) - return Response( - { - "status": "error", - "message": "Validation errors", - "errors": video_settings_form.errors, - }, - status=400, - ) + save_video_settings_information(event_slug, video_tokens) except Event.DoesNotExist: logger.error("Event with slug %s does not exist.", event_slug) return Response( @@ -149,3 +117,39 @@ def get_payload_from_token(request, video_settings): raise exceptions.AuthenticationFailedError("Token has expired") except jwt.InvalidTokenError: raise exceptions.AuthenticationFailedError("Invalid token") + + +def save_video_settings_information(event_slug, video_tokens): + with scopes_disabled(): + event_instance = Event.objects.get(slug=event_slug) + video_settings_data = { + "token": video_tokens[0], + "url": "{}/api/v1/worlds/{}/".format( + settings.EVENTYAY_VIDEO_BASE_PATH, event_slug + ), + } + + video_settings_form = VenuelessSettingsForm( + event=event_instance, data=video_settings_data + ) + + if video_settings_form.is_valid(): + video_settings_form.save() + logger.info( + "Video settings configured successfully for event %s.", event_slug + ) + return Response({"status": "success"}, status=200) + else: + logger.error( + "Failed to configure video settings for event %s - Validation errors: %s.", + event_slug, + video_settings_form.errors, + ) + return Response( + { + "status": "error", + "message": "Validation errors", + "errors": video_settings_form.errors, + }, + status=400, + ) From 0a7f382eded52269e5cec307b58a94254f787b3a Mon Sep 17 00:00:00 2001 From: odkhang Date: Fri, 6 Dec 2024 17:45:23 +0700 Subject: [PATCH 11/31] Update code --- src/pretalx/api/views/event.py | 66 +++++++++++++++++----------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 51af1d6d0..f9be8e075 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -61,7 +61,9 @@ def configure_video_settings(request): raise ValueError("Video tokens not found in the payload") try: - save_video_settings_information(event_slug, video_tokens) + with scopes_disabled(): + event_instance = Event.objects.get(slug=event_slug) + save_video_settings_information(event_slug, video_tokens, event_instance) except Event.DoesNotExist: logger.error("Event with slug %s does not exist.", event_slug) return Response( @@ -119,37 +121,35 @@ def get_payload_from_token(request, video_settings): raise exceptions.AuthenticationFailedError("Invalid token") -def save_video_settings_information(event_slug, video_tokens): - with scopes_disabled(): - event_instance = Event.objects.get(slug=event_slug) - video_settings_data = { - "token": video_tokens[0], - "url": "{}/api/v1/worlds/{}/".format( - settings.EVENTYAY_VIDEO_BASE_PATH, event_slug - ), - } +def save_video_settings_information(event_slug, video_tokens, event_instance): + video_settings_data = { + "token": video_tokens[0], + "url": "{}/api/v1/worlds/{}/".format( + settings.EVENTYAY_VIDEO_BASE_PATH, event_slug + ), + } - video_settings_form = VenuelessSettingsForm( - event=event_instance, data=video_settings_data - ) + video_settings_form = VenuelessSettingsForm( + event=event_instance, data=video_settings_data + ) - if video_settings_form.is_valid(): - video_settings_form.save() - logger.info( - "Video settings configured successfully for event %s.", event_slug - ) - return Response({"status": "success"}, status=200) - else: - logger.error( - "Failed to configure video settings for event %s - Validation errors: %s.", - event_slug, - video_settings_form.errors, - ) - return Response( - { - "status": "error", - "message": "Validation errors", - "errors": video_settings_form.errors, - }, - status=400, - ) + if video_settings_form.is_valid(): + video_settings_form.save() + logger.info( + "Video settings configured successfully for event %s.", event_slug + ) + return Response({"status": "success"}, status=200) + else: + logger.error( + "Failed to configure video settings for event %s - Validation errors: %s.", + event_slug, + video_settings_form.errors, + ) + return Response( + { + "status": "error", + "message": "Validation errors", + "errors": video_settings_form.errors, + }, + status=400, + ) From 9cfb2f0a107a28ae69e9a74c2efba1fed27ea625 Mon Sep 17 00:00:00 2001 From: odkhang Date: Fri, 6 Dec 2024 17:47:08 +0700 Subject: [PATCH 12/31] Fix black in pipeline --- src/pretalx/api/views/event.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index f9be8e075..256f19812 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -135,9 +135,7 @@ def save_video_settings_information(event_slug, video_tokens, event_instance): if video_settings_form.is_valid(): video_settings_form.save() - logger.info( - "Video settings configured successfully for event %s.", event_slug - ) + logger.info("Video settings configured successfully for event %s.", event_slug) return Response({"status": "success"}, status=200) else: logger.error( From a340e3860e69ab38932176ef8edcb7ca3643ce04 Mon Sep 17 00:00:00 2001 From: odkhang Date: Fri, 6 Dec 2024 17:54:19 +0700 Subject: [PATCH 13/31] Add comment --- src/pretalx/api/views/event.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 256f19812..b04b4f39e 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -122,6 +122,13 @@ def get_payload_from_token(request, video_settings): def save_video_settings_information(event_slug, video_tokens, event_instance): + """ + Save video settings information + @param event_slug: A string representing the event slug + @param video_tokens: A list of video tokens + @param event_instance: An instance of the event + @return: Response object + """ video_settings_data = { "token": video_tokens[0], "url": "{}/api/v1/worlds/{}/".format( From 6dd84aeaaa0f0cfc4e74f201b03d95d158756ec9 Mon Sep 17 00:00:00 2001 From: odkhang Date: Mon, 9 Dec 2024 15:38:46 +0700 Subject: [PATCH 14/31] Update code --- src/pretalx/api/views/event.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index b04b4f39e..d03cef658 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -53,13 +53,17 @@ def configure_video_settings(request): @return response object """ video_settings = request.data.get("video_settings") + + if not video_settings or "secret" not in video_settings: + return Response( + {"status": "error", "message": "Invalid video settings."}, + status=400, + ) + payload = get_payload_from_token(request, video_settings) event_slug = payload.get("event_slug") video_tokens = payload.get("video_tokens") - if not video_tokens: - raise ValueError("Video tokens not found in the payload") - try: with scopes_disabled(): event_instance = Event.objects.get(slug=event_slug) @@ -129,6 +133,10 @@ def save_video_settings_information(event_slug, video_tokens, event_instance): @param event_instance: An instance of the event @return: Response object """ + + if not video_tokens: + raise ValueError("Video tokens list is empty") + video_settings_data = { "token": video_tokens[0], "url": "{}/api/v1/worlds/{}/".format( From 9fe119146037abe14824e1121a6c22afd758c446 Mon Sep 17 00:00:00 2001 From: odkhang Date: Mon, 9 Dec 2024 15:44:37 +0700 Subject: [PATCH 15/31] Update code --- src/pretalx/api/views/event.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index d03cef658..0a8fd255a 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -55,10 +55,7 @@ def configure_video_settings(request): video_settings = request.data.get("video_settings") if not video_settings or "secret" not in video_settings: - return Response( - {"status": "error", "message": "Invalid video settings."}, - status=400, - ) + raise ValueError("Video settings are missing or secret is not provided") payload = get_payload_from_token(request, video_settings) event_slug = payload.get("event_slug") From 463cd051a6c7dc4752d38eecf5d0a4b26e375054 Mon Sep 17 00:00:00 2001 From: odkhang Date: Mon, 9 Dec 2024 15:49:52 +0700 Subject: [PATCH 16/31] Update code --- src/pretalx/api/views/event.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 0a8fd255a..da6670a0c 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -52,16 +52,16 @@ def configure_video_settings(request): @param request: request object @return response object """ - video_settings = request.data.get("video_settings") + try: + video_settings = request.data.get("video_settings") - if not video_settings or "secret" not in video_settings: - raise ValueError("Video settings are missing or secret is not provided") + if not video_settings or "secret" not in video_settings: + raise ValueError("Video settings are missing or secret is not provided") - payload = get_payload_from_token(request, video_settings) - event_slug = payload.get("event_slug") - video_tokens = payload.get("video_tokens") + payload = get_payload_from_token(request, video_settings) + event_slug = payload.get("event_slug") + video_tokens = payload.get("video_tokens") - try: with scopes_disabled(): event_instance = Event.objects.get(slug=event_slug) save_video_settings_information(event_slug, video_tokens, event_instance) From 1d3617fd60677faf91a618ac33edeb9256b7d7b1 Mon Sep 17 00:00:00 2001 From: odkhang Date: Mon, 16 Dec 2024 09:41:09 +0700 Subject: [PATCH 17/31] using constant from http module instead of string --- src/pretalx/api/views/event.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index da6670a0c..c5b3634aa 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -1,4 +1,5 @@ import logging +from http import HTTPMethod import jwt from django.conf import settings @@ -43,7 +44,7 @@ def get_object(self): raise Http404() -@api_view(http_method_names=["POST"]) +@api_view(http_method_names=[HTTPMethod.POST]) @authentication_classes([]) @permission_classes([]) def configure_video_settings(request): From b2a9bd37df49f135d978767386200adebdd24776 Mon Sep 17 00:00:00 2001 From: odkhang Date: Mon, 16 Dec 2024 09:46:01 +0700 Subject: [PATCH 18/31] using constant from http, using httpstatus --- src/pretalx/api/views/event.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index c5b3634aa..b2ed5178d 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -1,5 +1,5 @@ import logging -from http import HTTPMethod +from http import HTTPMethod, HTTPStatus import jwt from django.conf import settings @@ -73,18 +73,19 @@ def configure_video_settings(request): "status": "error", "message": "Event with slug {} not found.".format(event_slug), }, - status=404, + status=HTTPStatus.NOT_FOUND, ) except ValueError as e: logger.error("Error configuring video settings: %s", e) return Response( {"status": "error", "message": "Error configuring video settings."}, - status=400, + status=HTTPStatus.BAD_REQUEST, ) except AuthenticationFailedError as e: logger.error("Authentication failed: %s", e) return Response( - {"status": "error", "message": "Authentication failed."}, status=401 + {"status": "error", "message": "Authentication failed."}, + status=HTTPStatus.UNAUTHORIZED ) From 7bcca212ca8ba7d2336de145d20890c00947da8d Mon Sep 17 00:00:00 2001 From: odkhang Date: Mon, 16 Dec 2024 10:03:47 +0700 Subject: [PATCH 19/31] No need to bother with this outside of CI. --- .../agenda/test_agenda_schedule_export.py | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/src/tests/agenda/test_agenda_schedule_export.py b/src/tests/agenda/test_agenda_schedule_export.py index 5b7c9c38d..3ef2f97c0 100644 --- a/src/tests/agenda/test_agenda_schedule_export.py +++ b/src/tests/agenda/test_agenda_schedule_export.py @@ -39,27 +39,6 @@ def test_schedule_xsd_is_up_to_date(): assert response.data.decode() == schema_content -@pytest.mark.skipif( - "CI" not in os.environ or not os.environ["CI"], - reason="No need to bother with this outside of CI.", -) -def test_schedule_json_schema_is_up_to_date(): - """If this test fails: - - http -d https://raw.githubusercontent.com/voc/schedule/master/validator/json/schema.json >! tests/fixtures/schedule.json - """ - http = urllib3.PoolManager() - response = http.request( - "GET", - "https://raw.githubusercontent.com/voc/schedule/master/validator/json/schema.json", - ) - assert response.status == 200 - path = Path(__file__).parent / "../fixtures/schedule.json" - with open(path) as schema: - schema_content = schema.read() - assert response.data.decode() == schema_content - - @pytest.mark.django_db def test_schedule_frab_xml_export( slot, From bc5a53a3fe59840f9bd4c2b1d8487decc2ab8b74 Mon Sep 17 00:00:00 2001 From: odkhang Date: Mon, 16 Dec 2024 11:42:43 +0700 Subject: [PATCH 20/31] fix black code style --- src/pretalx/api/views/event.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index b2ed5178d..8ffa3fa26 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -85,7 +85,7 @@ def configure_video_settings(request): logger.error("Authentication failed: %s", e) return Response( {"status": "error", "message": "Authentication failed."}, - status=HTTPStatus.UNAUTHORIZED + status=HTTPStatus.UNAUTHORIZED, ) From 60df6212b6ad670c50e05c18cecd1783da2a28ad Mon Sep 17 00:00:00 2001 From: odkhang Date: Tue, 17 Dec 2024 10:59:11 +0700 Subject: [PATCH 21/31] rework code --- src/pretalx/api/urls.py | 2 +- src/pretalx/api/views/event.py | 98 +++++++++++++++++++--------------- 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/pretalx/api/urls.py b/src/pretalx/api/urls.py index ebbb1c79f..ed3731071 100644 --- a/src/pretalx/api/urls.py +++ b/src/pretalx/api/urls.py @@ -30,5 +30,5 @@ "events//favourite-talk/", submission.SubmissionFavouriteDeprecatedView.as_view(), ), - path("configure-video-settings/", event.configure_video_settings), + path("configure-video-settings/", event.ConfigureVideoSettingsView.as_view()), ] diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 8ffa3fa26..f4fc272b1 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -13,7 +13,10 @@ authentication_classes, permission_classes, ) +from rest_framework.exceptions import AuthenticationFailed +from rest_framework.permissions import AllowAny from rest_framework.response import Response +from rest_framework.views import APIView from pretalx.api.serializers.event import EventSerializer from pretalx.common import exceptions @@ -44,49 +47,60 @@ def get_object(self): raise Http404() -@api_view(http_method_names=[HTTPMethod.POST]) -@authentication_classes([]) -@permission_classes([]) -def configure_video_settings(request): +class ConfigureVideoSettingsView(APIView): """ - Configure video settings for an event - @param request: request object - @return response object + API View to configure video settings for an event. """ - try: - video_settings = request.data.get("video_settings") - - if not video_settings or "secret" not in video_settings: - raise ValueError("Video settings are missing or secret is not provided") - payload = get_payload_from_token(request, video_settings) - event_slug = payload.get("event_slug") - video_tokens = payload.get("video_tokens") - - with scopes_disabled(): - event_instance = Event.objects.get(slug=event_slug) - save_video_settings_information(event_slug, video_tokens, event_instance) - except Event.DoesNotExist: - logger.error("Event with slug %s does not exist.", event_slug) - return Response( - { - "status": "error", - "message": "Event with slug {} not found.".format(event_slug), - }, - status=HTTPStatus.NOT_FOUND, - ) - except ValueError as e: - logger.error("Error configuring video settings: %s", e) - return Response( - {"status": "error", "message": "Error configuring video settings."}, - status=HTTPStatus.BAD_REQUEST, - ) - except AuthenticationFailedError as e: - logger.error("Authentication failed: %s", e) - return Response( - {"status": "error", "message": "Authentication failed."}, - status=HTTPStatus.UNAUTHORIZED, - ) + authentication_classes = [] + permission_classes = [AllowAny] + + def post(self, request, *args, **kwargs): + """ + Handle POST request to configure video settings. + @param request: request object + @return response object + """ + try: + video_settings = request.data.get("video_settings") + if not video_settings or "secret" not in video_settings: + raise ValueError("Video settings are missing or secret is not provided") + payload = get_payload_from_token(request, video_settings) + event_slug = payload.get("event_slug") + video_tokens = payload.get("video_tokens") + with scopes_disabled(): + event_instance = Event.objects.get(slug=event_slug) + save_video_settings_information( + event_slug, video_tokens, event_instance + ) + return Response( + { + "status": "success", + "message": "Video settings configured successfully.", + }, + status=HTTPStatus.OK, + ) + except Event.DoesNotExist: + logger.error("Event with slug %s does not exist.", event_slug) + return Response( + { + "status": "error", + "message": f"Event with slug {event_slug} not found.", + }, + status=HTTPStatus.NOT_FOUND, + ) + except ValueError as e: + logger.error("Error configuring video settings: %s", e) + return Response( + {"status": "error", "message": str(e)}, + status=HTTPStatus.BAD_REQUEST, + ) + except AuthenticationFailed as e: + logger.error("Authentication failed: %s", e) + return Response( + {"status": "error", "message": "Authentication failed."}, + status=HTTPStatus.UNAUTHORIZED, + ) def get_payload_from_token(request, video_settings): @@ -150,7 +164,7 @@ def save_video_settings_information(event_slug, video_tokens, event_instance): if video_settings_form.is_valid(): video_settings_form.save() logger.info("Video settings configured successfully for event %s.", event_slug) - return Response({"status": "success"}, status=200) + return Response({"status": "success"}, status=HTTPStatus.OK) else: logger.error( "Failed to configure video settings for event %s - Validation errors: %s.", @@ -163,5 +177,5 @@ def save_video_settings_information(event_slug, video_tokens, event_instance): "message": "Validation errors", "errors": video_settings_form.errors, }, - status=400, + status=HTTPStatus.BAD_REQUEST, ) From 68f221f0a095e42c63f32c8afe7bdfb7eed1d4dd Mon Sep 17 00:00:00 2001 From: odkhang Date: Tue, 17 Dec 2024 11:27:32 +0700 Subject: [PATCH 22/31] fix code style, remove unused import --- src/pretalx/api/views/event.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index f4fc272b1..6c098e06a 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -1,5 +1,5 @@ import logging -from http import HTTPMethod, HTTPStatus +from http import HTTPStatus import jwt from django.conf import settings @@ -8,11 +8,6 @@ from pretalx_venueless.forms import VenuelessSettingsForm from rest_framework import viewsets from rest_framework.authentication import get_authorization_header -from rest_framework.decorators import ( - api_view, - authentication_classes, - permission_classes, -) from rest_framework.exceptions import AuthenticationFailed from rest_framework.permissions import AllowAny from rest_framework.response import Response @@ -20,7 +15,6 @@ from pretalx.api.serializers.event import EventSerializer from pretalx.common import exceptions -from pretalx.common.exceptions import AuthenticationFailedError from pretalx.event.models import Event logger = logging.getLogger(__name__) From bea82c0b024d2b85fc5b12f6b9adc2f5497cdaf1 Mon Sep 17 00:00:00 2001 From: odkhang Date: Wed, 18 Dec 2024 17:40:18 +0700 Subject: [PATCH 23/31] fix inconsistence for API response --- src/pretalx/api/views/event.py | 31 +++++++++++-------------------- src/pretalx/common/exceptions.py | 4 ++++ 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 6c098e06a..6aa08eaac 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -3,7 +3,7 @@ import jwt from django.conf import settings -from django.http import Http404 +from django.http import Http404, HttpResponseServerError from django_scopes import scopes_disabled from pretalx_venueless.forms import VenuelessSettingsForm from rest_framework import viewsets @@ -15,6 +15,7 @@ from pretalx.api.serializers.event import EventSerializer from pretalx.common import exceptions +from pretalx.common.exceptions import VideoIntegrationError from pretalx.event.models import Event logger = logging.getLogger(__name__) @@ -58,7 +59,8 @@ def post(self, request, *args, **kwargs): try: video_settings = request.data.get("video_settings") if not video_settings or "secret" not in video_settings: - raise ValueError("Video settings are missing or secret is not provided") + raise VideoIntegrationError( + "Video settings are missing or secret is not provided") payload = get_payload_from_token(request, video_settings) event_slug = payload.get("event_slug") video_tokens = payload.get("video_tokens") @@ -75,26 +77,15 @@ def post(self, request, *args, **kwargs): status=HTTPStatus.OK, ) except Event.DoesNotExist: - logger.error("Event with slug %s does not exist.", event_slug) - return Response( - { - "status": "error", - "message": f"Event with slug {event_slug} not found.", - }, - status=HTTPStatus.NOT_FOUND, - ) - except ValueError as e: + logger.error("Event does not exist.") + raise Http404("Event does not exist") + except VideoIntegrationError as e: logger.error("Error configuring video settings: %s", e) - return Response( - {"status": "error", "message": str(e)}, - status=HTTPStatus.BAD_REQUEST, - ) + return HttpResponseServerError( + "Video settings are missing or secret is not provided", status=HTTPStatus.SERVICE_UNAVAILABLE) except AuthenticationFailed as e: logger.error("Authentication failed: %s", e) - return Response( - {"status": "error", "message": "Authentication failed."}, - status=HTTPStatus.UNAUTHORIZED, - ) + raise AuthenticationFailed("Authentication failed.") def get_payload_from_token(request, video_settings): @@ -142,7 +133,7 @@ def save_video_settings_information(event_slug, video_tokens, event_instance): """ if not video_tokens: - raise ValueError("Video tokens list is empty") + raise VideoIntegrationError("Video tokens list is empty") video_settings_data = { "token": video_tokens[0], diff --git a/src/pretalx/common/exceptions.py b/src/pretalx/common/exceptions.py index 1d0f1c591..b2bad57f8 100644 --- a/src/pretalx/common/exceptions.py +++ b/src/pretalx/common/exceptions.py @@ -15,6 +15,10 @@ class AuthenticationFailedError(Exception): pass +class VideoIntegrationError(Exception): + pass + + class PretalxExceptionReporter(ExceptionReporter): def get_traceback_text(self): # pragma: no cover traceback_text = super().get_traceback_text() From a845cf4b1d4bb6b1bfb7e2a32b600529a6169587 Mon Sep 17 00:00:00 2001 From: odkhang Date: Wed, 18 Dec 2024 17:42:44 +0700 Subject: [PATCH 24/31] format code --- src/pretalx/api/views/event.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 6aa08eaac..df542a3ff 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -82,7 +82,8 @@ def post(self, request, *args, **kwargs): except VideoIntegrationError as e: logger.error("Error configuring video settings: %s", e) return HttpResponseServerError( - "Video settings are missing or secret is not provided", status=HTTPStatus.SERVICE_UNAVAILABLE) + "Video settings are missing or secret is not provided", + status=HTTPStatus.SERVICE_UNAVAILABLE) except AuthenticationFailed as e: logger.error("Authentication failed: %s", e) raise AuthenticationFailed("Authentication failed.") From 3eb6d1767b4600af05d394f10cc76989d3abe585 Mon Sep 17 00:00:00 2001 From: odkhang Date: Wed, 18 Dec 2024 18:03:55 +0700 Subject: [PATCH 25/31] handle case input form invalid --- src/pretalx/api/views/event.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index df542a3ff..f88b17390 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -3,7 +3,8 @@ import jwt from django.conf import settings -from django.http import Http404, HttpResponseServerError +from django.core.exceptions import ValidationError +from django.http import Http404, HttpResponseServerError, HttpResponseBadRequest from django_scopes import scopes_disabled from pretalx_venueless.forms import VenuelessSettingsForm from rest_framework import viewsets @@ -79,6 +80,11 @@ def post(self, request, *args, **kwargs): except Event.DoesNotExist: logger.error("Event does not exist.") raise Http404("Event does not exist") + except ValidationError as e: + logger.error("Validation error: %s", e) + return HttpResponseBadRequest( + "Failed to configure video settings - Validation errors: %s." % e, + status=HTTPStatus.BAD_REQUEST) except VideoIntegrationError as e: logger.error("Error configuring video settings: %s", e) return HttpResponseServerError( @@ -150,18 +156,13 @@ def save_video_settings_information(event_slug, video_tokens, event_instance): if video_settings_form.is_valid(): video_settings_form.save() logger.info("Video settings configured successfully for event %s.", event_slug) - return Response({"status": "success"}, status=HTTPStatus.OK) else: logger.error( "Failed to configure video settings for event %s - Validation errors: %s.", event_slug, video_settings_form.errors, ) - return Response( - { - "status": "error", - "message": "Validation errors", - "errors": video_settings_form.errors, - }, - status=HTTPStatus.BAD_REQUEST, + raise ValidationError( + "Failed to configure video settings for event %s - Validation errors: %s." % ( + event_slug, video_settings_form.errors) ) From a3ef9fcfda526d378060d11565bd092677e1199e Mon Sep 17 00:00:00 2001 From: odkhang Date: Wed, 18 Dec 2024 18:07:14 +0700 Subject: [PATCH 26/31] fix isort, black code style --- src/pretalx/api/views/event.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index f88b17390..6c3536d7c 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -4,7 +4,7 @@ import jwt from django.conf import settings from django.core.exceptions import ValidationError -from django.http import Http404, HttpResponseServerError, HttpResponseBadRequest +from django.http import Http404, HttpResponseBadRequest, HttpResponseServerError from django_scopes import scopes_disabled from pretalx_venueless.forms import VenuelessSettingsForm from rest_framework import viewsets @@ -61,7 +61,8 @@ def post(self, request, *args, **kwargs): video_settings = request.data.get("video_settings") if not video_settings or "secret" not in video_settings: raise VideoIntegrationError( - "Video settings are missing or secret is not provided") + "Video settings are missing or secret is not provided" + ) payload = get_payload_from_token(request, video_settings) event_slug = payload.get("event_slug") video_tokens = payload.get("video_tokens") @@ -84,12 +85,14 @@ def post(self, request, *args, **kwargs): logger.error("Validation error: %s", e) return HttpResponseBadRequest( "Failed to configure video settings - Validation errors: %s." % e, - status=HTTPStatus.BAD_REQUEST) + status=HTTPStatus.BAD_REQUEST, + ) except VideoIntegrationError as e: logger.error("Error configuring video settings: %s", e) return HttpResponseServerError( "Video settings are missing or secret is not provided", - status=HTTPStatus.SERVICE_UNAVAILABLE) + status=HTTPStatus.SERVICE_UNAVAILABLE, + ) except AuthenticationFailed as e: logger.error("Authentication failed: %s", e) raise AuthenticationFailed("Authentication failed.") @@ -163,6 +166,6 @@ def save_video_settings_information(event_slug, video_tokens, event_instance): video_settings_form.errors, ) raise ValidationError( - "Failed to configure video settings for event %s - Validation errors: %s." % ( - event_slug, video_settings_form.errors) + "Failed to configure video settings for event %s - Validation errors: %s." + % (event_slug, video_settings_form.errors) ) From d98fbde587c241107036780808b84036319c436e Mon Sep 17 00:00:00 2001 From: odkhang Date: Wed, 18 Dec 2024 18:17:24 +0700 Subject: [PATCH 27/31] fix isort, black code style --- src/pretalx/api/views/event.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 6c3536d7c..b8b4d4d9f 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -83,10 +83,7 @@ def post(self, request, *args, **kwargs): raise Http404("Event does not exist") except ValidationError as e: logger.error("Validation error: %s", e) - return HttpResponseBadRequest( - "Failed to configure video settings - Validation errors: %s." % e, - status=HTTPStatus.BAD_REQUEST, - ) + return HttpResponseBadRequest(e, status=HTTPStatus.BAD_REQUEST) except VideoIntegrationError as e: logger.error("Error configuring video settings: %s", e) return HttpResponseServerError( @@ -165,7 +162,4 @@ def save_video_settings_information(event_slug, video_tokens, event_instance): event_slug, video_settings_form.errors, ) - raise ValidationError( - "Failed to configure video settings for event %s - Validation errors: %s." - % (event_slug, video_settings_form.errors) - ) + raise ValidationError("Validation errors: %s " % video_settings_form.errors) From 7947d318a289618859f4ac1b0c0ee0f154819329 Mon Sep 17 00:00:00 2001 From: odkhang Date: Thu, 19 Dec 2024 17:49:26 +0700 Subject: [PATCH 28/31] re format API response for case validation error --- src/pretalx/api/views/event.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index b8b4d4d9f..135adbec6 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -82,14 +82,12 @@ def post(self, request, *args, **kwargs): logger.error("Event does not exist.") raise Http404("Event does not exist") except ValidationError as e: - logger.error("Validation error: %s", e) - return HttpResponseBadRequest(e, status=HTTPStatus.BAD_REQUEST) + return Response({"detail": str(e)}, status=HTTPStatus.BAD_REQUEST) except VideoIntegrationError as e: logger.error("Error configuring video settings: %s", e) - return HttpResponseServerError( - "Video settings are missing or secret is not provided", - status=HTTPStatus.SERVICE_UNAVAILABLE, - ) + return Response( + {"detail": "Video settings are missing, please try after sometime."}, + status=HTTPStatus.SERVICE_UNAVAILABLE) except AuthenticationFailed as e: logger.error("Authentication failed: %s", e) raise AuthenticationFailed("Authentication failed.") @@ -162,4 +160,4 @@ def save_video_settings_information(event_slug, video_tokens, event_instance): event_slug, video_settings_form.errors, ) - raise ValidationError("Validation errors: %s " % video_settings_form.errors) + raise ValidationError(video_settings_form.errors.get_json_data()) From 1b6ce53798d206c8265a8722d3a72ab59ca45970 Mon Sep 17 00:00:00 2001 From: odkhang Date: Thu, 19 Dec 2024 17:52:44 +0700 Subject: [PATCH 29/31] fix pipeline --- src/pretalx/api/views/event.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index 135adbec6..bb0517af9 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -4,7 +4,7 @@ import jwt from django.conf import settings from django.core.exceptions import ValidationError -from django.http import Http404, HttpResponseBadRequest, HttpResponseServerError +from django.http import Http404 from django_scopes import scopes_disabled from pretalx_venueless.forms import VenuelessSettingsForm from rest_framework import viewsets @@ -87,7 +87,8 @@ def post(self, request, *args, **kwargs): logger.error("Error configuring video settings: %s", e) return Response( {"detail": "Video settings are missing, please try after sometime."}, - status=HTTPStatus.SERVICE_UNAVAILABLE) + status=HTTPStatus.SERVICE_UNAVAILABLE, + ) except AuthenticationFailed as e: logger.error("Authentication failed: %s", e) raise AuthenticationFailed("Authentication failed.") From 99717c94aed8f20a69a9ba28135b08e9632eef7e Mon Sep 17 00:00:00 2001 From: odkhang Date: Thu, 19 Dec 2024 18:51:49 +0700 Subject: [PATCH 30/31] make error message more clear for validation error --- src/pretalx/api/views/event.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index bb0517af9..ec98e6b39 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -156,9 +156,12 @@ def save_video_settings_information(event_slug, video_tokens, event_instance): video_settings_form.save() logger.info("Video settings configured successfully for event %s.", event_slug) else: + errors = video_settings_form.errors.get_json_data() + formatted_errors = {field: [error['message'] for error in error_list] for + field, error_list in errors.items()} logger.error( "Failed to configure video settings for event %s - Validation errors: %s.", event_slug, - video_settings_form.errors, + formatted_errors, ) - raise ValidationError(video_settings_form.errors.get_json_data()) + raise ValidationError(formatted_errors) From f28ab8e15737f61499035302f3e6f4bfad3f35af Mon Sep 17 00:00:00 2001 From: odkhang Date: Thu, 19 Dec 2024 18:54:28 +0700 Subject: [PATCH 31/31] coding style fix --- src/pretalx/api/views/event.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pretalx/api/views/event.py b/src/pretalx/api/views/event.py index ec98e6b39..550b67874 100644 --- a/src/pretalx/api/views/event.py +++ b/src/pretalx/api/views/event.py @@ -157,8 +157,10 @@ def save_video_settings_information(event_slug, video_tokens, event_instance): logger.info("Video settings configured successfully for event %s.", event_slug) else: errors = video_settings_form.errors.get_json_data() - formatted_errors = {field: [error['message'] for error in error_list] for - field, error_list in errors.items()} + formatted_errors = { + field: [error["message"] for error in error_list] + for field, error_list in errors.items() + } logger.error( "Failed to configure video settings for event %s - Validation errors: %s.", event_slug,