Skip to content

fix: restrict invitation accept/decline actions to invited user only#5777

Open
ashnaaseth2325-oss wants to merge 2 commits intolearningequality:unstablefrom
ashnaaseth2325-oss:fix/invitation-accept-decline-auth
Open

fix: restrict invitation accept/decline actions to invited user only#5777
ashnaaseth2325-oss wants to merge 2 commits intolearningequality:unstablefrom
ashnaaseth2325-oss:fix/invitation-accept-decline-auth

Conversation

@ashnaaseth2325-oss
Copy link
Contributor

@ashnaaseth2325-oss ashnaaseth2325-oss commented Mar 23, 2026

1. SUMMARY

This PR enforces invitee-only authorization in the invitation accept and decline endpoints, preventing non-invited users (e.g., channel editors) from modifying invitation state. It ensures only the intended recipient can act on an invitation, avoiding unauthorized acceptance or rejection.


2. FIX

# Before
invitation = self.get_object()
invitation.accept()

# After
invitation = self.get_object()
if request.user.email.lower() != (invitation.email or "").lower():
    return Response(
        {"detail": "Only the invited user may accept this invitation."},
        status=status.HTTP_403_FORBIDDEN,
    )
invitation.accept()

closes #5781

3. VERIFICATION

Sending a request as a non invited user to POST /invitation/<id>/accept/ or /decline/ now returns 403 FORBIDDEN instead of modifying the invitation.

The invitation state remains unchanged, while valid requests from the invited user continue to work as expected.


4, AI Usage

I did not use AI to generate or implement the code changes. The issue was identified by reviewing the existing invitation flow and noticing a missing authorization check, and the fix (including tests) was implemented and validated manually.

AI was only used to help refine the wording and structure of the PR description so that the problem and solution are communicated more clearly. All code changes were implemented and verified manually.

Channel editors could accept or decline invitations meant for other
users because the accept/decline actions only checked the view queryset
(which includes all channel editors) without verifying the requesting
user is the actual invitee. Add an email equality guard to both actions
and cover the case with regression tests.

Signed-off-by: ashnaaseth2325-oss <ashnaaseth2325@gmail.com>
@learning-equality-bot
Copy link

👋 Hi @ashnaaseth2325-oss, thanks for contributing!

For the review process to begin, please verify that the following is satisfied:

  • Contribution is aligned with our contributing guidelines

  • Pull request description has correctly filled AI usage section & follows our AI guidance:

    AI guidance

    State explicitly whether you didn't use or used AI & how.

    If you used it, ensure that the PR is aligned with Using AI as well as our DEEP framework. DEEP asks you:

    • Disclose — Be open about when you've used AI for support.
    • Engage critically — Question what is generated. Review code for correctness and unnecessary complexity.
    • Edit — Review and refine AI output. Remove unnecessary code and verify it still works after your edits.
    • Process sharing — Explain how you used the AI so others can learn.

    Examples of good disclosures:

    "I used Claude Code to implement the component, prompting it to follow the pattern in ComponentX. I reviewed the generated code, removed unnecessary error handling, and verified the tests pass."

    "I brainstormed the approach with Gemini, then had it write failing tests for the feature. After reviewing the tests, I used Claude Code to generate the implementation. I refactored the output to reduce verbosity and ran the full test suite."

Also check that issue requirements are satisfied & you ran pre-commit locally.

Pull requests that don't follow the guidelines will be closed.

Reviewer assignment can take up to 2 weeks.

@ashnaaseth2325-oss
Copy link
Contributor Author

Hello @bjester ,
Kindly review this PR when you have time.
Thanks!

Copy link
Member

@bjester bjester left a comment

Choose a reason for hiding this comment

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

This is my second warning about opening unsolicited PRs without discussion with us through an issue or Github discussion.

A meaningful improvement to the tests would be to validate an unrelated user cannot accept an invitation. That should be covered by the existing code.

The fix has duplication and could be consolidated. With investigation into how the aforementioned case is covered, I think there are other small improvements that can be made to these actions.

Replace repeated inline email checks in accept() and decline() with a
single _ensure_invitee() method that raises PermissionDenied, removing
duplication and aligning with DRF exception-based authorization patterns.
@ashnaaseth2325-oss
Copy link
Contributor Author

Thanks for the feedback , I have pushed an update to remove duplication and keep the change minimal.

I have also opened an issue to align on the approach here: #5781

Copy link
Member

@bjester bjester left a comment

Choose a reason for hiding this comment

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

On the viewset, there exist methods get_object and get_edit_object. If you take a look at how those operate, you should see that they use Invitation.filter_view_queryset and Invitation.filter_edit_queryset methods respectively.

In my previous review, I mentioned:

With investigation into how the aforementioned case is covered, I think there are other small improvements that can be made to these actions.

It seems reasonable that these should actually use get_edit_object instead of get_object. Although, that does not solve the original issue, but it is an improvement. Additionally, while that code covers the case of completely unrelated users from accepting or declining, it did not appear to have tests. That would be a meaningful improvement.

Requested changes:

  • update the existing actions in how they obtain the invitation object
  • align the restriction with Invitation.filter_*_queryset methods by allowing admins
  • clarify your original tests to show they cover the case where the authenticated user is the channel editor
  • add new tests to cover the case of a completely new (in the test), unrelated user (not an admin, viewer or editor) attempting to accept or decline the invitation

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.

Restrict invitation accept/decline actions to invited user only

2 participants