You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/features/ban-user.md
+32-7Lines changed: 32 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -34,22 +34,47 @@ Banning prevents a user from participating in a specific room. Unlike kicking (w
34
34
35
35
**Important:** after unban the user **does not become a member** of the room again. The banned subscription is deleted. The user must be invited or join again.
36
36
37
-
## Re-entry After Unban
37
+
## Join / Invite / Re-entry Behavior
38
38
39
-
In `addUserToRoom`, if the user being added has a subscription with `status: 'BANNED'`:
40
-
- Removes the banned subscription.
41
-
- Saves a `user-unbanned` system message.
42
-
- Creates a new subscription normally.
39
+
A banned user **cannot** re-enter the room through any path. The ban must be explicitly lifted first. Below is how each entry point enforces this for both normal and federated rooms.
43
40
44
-
This means inviting/adding a banned user automatically unbans them.
41
+
### Invite via API / UI (`groups.invite`, `channels.invite`, "Add Users")
42
+
43
+
`addUsersToRoom` checks for a `BANNED` subscription before calling `addUserToRoom`:
44
+
- Returns `error-user-is-banned` — the invite is rejected.
45
+
- The UI shows a warning modal asking the admin to unban first.
46
+
- Applies equally to normal and federated rooms (the check is in the method layer, before the room-type branch).
47
+
48
+
### Invite link (`useInviteToken`)
49
+
50
+
`useInviteToken` checks for a `BANNED` subscription before saving the invite token or calling `addUserToRoom`:
51
+
- Returns `error-user-is-banned` — the token is not consumed.
52
+
- Because the check runs before `Users.updateInviteToken`, the secondary path through `setUsername` (for users who register via invite link) is also blocked.
53
+
54
+
### Direct join (`channels.join`, `joinRoom`)
55
+
56
+
`Room.join` calls `canAccessRoom` before `addUserToRoom`:
57
+
- For **public rooms** and **public rooms inside teams**, the `canAccessRoom` validators explicitly check `findOneBannedSubscription` and deny access.
58
+
- For **private rooms**, `countByRoomIdAndUserId` excludes `BANNED` subscriptions (`status: { $exists: false }`), so the "already joined" validator returns false and access is denied.
59
+
60
+
### Federation invite events
61
+
62
+
When a Matrix homeserver sends an invite for a user who is banned locally:
63
+
-`handleInvite` in `federation-matrix/src/events/member.ts` finds the existing (banned) subscription and returns early without creating a new one.
64
+
- The user never receives an `INVITED` subscription, so `handleJoin` is never reached.
65
+
66
+
### Expected flow
67
+
68
+
1.**Unban** the user via `POST /v1/rooms.unbanUser`, `/unban @username`, or the "Banned Users" contextual bar. This deletes the banned subscription.
69
+
2.**Invite or join** — the user can now be invited (API, UI, invite link) or join (public rooms) normally.
45
70
46
71
## Access Control
47
72
48
73
The `canAccessRoom` validators check for bans in two public room scenarios:
49
74
-**Public rooms inside teams** — if banned, access is denied.
50
75
-**Regular public rooms** — if banned, access is denied.
51
76
52
-
For private rooms, access is already controlled by the subscription (which is marked as `BANNED`).
77
+
For private rooms, access is controlled by the subscription: `countByRoomIdAndUserId` excludes `BANNED` subscriptions, so a banned user has no valid subscription and cannot access the room.
0 commit comments