Skip to content

Conversation

@Aqil-Ahmad
Copy link

@Aqil-Ahmad Aqil-Ahmad commented Oct 12, 2025

Description

Allows users to register for tickets and speaker accounts using Wikimedia OAuth, even when their Wikimedia profile doesn't have an associated email address.

Changes

  • Add is_wikimedia_user field to user model to identify Wikimedia OAuth users
  • Generate placeholder emails for Wikimedia users without email
  • Make email field optional in registration
  • Skip sending emails to placeholder addresses
  • Add utility functions: is_wikimedia_user() and get_or_create_email_for_wikimedia_user()
  • Add database migration for new field

Closes

Fixes #1013

Summary by Sourcery

Allow Wikimedia OAuth users to register without an email by generating placeholder email addresses, adding an is_wikimedia_user flag to the user model, suppressing email notifications for placeholder accounts, and making email optional in relevant forms.

New Features:

  • Enable Wikimedia OAuth users to register without an email by generating [email protected] addresses
  • Add is_wikimedia_user flag to the User model to track Wikimedia OAuth accounts

Enhancements:

  • Skip sending security and password emails to placeholder Wikimedia addresses
  • Make email fields optional and bypass validation for Wikimedia users in checkout and settings forms
  • Introduce utility functions is_wikimedia_user() and get_or_create_email_for_wikimedia_user()
  • Add database migration to add the is_wikimedia_user field to the User model

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Oct 12, 2025

Reviewer's Guide

This PR enables Wikimedia OAuth users without an email by marking them with a new flag, generating placeholder emails, adapting the social auth flow, skipping notifications to placeholder addresses, and making email fields optional in relevant forms.

Entity relationship diagram for User model and Wikimedia OAuth

erDiagram
    USER {
      string fullname
      string wikimedia_username
      boolean is_wikimedia_user
      string email
    }
    SOCIALACCOUNT {
      string provider
      json extra_data
    }
    USER ||--o{ SOCIALACCOUNT : has
    SOCIALACCOUNT }o--|| USER : belongs_to
Loading

Class diagram for updated User model with Wikimedia support

classDiagram
class User {
  +fullname: CharField
  +wikimedia_username: CharField
  +is_wikimedia_user: BooleanField
  +is_active: BooleanField
  +is_staff: BooleanField
  +date_joined: DateTimeField
  +send_security_notice(messages, email=None)
  +send_password_reset(request)
  +reset_password(event, user=None, mail_text=None, orga=False)
  +change_password(new_password)
}
User <|-- UserSettingsForm
User <|-- get_or_create_user
User <|-- is_wikimedia_user
User <|-- get_or_create_email_for_wikimedia_user
Loading

File-Level Changes

Change Details Files
Add is_wikimedia_user flag to User model with migration
  • Add BooleanField is_wikimedia_user to User model
  • Create migration to add the new field
app/eventyay/base/models/auth.py
app/eventyay/base/migrations/0005_user_is_wikimedia_user.py
Introduce utility functions for Wikimedia users
  • Implement get_or_create_email_for_wikimedia_user to generate or reuse emails
  • Implement is_wikimedia_user helper to detect OAuth users
app/eventyay/person/utils.py
Update social auth user creation to handle placeholder emails and flags
  • Use utility to derive final_email for registration
  • Set auth_backend dynamically based on provider
  • Initialize and update wikimedia_username and is_wikimedia_user fields
app/eventyay/plugins/socialauth/views.py
Skip sending emails to placeholder addresses
  • Add checks in send_security_notice, send_password_reset, reset_password, change_password to return early for placeholder emails
app/eventyay/base/models/auth.py
Make email optional for Wikimedia users in forms
  • Mark email (and email_repeat) as optional and adjust clean logic in Checkout form
  • Conditionally require email in UserSettingsForm based on is_wikimedia_user
app/eventyay/presale/forms/checkout.py
app/eventyay/base/forms/user.py

Assessment against linked issues

Issue Objective Addressed Explanation
#1013 Allow users authenticating via Wikimedia OAuth to register as ticket buyers or speakers even if their Wikimedia profile does not contain an email address.
#1013 Update OAuth login and user creation logic to skip strict email validation for Wikimedia OAuth users, use Wikimedia username as unique identifier, and optionally store a placeholder email in the format '[email protected]' for internal use.
#1013 Ensure compatibility with ticket purchase and confirmation flows, speaker and submission forms, and user profiles, so that Wikimedia users without email can proceed without validation errors and are correctly displayed in organizer/admin panels.

Possibly linked issues


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. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the 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 exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

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
Contributor

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

  • Abstract the '@wikimedia.local' placeholder domain into a configurable setting or constant to avoid hardcoding it in multiple places.
  • Ensure placeholder emails remain unique (e.g. by appending a timestamp or random suffix) to prevent collisions for users sharing the same Wikimedia username.
  • DRY up the repeated skip-email logic by extracting it into a decorator or helper so you don’t need to repeat the same if endswith('@wikimedia.local') checks.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Abstract the '@wikimedia.local' placeholder domain into a configurable setting or constant to avoid hardcoding it in multiple places.
- Ensure placeholder emails remain unique (e.g. by appending a timestamp or random suffix) to prevent collisions for users sharing the same Wikimedia username.
- DRY up the repeated skip-email logic by extracting it into a decorator or helper so you don’t need to repeat the same `if endswith('@wikimedia.local')` checks.

## Individual Comments

### Comment 1
<location> `app/eventyay/plugins/socialauth/views.py:106-107` </location>
<code_context>
             wikimedia_username = extra_data.get('username', extra_data.get('realname', ''))

+        # Generate placeholder email for Wikimedia users without email
+        final_email = get_or_create_email_for_wikimedia_user(wikimedia_username, email)
+
         user, created = User.objects.get_or_create(
</code_context>

<issue_to_address>
**suggestion:** Consider handling empty Wikimedia usernames when generating placeholder emails.

Currently, an empty wikimedia_username results in a placeholder email missing the username part. Please add a check to ensure the username is not empty before generating the email.

```suggestion
        # Generate placeholder email for Wikimedia users without email
        if wikimedia_username:
            final_email = get_or_create_email_for_wikimedia_user(wikimedia_username, email)
        else:
            final_email = email
```
</issue_to_address>

### Comment 2
<location> `app/eventyay/person/utils.py:15` </location>
<code_context>
+    """
+    if email and email.strip():
+        return email
+    return f"{username}@wikimedia.local"
+
+
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Placeholder email generation does not sanitize Wikimedia usernames.

Usernames with spaces or special characters could result in invalid email addresses. Please sanitize the username before constructing the email.
</issue_to_address>

### Comment 3
<location> `app/eventyay/base/forms/user.py:67-70` </location>
<code_context>
    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user')
        super().__init__(*args, **kwargs)
        # Make email optional for Wikimedia users
        if not is_wikimedia_user(self.user):
            self.fields['email'].required = True
        else:
            self.fields['email'].required = False
        self.fields['wikimedia_username'].widget.attrs['readonly'] = True
        if self.user.auth_backend != 'native':
            del self.fields['old_pw']
            del self.fields['new_pw']
            del self.fields['new_pw_repeat']
            self.fields['email'].disabled = True

</code_context>

<issue_to_address>
**suggestion (code-quality):** We've found these issues:

- Replace if statement with if expression ([`assign-if-exp`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/assign-if-exp/))
- Simplify boolean if expression ([`boolean-if-exp-identity`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/boolean-if-exp-identity/))
- Remove unnecessary casts to int, str, float or bool ([`remove-unnecessary-cast`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/remove-unnecessary-cast/))

```suggestion
        self.fields['email'].required = not is_wikimedia_user(self.user)
```
</issue_to_address>

### Comment 4
<location> `app/eventyay/person/utils.py:13-15` </location>
<code_context>
def get_or_create_email_for_wikimedia_user(username, email=None):
    """
    Generate an email for Wikimedia users.
    If email exists, use it. Otherwise, create a placeholder.

    Args:
        username (str): Wikimedia username
        email (str): Email from Wikimedia profile (can be None)

    Returns:
        str: Email address
    """
    if email and email.strip():
        return email
    return f"{username}@wikimedia.local"

</code_context>

<issue_to_address>
**suggestion (code-quality):** We've found these issues:

- Lift code into else after jump in control flow ([`reintroduce-else`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/reintroduce-else/))
- Replace if statement with if expression ([`assign-if-exp`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/assign-if-exp/))

```suggestion
    return email if email and email.strip() else f"{username}@wikimedia.local"
```
</issue_to_address>

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.

Copy link
Member

@mariobehling mariobehling left a comment

Choose a reason for hiding this comment

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

Hi, I’ve run an AI-assisted review on this PR to catch structural and consistency issues.
The feature direction looks fine, but there are several must-fix items before merge — please review carefully.

🧩 1) UserSettingsForm – redundant required assignment

You set self.fields['email'].required = True and then re-set it conditionally.
Please simplify to a single clear line:

self.fields['email'].required = not is_wikimedia_user(self.user)

This avoids confusing double assignment.

🧩 2) Placeholder email – no sanitization

get_or_create_email_for_wikimedia_user builds f"{username}@wikimedia.local" directly.
This can yield invalid or colliding addresses (spaces, Unicode, punctuation).
Add sanitization:

  • lowercase, strip, replace whitespace → .
  • remove disallowed chars
  • optionally append Wikimedia user ID to ensure uniqueness.

🧩 3) Empty username edge case

If both username and realname are missing, wikimedia_username becomes '', producing @wikimedia.local.
Guard this explicitly—either:

  • fail with a user-friendly error, or
  • generate a deterministic surrogate (wm-{social_id}@wikimedia.local).

🧩 4) User lookup by placeholder email → collision risk

User.objects.get_or_create(email=final_email) relies on the synthetic email for uniqueness.
Different users could collide or one user could later switch to a real email.
Either:

  • guarantee unique placeholders (e.g., include Wikimedia ID), or
  • key on wikimedia_username + provider instead of email.

🧩 5) i18n missing for new fields

verbose_name=('Wikimedia username') and is_wikimedia_user should be wrapped in _() for translation consistency.

🧩 6) Mail suppression logic duplicated

Several methods (send_security_notice, send_password_reset, reset_password, change_password) repeat

if self.email.endswith('@wikimedia.local'):
    return

Extract a helper like is_placeholder_email(email) and reuse across all mail-sending paths.

🧩 7) Migration index check

Migration 0005_user_is_wikimedia_user depends on 0004_....
Please confirm no newer migration was added on enext since then — rebase or renumber if necessary.

✅ Next steps

  • Address all seven items above.
  • Re-run tests after sanitization and form updates.
  • Add a small test case for the new utils once you introduce them.

💡 Note: This review used AI assistance for consistency and code-quality scanning.
I recommend you also use an AI tool (e.g. ChatGPT or Sourcery AI) to review your future contributions — paste your code or PR URL and ask it to spot logical and structural issues. It’s very effective for edge cases like the placeholder-email flow.

@Aqil-Ahmad Aqil-Ahmad force-pushed the fix/wikimedia-email-registration branch from 7fb880f to 8935b93 Compare October 13, 2025 19:40
@mariobehling mariobehling requested a review from hongquan October 21, 2025 15:29
Copy link
Member

@mariobehling mariobehling left a comment

Choose a reason for hiding this comment

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

The conflicts of this PR need to be resolved before it can be further reviewed.

@Aqil-Ahmad Aqil-Ahmad force-pushed the fix/wikimedia-email-registration branch from 612ffb9 to bd64b99 Compare October 29, 2025 14:33
@Aqil-Ahmad
Copy link
Author

The conflicts of this PR need to be resolved before it can be further reviewed.

Hi @mariobehling ! i've rebased this PR on the latest enext branch. GitHub is still showing a conflict but when I test the merge locally, it completes successfully with no conflicts.

@mariobehling mariobehling requested a review from Copilot October 29, 2025 21:40
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for Wikimedia OAuth users with placeholder email addresses, allowing users who don't provide real email addresses to use the platform without receiving unwanted notifications.

Key changes:

  • Added utilities to generate and identify placeholder Wikimedia emails
  • Modified user authentication flow to support Wikimedia users without real emails
  • Added database field to track Wikimedia user status
  • Updated form validation to make email optional for Wikimedia users

Reviewed Changes

Copilot reviewed 8 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/person/test_wikimedia_utils.py Comprehensive test coverage for Wikimedia email utility functions
app/eventyay/person/utils.py Core utility functions for generating placeholder emails and identifying Wikimedia users
app/eventyay/plugins/socialauth/views.py Updated OAuth flow to use wikimedia_username as primary lookup key and generate placeholder emails
app/eventyay/presale/forms/checkout.py Made email field optional for Wikimedia users in checkout forms
app/eventyay/base/models/auth.py Added is_wikimedia_user field and guards to prevent sending emails to placeholder addresses
app/eventyay/base/forms/user.py Made email field optional for Wikimedia users in user settings
app/eventyay/base/migrations/0005_user_is_wikimedia_user.py Database migration to add is_wikimedia_user field
app/eventyay/config/urls.py Added socialauth plugin URLs to main URL configuration

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Member

@mariobehling mariobehling left a comment

Choose a reason for hiding this comment

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

Thank you. Please check Copilot comments. Also, we will reset the database migrations through another PR in the upcoming days. So, this would require a change in this regard as well.

@Aqil-Ahmad Aqil-Ahmad force-pushed the fix/wikimedia-email-registration branch from aa0b1d3 to 45ec22a Compare October 30, 2025 02:38
Copy link
Member

@mariobehling mariobehling left a comment

Choose a reason for hiding this comment

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

@Aqil-Ahmad Please take into account the changes mentioned here #1013 (comment)

There is an issue with the placeholder requirement. We actually do not need it.

Regarding the functionality of this feature. We need to check in detail.

Please make the adjustments based on the comments.

@Aqil-Ahmad
Copy link
Author

@Aqil-Ahmad Please take into account the changes mentioned here #1013 (comment)

There is an issue with the placeholder requirement. We actually do not need it.

Regarding the functionality of this feature. We need to check in detail.

Please make the adjustments based on the comments.

thanks for the feedback!
i'll remove the placeholder email logic and try to make it optional instead. will push the updates shortly.

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.

Feature: Allow Ticket and Speaker Registration with Wikimedia Accounts Without Email

2 participants