Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSC2213: Rejoinability of private/invite-only rooms #2213

Open
wants to merge 2 commits into
base: old_master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions proposals/2213-rejoin-private-rooms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Rejoinability of private rooms

Similar to a house, users in a private room should have the option of joining and
leaving a room provided they have a key to get in. This process shouldn't involve
another user to send an invite once the user has joined at least once. This proposal
has little meaning in a public room as users are welcome to come and go as they
please already.

An example use case for this would be a direct chat where for de-cluttering one
of the users leaves all direct chats after they become irrelevant. This does
already happen in practice, and often results in the user who left creating multiple
DMs with the other user. [MSC2199](https://github.com/matrix-org/matrix-doc/pull/2199)
covers new DM semantics which benefit from this proposal where users can re-use
DMs even after they've left.

Another use case, not solved by this proposal, would be to support a group-wide
join rule where members of a given group are able to join the room. This use case
is better solved by [MSC2214](https://github.com/matrix-org/matrix-doc/pull/2214)
however.

## Proposal

In a future room version...

`m.room.join_rules` is expanded to have a new `rejoin_rule` field under `content`,
preserved by the redaction algorithm. The `rejoin_rule` must be one of:
Comment on lines +25 to +26
Copy link
Member

Choose a reason for hiding this comment

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

We probably want to add knock to the list of rejoin_rule options now that MSC2403 has merged.

I don't think restricted (MSC3083) or knock_restricted (MSC3787) would make much sense here unless you wanted to allow members to rejoin based on membership somewhere, but not allow new members to join based on that membership? Seems like a bit of an odd-case (and then you need to worry about the configuration of which rooms, etc.)


* `invite`: Members which were previously invited or joined to the room can rejoin,
provided they are now not banned.

* `join`: Members which were previously joined to the room can rejoin, provided they
are now not banned.

* `forbidden`: This event cannot be used to authorize a rejoin (members must be
explicitly invited back into the room). This is the default.
KitsuneRal marked this conversation as resolved.
Show resolved Hide resolved
Comment on lines +28 to +35
Copy link

@erkinalp erkinalp Feb 23, 2021

Choose a reason for hiding this comment

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

Suggested change
* `invite`: Members which were previously invited or joined to the room can rejoin,
provided they are now not banned.
* `join`: Members which were previously joined to the room can rejoin, provided they
are now not banned.
* `forbidden`: This event cannot be used to authorize a rejoin (members must be
explicitly invited back into the room). This is the default.
* `invite`: Members which were previously invited or joined to the room can rejoin,
provided they are now not banned.
*`comeback`: Members which were previously invited or joined to the room can rejoin,
provided they are now not kicked or banned.
* `join`: Members which were previously joined to the room can rejoin, provided they
are now not banned.
* `forbidden`: This event cannot be used to authorize a rejoin (members must be
explicitly invited back into the room). This is the default.
* `block`: A member quitting a room for any reason is treated as if irreversibly banned.


The `rejoin_rule` only takes effect if the `join_rule` for the room is `invite`,
given users can already rejoin the room if the room is public. When the `join_rule`
is any other value, the `rejoin_rule` does not affect the auth for an event.

When a join or invite is being processed, the server must first determine if that
user has a prior membership event. If the user does not have a prior membership event,
the `rejoin_rule` does not apply. If the user does have a prior membership event,
the following conditions do apply:

1. If the previous membership is not explicitly `leave`, `rejoin_rule` does not apply.
For example, bans still ban, invites still invite, and never having been in the room
does not let you use `rejoin_rule` to get in.
2. If the `rejoin_rule` is `forbidden`, or implied to be `forbidden`, reject.
3. If the previous membership is explicitly `leave`, the server must look at the membership
previous to that membership to make a decision:
1. If the `rejoin_rule` is `join` and the membership previous to `leave` is not `join`
then reject. Else accept.
2. If the `rejoin_rule` is `invite` and the membership previous to `leave` is not
`join` or `invite`, reject. Else accept.
KitsuneRal marked this conversation as resolved.
Show resolved Hide resolved
Comment on lines +46 to +55
Copy link

@erkinalp erkinalp Feb 23, 2021

Choose a reason for hiding this comment

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

Suggested change
1. If the previous membership is not explicitly `leave`, `rejoin_rule` does not apply.
For example, bans still ban, invites still invite, and never having been in the room
does not let you use `rejoin_rule` to get in.
2. If the `rejoin_rule` is `forbidden`, or implied to be `forbidden`, reject.
3. If the previous membership is explicitly `leave`, the server must look at the membership
previous to that membership to make a decision:
1. If the `rejoin_rule` is `join` and the membership previous to `leave` is not `join`
then reject. Else accept.
2. If the `rejoin_rule` is `invite` and the membership previous to `leave` is not
`join` or `invite`, reject. Else accept.
1. If the previous membership is not explicitly `leave`, `rejoin_rule` does not apply.
For example, bans still ban, invites still invite, and never having been in the room
does not let you use `rejoin_rule` to get in. The rejoin rule `block` is an exception,
where leaving a room for any reason prevents further rejoins, even if invited.
2. If the `rejoin_rule` is `forbidden`, or implied to be `forbidden`, reject.
3. If the previous membership is explicitly `leave`, the server must look at the membership
previous to that membership to make a decision:
1. If the `rejoin_rule` is `join` and the membership previous to `leave` is not `join`
then reject. Else accept.
2. If the `rejoin_rule` is `comeback` and the membership previous to `leave` is not
`join` or member was put into the leave state by some other member, then reject.
Else accept.
3. If the `rejoin_rule` is `invite` and the membership previous to `leave` is not
`join` or `invite`, reject. Else accept.


In short: the member must `leave` before they can have a `rejoin_rule` allow them in
again.

**Known limitation**: If the user were to be kicked twice they would not be allowed
back into the room despite a reasonable `rejoin_rule`. This is an intentional limitation
of the proposal to prevent servers from having to traverse the entire room state history
to find a previous membership event. For example, if a server had to traverse the state
history for Matrix HQ (if it were private) every time someone wanted to join the server
could end up exhausting resources. For simplicity, the server is only expected to look
at the most recent 2 memberships maximum, as per above. This limitation can be resolved
with a regular invite.


## Security considerations

Room operators are expected to be aware of the room access controls available to them,
much like they are expected to understand the ones currently available. This join rule
alteration may not be applicable to their room, or could open them up to an attack they
are not comfortable with. For this reason, the default behaviour of the proposal is to
maintain existing expectations for join rules.


## Alternative solutions

Instead of re-using the join rules event we could introduce a new state event. Although
possible, and would likely have the same semantics, it is not immediately obvious what
the benefit of more state events would bring to Matrix. It is often preferred to reuse
existing constructs where possible, such as the aptly named "join rules" event.

Further, this proposal could be done in the form of introducing new `join_rule`s instead
of a new field. Given the `rejoin_rule` only takes effect when `join_rule == "invite"`,
we could redefine the `join_rule` to be `[public, invite, rejoin_invite, rejoin_join]`
or similar. This would simplify the definition, however it does conflate two concerns
and behaviours.