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

Sync customer data from ticket component #174

Merged
merged 1 commit into from
Aug 6, 2024

Conversation

lcduong
Copy link
Contributor

@lcduong lcduong commented Aug 6, 2024

This PR closes/references issue #166 . It does so by

  • Implement a script to sync customer from ticket component
  • to execute script: python manage.py sync_customer_account

image

input data:

  • Ticket organizer must be same short name with organizer from talk. e.g: wikiorg
  • url of ticket component, e.g: https://wikimania-tickets.eventyay.com/
  • ticket token: generate it under Team ogranizer setting

image

How it work:

  1. Get all customer account under organizer provided above from ticket component
  2. Check if customer email existed in talk yet or not.
  • if customer email already created -> do nothing
  • If customer email not existed -> create a user with that email and set unusable password.
  • After that, customer add favorite session without login talk, when user first time login talk with SSO, list favorite sessions will be there.

How has this been tested?

Checklist

  • I have added tests to cover my changes.

Summary by Sourcery

Add a management command to sync customer accounts from the Eventyay ticket component to the talk component, creating new user accounts if they do not already exist.

New Features:

  • Implement a script to sync customer data from the ticket component to the talk component.

Copy link

sourcery-ai bot commented Aug 6, 2024

Reviewer's Guide by Sourcery

This pull request introduces a new management command script to sync customer accounts from the Eventyay ticket component. The script retrieves customer data via an API, checks if the customer email already exists in the local database, and creates new user accounts with unusable passwords if they do not exist. The new users are also associated with a SocialAccount linked to the ticket organizer. The script includes error handling for missing organizers, failed API requests, and user creation issues.

File-Level Changes

Files Changes
src/pretalx/common/management/commands/sync_customer_account.py Introduced a new management command to sync customer accounts from the Eventyay ticket component, including argument parsing, API requests, and user creation with error handling.

Tips
  • Trigger a new Sourcery review by commenting @sourcery-ai review on the pull request.
  • Continue your discussion with Sourcery by replying directly to review comments.
  • You can change your review settings at any time by accessing your dashboard:
    • Enable or disable the Sourcery-generated pull request summary or reviewer's guide;
    • Change the review language;
  • You can always contact us if you have any questions or feedback.

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 @lcduong - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider using environment variables or a secure configuration method for sensitive data like tokens instead of using input(). This will improve security and make the script more suitable for production use.
  • Improve error handling by catching specific exceptions and providing more detailed error messages. This will make troubleshooting easier in case of failures.
Here's what I looked at during the review
  • 🟡 General issues: 3 issues found
  • 🟡 Security: 1 issue found
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 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 to tell me if it was helpful.

Comment on lines +22 to +26
try:
Organiser.objects.get(slug=organizer_slug)
except Organiser.DoesNotExist:
self.stderr.write(self.style.ERROR('Organizer not found.'))
return
Copy link

Choose a reason for hiding this comment

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

suggestion: Consider using more specific exception handling

Catching all exceptions might hide important errors. Consider catching and handling specific exceptions (e.g., requests.RequestException) to provide more informative error messages and potentially handle different error scenarios differently.

Suggested change
try:
Organiser.objects.get(slug=organizer_slug)
except Organiser.DoesNotExist:
self.stderr.write(self.style.ERROR('Organizer not found.'))
return
try:
Organiser.objects.get(slug=organizer_slug)
except Organiser.DoesNotExist:
self.stderr.write(self.style.ERROR('Organizer not found.'))
return
except Organiser.MultipleObjectsReturned:
self.stderr.write(self.style.ERROR('Multiple organizers found with the same slug.'))
return

parser.add_argument('--ticket-url', type=str, help='Ticket Url')
parser.add_argument('--ticket-token', type=str, help='Ticket token')

def handle(self, *args, **options):
Copy link

Choose a reason for hiding this comment

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

suggestion: Refactor the handle method for better separation of concerns

The handle method is currently responsible for argument handling, API requests, and database operations. Consider breaking these responsibilities into separate methods for improved readability and maintainability.

    def handle(self, *args, **options):
        self.get_input_data(options)
        self.make_api_request()
        self.update_database()

    def get_input_data(self, options):
        self.organizer_slug = options.get('ticket-organizer-slug') or input('Enter Ticket Organizer Slug: ')
        self.ticket_url = options.get('ticket-url') or input('Enter Ticket Url: ')

    def make_api_request(self):
        # API request logic here

    def update_database(self):
        # Database update logic here

except Organiser.DoesNotExist:
self.stderr.write(self.style.ERROR('Organizer not found.'))
return
url = f'{ticket_url}/api/v1/organizers/{organizer_slug}/customers/'
Copy link

Choose a reason for hiding this comment

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

🚨 suggestion (security): Use urljoin for safer URL construction

Directly inserting user input into URLs can lead to security vulnerabilities. Consider using urllib.parse.urljoin() or a similar method to construct URLs safely.

Suggested change
url = f'{ticket_url}/api/v1/organizers/{organizer_slug}/customers/'
from urllib.parse import urljoin
url = urljoin(ticket_url, f'api/v1/organizers/{organizer_slug}/customers/')

Comment on lines +55 to +57
except Exception as e:
self.stderr.write(self.style.ERROR('Error when creating customer: ' + customer['email']))
continue
Copy link

Choose a reason for hiding this comment

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

suggestion: Improve error handling when creating customers

The current error handling silently continues on any exception. Consider logging the specific error (e.g., str(e)) for easier debugging. Also, you might want to handle specific exceptions differently based on their type.

            except Exception as e:
                error_message = f"Error when creating customer {customer['email']}: {str(e)}"
                self.stderr.write(self.style.ERROR(error_message))
                logger.error(error_message)
                if isinstance(e, IntegrityError):
                    self.stderr.write(self.style.WARNING("Customer may already exist. Skipping."))
                elif isinstance(e, ValidationError):
                    self.stderr.write(self.style.WARNING("Invalid customer data. Skipping."))
                continue

@mariobehling mariobehling merged commit eca5be9 into fossasia:development Aug 6, 2024
3 of 9 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.

3 participants