Include private user profiles in search results#3034
Conversation
fix(user-search): include private user profiles in search results
Include private user profiles in user search results
Greptile SummaryThis PR removes the
|
| Filename | Overview |
|---|---|
| api/dashboard/user/dash_user_views.py | Removes the is_public filter from UserSearchAPI — a public, unauthenticated endpoint — exposing all private user profiles (name, muid, karma, orgs) to any caller. |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant C as Unauthenticated Caller
participant S as UserSearchAPI (GET /search/)
participant DB as Database
Note over C,S: No authentication_classes declared - No JWT required
C->>S: "GET /api/v1/dashboard/user/search/?search=..."
S->>DB: User.objects.all() (no is_public filter)
DB-->>S: All users including private profiles
S-->>C: id, full_name, muid, profile_pic, karma, organizations
Note over C,S: Before this PR
C->>S: "GET /api/v1/dashboard/user/search/?search=..."
S->>DB: "User.objects.filter(user_settings_user__is_public=True)"
DB-->>S: Only public profiles
S-->>C: Public user data only
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant C as Unauthenticated Caller
participant S as UserSearchAPI (GET /search/)
participant DB as Database
Note over C,S: No authentication_classes declared - No JWT required
C->>S: "GET /api/v1/dashboard/user/search/?search=..."
S->>DB: User.objects.all() (no is_public filter)
DB-->>S: All users including private profiles
S-->>C: id, full_name, muid, profile_pic, karma, organizations
Note over C,S: Before this PR
C->>S: "GET /api/v1/dashboard/user/search/?search=..."
S->>DB: "User.objects.filter(user_settings_user__is_public=True)"
DB-->>S: Only public profiles
S-->>C: Public user data only
Reviews (1): Last reviewed commit: "Merge pull request #3033 from gtech-mule..." | Re-trigger Greptile
| queryset = ( | ||
| User.objects.all() | ||
| .select_related("wallet_user") | ||
| .filter(user_settings_user__is_public=True) | ||
| .prefetch_related("user_settings_user") | ||
| .order_by("-wallet_user__karma") | ||
| ) |
There was a problem hiding this comment.
Private profiles exposed on an unauthenticated public endpoint
UserSearchAPI has no authentication_classes = [CustomizePermission] declaration, making it accessible without any JWT. The removed filter was the only guard preventing private profiles from appearing in results. user_settings.is_public defaults to 0 (false) in the schema, so the majority of users who never explicitly opted in are now discoverable — including their id, full_name, muid, profile_pic, karma, organizations, and interest_groups — by any unauthenticated caller.
Every other privacy boundary in the codebase enforces this invariant: profile_view.py gates five separate profile sub-endpoints on is_public, mulearner_views.py filters with user_settings_user__is_public=True, and external_api_views.py rejects private profiles with 403. Removing this single line breaks the contract users relied on when they left (or set) their visibility to private.
No description provided.