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

Eventyay-Common: Add option to create video access to the event #385

Merged
merged 13 commits into from
Nov 1, 2024

Conversation

odkhang
Copy link
Collaborator

@odkhang odkhang commented Oct 10, 2024

This PR related to issue #358 Eventyay-Common: Add option to create video access to the event
Implement a checkbox in Event create/edit page, if it checked, will trigger API call to Eventyay-video to create World/Event in video.

Summary by Sourcery

Add functionality to create a video platform for events by introducing a new checkbox in the event creation and editing forms. Implement a background task to handle the video system creation when the option is selected, and update the project settings to include a video server hostname configuration.

New Features:

  • Introduce an option to create a video platform for events by adding a checkbox in the event creation and editing forms.

Enhancements:

  • Implement a task to handle the creation of a video system for events when the video option is selected.

Build:

  • Add a new configuration setting for the video server hostname in the project settings.

Copy link

sourcery-ai bot commented Oct 10, 2024

Reviewer's Guide by Sourcery

This pull request implements a new feature to add an option for creating video access to events in the Eventyay-Common system. The changes include adding a checkbox in the event creation and edit pages, which triggers an API call to Eventyay-video to create a World/Event in video when checked. The implementation involves modifications to several files, including new functions, form fields, model changes, and UI updates.

Sequence diagram for creating video access during event creation

sequenceDiagram
    actor User
    participant EventForm
    participant Backend
    participant VideoAPI
    User->>EventForm: Fill event details and check 'Create Video'
    EventForm->>Backend: Submit event creation form
    Backend->>Backend: Check create permission
    alt User has permission
        Backend->>VideoAPI: POST /api/v1/create-world/
        VideoAPI-->>Backend: Video world created
    else User lacks permission
        Backend-->>User: Permission denied
    end
Loading

User journey diagram for event creation with video access

journey
    title Event Creation with Video Access
    section Event Creation
      Fill Event Details: 5: User
      Check 'Create Video' Option: 4: User
      Submit Form: 5: User
    section Backend Processing
      Validate Permissions: 4: System
      Create Event: 5: System
      Create Video World: 3: System
    section Confirmation
      Display Success Message: 5: System
      Redirect to Event List: 4: System
Loading

Class diagram for Event model changes

classDiagram
    class Event {
        +Boolean is_video_create
        +add_video_call()
    }
Loading

File-Level Changes

Change Details Files
Implement video creation functionality
  • Add a new shared task 'create_world' to handle video system creation
  • Implement logic to check user permissions for video creation
  • Add API call to create video world with error handling and retries
src/pretix/eventyay_common/tasks.py
Update event creation and editing process
  • Add 'is_video_create' field to event model and forms
  • Implement logic to handle video creation during event creation and editing
  • Update form validation and saving process to include video creation option
src/pretix/eventyay_common/views/event.py
src/pretix/control/forms/event.py
src/pretix/base/models/event.py
Add UI elements for video creation option
  • Add checkbox for video creation in event creation and settings pages
  • Update templates to display new video creation option
src/pretix/eventyay_common/templates/eventyay_common/event/settings.html
src/pretix/eventyay_common/templates/eventyay_common/events/create_foundation.html
Implement utility functions for video creation
  • Add functions to generate tokens for video system
  • Implement permission checking for video creation
  • Create utility for encoding user email
src/pretix/eventyay_common/utils.py
Update configuration and database schema
  • Add VIDEO_SERVER_HOSTNAME configuration
  • Create database migration for new 'is_video_create' field
src/pretix/settings.py
src/pretix/base/migrations/0005_event_add_video.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time. You can also use
    this command to specify where the summary should be inserted.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @odkhang - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider extracting the is_video_create logic into a separate method to reduce duplication between event creation and update views.
  • In the create_world task, consider using more specific exception handling instead of catching the generic RequestException.
  • For improved security, consider using a separate secret key for JWT encoding in the generate_token function, rather than settings.SECRET_KEY.
Here's what I looked at during the review
  • 🟡 General issues: 2 issues found
  • 🟡 Security: 1 issue found
  • 🟢 Testing: all looks good
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@@ -103,6 +103,48 @@ def send_event_webhook(self, user_id, event, action):
except self.MaxRetriesExceededError:
logger.error("Max retries exceeded for sending organizer webhook.")

@shared_task(bind=True, max_retries=5, default_retry_delay=60) # Retries up to 5 times with a 60-second delay
def create_world(self, is_video_create, data):
Copy link

Choose a reason for hiding this comment

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

suggestion: Consider improving error handling in create_world function

While the function catches and logs exceptions, it might be beneficial to add more specific error handling for different types of request exceptions. This could help in diagnosing and addressing specific issues more effectively.

def create_world(self, is_video_create, data):
    try:
        # Existing function logic here
    except requests.exceptions.ConnectionError as e:
        logger.error(f"Connection error: {e}")
        raise self.retry(exc=e)
    except requests.exceptions.Timeout as e:
        logger.error(f"Request timed out: {e}")
        raise self.retry(exc=e)
    except requests.exceptions.RequestException as e:
        logger.error(f"Request failed: {e}")
        raise self.retry(exc=e)

logger = logging.getLogger(__name__)


def generate_token(request):
Copy link

Choose a reason for hiding this comment

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

🚨 suggestion (security): Reconsider token generation method for improved security

The current token generation method uses a simple SHA256 hash of the email, which might not be sufficiently secure. Consider using a more robust method, such as a cryptographically secure random number generator, to create these tokens.

import secrets

def generate_token(request):
    """
    Generate secure token for video system
    """
    return secrets.token_urlsafe(32)

timezone=basics_data.get('timezone'),
locale=basics_data.get('locale'), has_permission=check_create_permission(self.request),
token=generate_token(self.request))
create_world.delay(is_video_create=foundation_data.get('is_video_create'), data=data)
Copy link

Choose a reason for hiding this comment

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

suggestion (bug_risk): Implement safeguard against duplicate world creation

The create_world task is called in both the done and form_valid methods. Consider adding a check to prevent duplicate world creation if a world already exists for this event.

Suggested change
create_world.delay(is_video_create=foundation_data.get('is_video_create'), data=data)
if not World.objects.filter(event_id=data['event_id']).exists():
create_world.delay(is_video_create=foundation_data.get('is_video_create'), data=data)
else:
messages.warning(self.request, _("A world for this event already exists."))

@@ -248,6 +263,21 @@
self.sform.save()

tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk})

if check_create_permission(self.request):
Copy link

Choose a reason for hiding this comment

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

issue (complexity): Consider extracting video creation logic into separate methods for improved modularity.

The done and form_valid methods have become more complex with the addition of video creation logic. To improve readability and maintainability, consider extracting the video creation related code into a separate method. This will make the code more modular while maintaining the new functionality. Here's an example of how you could refactor the form_valid method:

class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequiredMixin, MetaDataEditorMixin, UpdateView):
    # ... existing code ...

    @transaction.atomic
    def form_valid(self, form):
        self._save_decoupled(self.sform)
        self.sform.save()

        tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk})

        self._handle_video_creation(form)

        messages.success(self.request, _('Your changes have been saved.'))
        return super().form_valid(form)

    def _handle_video_creation(self, form):
        if check_create_permission(self.request):
            form.instance.is_video_create = form.cleaned_data.get('is_video_create')
        elif not check_create_permission(self.request) and form.cleaned_data.get('is_video_create'):
            form.instance.is_video_create = True
        else:
            form.instance.is_video_create = False

        data = dict(id=form.cleaned_data.get('slug'), title=form.cleaned_data.get('name').data,
                    timezone=self.sform.cleaned_data.get('timezone'), locale=self.sform.cleaned_data.get('locale'),
                    has_permission=check_create_permission(self.request), token=generate_token(self.request))

        create_world.delay(is_video_create=form.cleaned_data.get('is_video_create'), data=data)

This refactoring extracts the video creation logic into a separate _handle_video_creation method, making the form_valid method cleaner and easier to understand. You can apply a similar approach to the done method in the wizard view. This change improves the separation of concerns without introducing unnecessary complexity.

try:
requests.post(
"{}/api/v1/create-world/".format(settings.VIDEO_SERVER_HOSTNAME),
json= payload,
Copy link
Member

Choose a reason for hiding this comment

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

Why space after "="?

src/pretix/base/models/event.py Outdated Show resolved Hide resolved
@param request: user request
@return: jwt
"""
uid_token = encode_email(request.user.email)
Copy link
Member

Choose a reason for hiding this comment

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

The uid_token seems not to carry any info for client side to extract. If so, please use a short method with secrets module to generate it, as @sourcery-ai suggested.

Copy link
Member

Choose a reason for hiding this comment

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

Why do you still have to create uid_token in a very complex way?

@odkhang odkhang requested a review from hongquan October 29, 2024 07:48
@mariobehling
Copy link
Member

@odkhang Postgres tests are failing after merged dev branch here. Please check. Thank you

@lcduong
Copy link
Contributor

lcduong commented Oct 29, 2024

@odkhang Postgres tests are failing after merged dev branch here. Please check. Thank you

Hi @mariobehling, tests are passed

@param request: user request
@return: jwt
"""
uid_token = encode_email(request.user.email)
Copy link
Member

Choose a reason for hiding this comment

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

Why do you still have to create uid_token in a very complex way?

src/pretix/eventyay_common/tasks.py Show resolved Hide resolved
@odkhang odkhang requested a review from hongquan October 30, 2024 09:50
@mariobehling mariobehling merged commit ce24ea2 into fossasia:development Nov 1, 2024
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants