fix: return 400 instead of 500 when request user is invalid (closes #6809)#7636
fix: return 400 instead of 500 when request user is invalid (closes #6809)#7636botbikamordehai2-sketch wants to merge 2 commits into
Conversation
|
@botbikamordehai2-sketch is attempting to deploy a commit to the Flagsmith Team on Vercel. A member of the Team first needs to authorize it. |
for more information, see https://pre-commit.ci
There was a problem hiding this comment.
Code Review
This pull request modifies the AuthorData.from_request method to raise a Django REST Framework ValidationError instead of a standard Python ValueError when the request user is invalid. The reviewer points out that raising a ValidationError (which results in an HTTP 400 Bad Request) is inappropriate for unauthenticated or anonymous users. Instead, the reviewer suggests raising NotAuthenticated (HTTP 401) for anonymous users to properly trigger authentication flows, and provides a code suggestion to implement this behavior.
|
|
||
| from users.models import FFAdminUser | ||
|
|
||
| if type(request.user) is FFAdminUser: | ||
| return cls(user=request.user) | ||
| elif hasattr(request.user, "key"): | ||
| return cls(api_key=request.user.key) | ||
| else: |
There was a problem hiding this comment.
When the request user is anonymous or not authenticated, raising a ValidationError results in an HTTP 400 Bad Request. However, for unauthenticated requests, returning an HTTP 401 Unauthorized (via NotAuthenticated) is standard and crucial for clients to correctly handle authentication flows (such as redirecting to login or triggering token refresh). We should check if the user is anonymous or missing and raise NotAuthenticated in those cases, while keeping ValidationError for other unexpected authenticated user types.
| from users.models import FFAdminUser | |
| if type(request.user) is FFAdminUser: | |
| return cls(user=request.user) | |
| elif hasattr(request.user, "key"): | |
| return cls(api_key=request.user.key) | |
| else: | |
| from rest_framework.exceptions import NotAuthenticated, ValidationError | |
| if not request.user or request.user.is_anonymous: | |
| raise NotAuthenticated() | |
| if type(request.user) is FFAdminUser: | |
| return cls(user=request.user) | |
| elif hasattr(request.user, "key"): | |
| return cls(api_key=request.user.key) | |
| else: | |
| raise ValidationError("Request user must be FFAdminUser or have an API key") |
|
|
||
| @classmethod | ||
| def from_request(cls, request: "Request") -> "AuthorData": | ||
| from rest_framework.exceptions import ValidationError |
There was a problem hiding this comment.
Any particular reason to use a local import here?
| return cls(api_key=request.user.key) | ||
| else: | ||
| raise ValueError("Request user must be FFAdminUser or have an API key") | ||
| raise ValidationError("Request user must be FFAdminUser or have an API key") |
There was a problem hiding this comment.
Seems like there's no test coverage for this line?
Also, the exception message doesn't make sense when presented in an API response.
What
When a request has an unexpected user type (e.g., anonymous, or a user model that is neither FFAdminUser nor an API key),
AuthorData.from_requestraises a bareValueError. This propagates to database operations where unvalidated input (like a string 'PROJECT_ID' for an integer field) causes a similarValueError, resulting in a 500 Internal Server Error.Fix
Replaced the generic
ValueErrorwith Django REST Framework'sValidationError, which automatically results in an HTTP 400 Bad Request response. This aligns with the project's goal of validating input early and returning proper error responses.Closes #6809