feat/user-blocking #50

Merged
nrupard merged 4 commits from feat/user-blocking into main 2026-05-06 19:40:28 +02:00
Owner
No description provided.
- Add user_blocks table (auth/0006) keyed by (blocker_id, blocked_id) with a CHECK preventing self-blocks.
- Add db helpers: block_user, unblock_user, did_block, is_blocked_either_way, list_blocked_users; extend search_users to exclude users blocked in either direction.
- Add POST /users/{id}/block, POST /users/{id}/unblock with safe same-origin return_to redirects.
- Add GET /settings/blocked page listing blocked users with an Unblock action; link from the Settings page Privacy section.
- DM page renders a friendly "You can't message @x" notice via WelcomePage when either party blocks the other; sidebar hides DMs with blocked peers.
- Refuse top-level message and thread reply sends in DM rooms when either party is blocked.
- Surface a Block button in the DM header and in user search results; both confirm before posting.
- Tests cover block/unblock round trip, list_blocked_users, and that search_users excludes users blocked in either direction.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Blocking previously only hid DMs and prevented new DM creation. Messages authored by a blocked user remained visible in shared enclave rooms, thread panels, search hits, and live WebSocket pushes. Extend the filter to every message surface.

- Add db::auth::list_blocked_ids_either_way returning the union of users the viewer blocked and users who blocked the viewer.
- Filter raw_messages in get_room and DM page; filter thread replies in get_thread_panel and 404 the panel when the parent is blocked; 404 get_single_message when the message author is blocked.
- Filter search results by author so blocked authors don't appear in the global search index for the viewer.
- WebSocket: drop NewMessage, ThreadReply, and MessageEdited renders when the author is blocked, so live pushes don't bypass the page-render filter.
- Backfill 0006 migration into every test's setup helper that hadn't already been updated.
- Add list_blocked_ids_either_way unit test covering both directions and an unrelated user.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Users with privacy turned on don't appear in people search, which means the existing search-result Block button can't reach them. Add a "Block by username" form on /settings/blocked that takes the exact username (with or without a leading @) and resolves it via find_user_by_username, which ignores the privacy filter. Inline error messages cover blank input, unknown usernames, and self-block attempts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The username form on /settings/blocked previously resolved any username via find_user_by_username so users with private profiles could be blocked. That bypass also let any caller probe the existence of every account (including private ones) and pre-emptively block users they had no relationship with, which is an abuse vector.

Restrict the bypass: when the target's profile is private, only allow the block when caller and target share at least one enclave. Public profiles are still blockable by username because they're already discoverable through people-search. The denial reuses the "No user found" message verbatim so the response cannot distinguish "doesn't exist" from "exists but private and no shared enclave".

Adds db::enclave::users_share_enclave for the membership probe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
nrupard deleted branch feat/user-blocking 2026-05-06 19:40:28 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!50
No description provided.