Visiting /profile/<someone-you-blocked> used to return a generic 404. That's the right call when they blocked you (a dedicated "you've been blocked" page would leak the block state to the blockee), but the wrong call when you are the blocker — you chose the state and the page should tell you what happened and offer a one-click way out.
Now splits the block check by direction:
- You blocked them → renders
profile/blocked-by-me.php. Auto-opening modal explains the block, offers an Unblock form with CSRF + confirm, and links to /friends/blocked for the full list. Same shape asprofile/private.phpso the UX pattern is consistent. - They blocked you → still 404 (non-admin). Admin bypass preserved for this direction only so moderation access works.
Admins who personally block someone still get the modal — the admin bypass is scoped to the blockee case, not the blocker case. Self-chosen blocks are respected regardless of role.
New App\Models\Block centralises the predicate so the inline SQL isn't copy-pasted across controllers:
Block::exists($a, $b)— bidirectional. Use wherever either side's consent to interact matters (DMs, mentions, tips, follows).Block::blockedBy($blocker, $blocked)— directional. Use where direction carries meaning (rendering the Block/Unblock toggle, or the split above).
Both short-circuit on self-pairs (a === b) so callers passing a current-user id unconditionally don't trip an accidental "blocked" state.
Known adjacent enforcement gaps (not in scope for this fix, noted for a follow-up):
MessageController::sendMessagehas a unidirectional block check — if you block someone mid-conversation, you can still keep replying to them.FollowController::togglehas no block check — a blocked user can follow the blocker.TipController::storehas no block check.ForumController::processMentionsdoesn't filter @-mention notifications by block pairs.
Ping if you want those done in a separate pass — the new Block helper makes each one a one-line addition.
. __ ____ ___ ____ _ _
/ /_| ___| / _ \___ \(_)___| |__
| '_ \___ \| | | |__) | / __| '_ \
| (_) |__) | |_| / __/| \__ \ | | |
\___/____/ \___/_____|_|___/_| |_|
D2sk - Sysop