Moderate misbehaving users as a chat user

Regular chat users (without secretKey) can mute undesirable users to hide their messages. For admin moderation, see Moderation as admin.

Mute list behavior:

  • Soft limit: 200 users
  • Default: session-only persistence
  • Optional: persist across sessions (32 KiB server limit applies)
Mute list limit

Persisted lists exceeding 32 KiB (~200 users) trigger HTTP 413 errors. Users remain muted for the session but won't persist.

Affected methods:

note

Enable App Context in the Admin Portal to mute users.

Mute users as a regular chat user​

Mute a specific user on all channels.

Method signature​

1chat.mutedUsersManager.muteUser(userId): Promise<any>;

Input​

* required
ParameterDescription
userId *
Type: string
User ID of the user you want to mute.

Output​

This method returns a Promise that succeeds when the data has been synced with the server. If syncMutedUsers is not enabled, the Promise always succeeds.

Errors​

If the size of the mute list exceeds 32 KiB (roughly 200 users), you'll get the HTTP 413 (Request Entity Too Large) error.

Sample code​

1import { Chat } from "@pubnub/chat"
2
3const chat = Chat.init({
4 publishKey: "demo",
5 subscribeKey: "demo",
6 userId: "myUniqueUserId"
7})
8
9let userToMute = "user_1905"
10
11await chat.mutedUsersManager.muteUser(userToMute)

Unmute users as a regular chat user​

Remove a user from the mute list to see their messages and events again.

Method signature​

1chat.mutedUsersManager.unmuteUser(userId): Promise<any>;

Input​

* required
ParameterDescription
userId *
Type: string
User ID of the user you want to unmute.

Output​

This method returns a Promise that succeeds when the data has been synced with the server. If syncMutedUsers is not enabled, the Promise always succeeds.

Sample code​

1import { Chat } from "@pubnub/chat"
2
3const chat = Chat.init({
4 publishKey: "demo",
5 subscribeKey: "demo",
6 userId: "myUniqueUserId"
7})
8
9let userToUnmute = "user_1905"
10
11await chat.mutedUsersManager.unmuteUser(userToUnmute)

Check muted users​

Inspect the mute list to see which users are muted.

Method signature​

1chat.mutedUsersManager.mutedUsers

Output​

This property returns a Array<String> where each String is a user ID of a muted user.

Sample code​

1import { Chat } from "@pubnub/chat";
2
3const chat = Chat.init({
4 publishKey: "demo",
5 subscribeKey: "demo",
6 userId: "myUniqueUserId"
7});
8
9let userToMute = "user_1905";
10
11// Mute the user
12await chat.mutedUsersManager.muteUser(userToMute)
13
14// Once the user is muted, get the list of muted users
15const mutedUsers = chat.mutedUsersManager.mutedUsers;
show all 17 lines

Persist the mute list​

Set syncMutedUsers: true during client initialization to persist the mute list across sessions.

Access Manager permissions

With Access Manager and syncMutedUsers enabled, grant these permissions (replace $currentUserId with the actual user ID):

  • read on PN_PRV.$currentUserId.mute1 channel
  • update, delete, get on PN_PRV.$currentUserId.mute1 user

Check restrictions​

Check admin-imposed mute or ban restrictions:

Sample code​

Single user on a single channel​
1// List all mute and ban restrictions set by the admin
2// for the user support_agent_15.
3
4// reference "support-agent-15"
5const user = await chat.getUser("support_agent_15")
6
7// list all restrictions set for that user
8await user.getChannelsRestrictions()
All users on a single channel​
1// List all mute and ban restrictions set by the admin
2// for the support channel.
3
4// reference the "support" channel
5const channel = await chat.getChannel("support")
6
7// list all restrictions on the "support" channel
8await channel.getUsersRestrictions()
Single user on all channels​
1// List all mute and ban restrictions set by the admin
2// for the user support_agent_15.
3
4// reference "support-agent-15"
5const user = await chat.getUser("support_agent_15")
6
7// list all restrictions set for that user
8await user.getChannelsRestrictions()

Secure moderation​

Client-side restrictions can be bypassed without server-side logic using Access Manager. Combine with client-side UI feedback to inform users of restrictions.

Client-side restrictions​

With server-side permissions enforced via Access Manager, read moderation restrictions on the frontend to show users their status (e.g., popup messages, disabled input fields).

To react to permission changes in real-time:

  1. Listen for moderation events.

    Set up a listener to listen for the moderation event type ("banned," "muted," or "lifted") generated when UI restrictions are added or removed.

    1useEffect(() => {
    2 // Set up a listener for moderation events on the current user's channel
    3 const moderationListener = chat.listenForEvents({
    4 channel: chat.currentUser.id,
    5 type: "moderation",
    6 callback: handleModerationEvent,
    7 });
    8
    9 return () => {
    10 moderationListener(); // Remove the moderation event listener on cleanup
    11 };
    12}, [chat]);
  2. Act on moderation events.

    Update permissions in response to moderation events and generate new tokens if necessary.

    1// Callback function to handle different moderation events
    2async function handleModerationEvent(moderationPayload: Event<"moderation">) {
    3 const { channelId, restriction, reason } = moderationPayload.payload;
    4
    5 // Handle different moderation events
    6 if (restriction === "banned") {
    7 // Revoke specific permissions for banning
    8 console.log(`User ${chat.currentUser.id} is banned on channel ${channelId}. Reason: ${reason || "N/A"}`);
    9
    10 // Revoke access rights specific to banning logic here
    11 // For example, you might remove write access
    12
    13 } else if (restriction === "muted") {
    14 // Revoke specific permissions for muting
    15 console.log(`User ${chat.currentUser.id} is muted on channel ${channelId}. Reason: ${reason || "N/A"}`);
    show all 29 lines
  3. Remove the event listener.

    1return () => {
    2 moderationListener(); // Remove the moderation event listener on cleanup
    3};

Was this page useful?

Last updated on