Skip to content

feat(chat): backoffice list of the restrictions reaching a room - #262

Merged
zaxovaiko merged 4 commits into
devfrom
feat/chat-restricted-players
Oct 9, 2026
Merged

zaxovaiko merged 4 commits into
devfrom
feat/chat-restricted-players

Conversation

@okapitula

@okapitula okapitula commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds adminListRoomRestrictions (GET /backoffice/chat/rooms/{roomId}/restrictions): the active mutes, bans and cooldowns that reach one room, paginated and newest first, with who set each one. Stacks on #261 (base branch feat/chat-player-restrictions), which stacks on #260.

Why

The admin mute, ban and cooldown lists filter by user only. Without a filter they return every active row on the platform, unpaginated, and say neither who set an entry nor the player's username. Which wide scopes reach a room depends on the room kind (platformScopesFor(roomReach(room))), and room-moderator mutes and bans live in their own tables, so a consumer cannot build a per-room view from the existing routes without re-implementing core's reach rules. Every operator running the backoffice needs to see who is restricted in a room.

  • One UNION ALL over chat_mute, chat_platform_ban, chat_player_cooldown, chat_room_mute and chat_room_ban, plus a count, paginated in SQL with id as the tiebreak. type filters to mute, ban or cooldown.
  • Each item reports source (admin for staff rows, room for room-moderator rows), scope, roomId, reason (null for a room-moderator ban), setByName (the player username for room rows, the staff account name for admin rows, null if not found), cooldownSeconds (null unless a cooldown), createdAt and expiresAt.
  • Guarded by chat-moderation:view, like the existing lists. An unknown or deleted room returns 404; the global room is addressed by its row id or __global.
  • Partial indexes on (room_id, expires_at) and (scope, expires_at) where lifted_at IS NULL for the three admin tables, so expired history does not slow the listing.

Alternatives considered

  • A roomId filter on the existing mute and ban lists: it would miss wide-scope rows that reach the room and the room-moderator tables.
  • Reading through the CHAT_MODERATION port: the port has no per-room query, and adding one widens an overridable port. This reads core's tables directly, like the other admin room routes.

Risks

  • An operator who rebinds CHAT_MODERATION to store mutes, bans or cooldowns elsewhere gets an incomplete list from this route.
  • total and the page come from two queries, so a restriction set or lifted between them can make them disagree by one, as with the room list.
  • Migration 0018_chat_restriction_room_indexes only adds indexes.

@okapitula
okapitula added this pull request to stack #266 October 6, 2026 07:27
@okapitula
okapitula marked this pull request as ready for review October 6, 2026 07:28
@okapitula
okapitula force-pushed the feat/chat-restricted-players branch from 07dbc7f to 2656cad Compare October 7, 2026 12:31
@okapitula
okapitula force-pushed the feat/chat-restricted-players branch 2 times, most recently from 23c6ffb to e84f9bf Compare October 8, 2026 09:42
@okapitula
okapitula force-pushed the feat/chat-restricted-players branch from e84f9bf to 7dc1732 Compare October 9, 2026 12:03
zaxovaiko
zaxovaiko previously approved these changes Oct 9, 2026

@zaxovaiko zaxovaiko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good. One to check later: the restricted-players lookup does not filter isPublic, so an admin with chat-moderation view can list private room bans/mutes.

@zaxovaiko
zaxovaiko added this pull request to the merge queue Oct 9, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue because a pull request earlier in the stack was removed Oct 9, 2026
@zaxovaiko
zaxovaiko force-pushed the feat/chat-restricted-players branch from 7dc1732 to 9eba680 Compare October 9, 2026 17:36
Base automatically changed from feat/chat-player-restrictions to dev October 9, 2026 17:49
adminListRoomRestrictions returns the active mutes, bans and cooldowns that
reach one room, paginated in SQL and newest first, with who set each entry.
Wide-scope rows count when platformScopesFor(roomReach(room)) covers them;
room-moderator mutes and bans report source 'room'.

- GET /backoffice/chat/rooms/{roomId}/restrictions, guarded by
  chat-moderation:view, 404 for an unknown or deleted room
- one UNION ALL over the five restriction tables plus a count
- partial (room_id, expires_at) and (scope, expires_at) indexes on active
  chat_mute, chat_platform_ban and chat_player_cooldown rows
…ts at

Room-moderator rows resolve the setter's player username and staff rows the account name, so an id that also matches the other table no longer picks the wrong one. The row type is inferred from the union query, and setBy { id, name } becomes setByName so staff ids are not exposed.
@zaxovaiko
zaxovaiko force-pushed the feat/chat-restricted-players branch from 9eba680 to 7d8f674 Compare October 9, 2026 17:50
@zaxovaiko
zaxovaiko merged commit 1697f2e into dev Oct 9, 2026
6 checks passed
@zaxovaiko
zaxovaiko deleted the feat/chat-restricted-players branch October 9, 2026 17:58
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.

2 participants