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

Managed Mjolnirs are being informed of every event sent to the appservice #412

Open
Gnuxie opened this issue Nov 4, 2022 · 3 comments
Open
Labels
A-Appservice S-Critical Prevents work, causes data loss and/or has no workaround T-Task Refactoring, enabling or disabling functionality, other engineering tasks X-Release-Blocker This issue must be resolved before the next release can be made

Comments

@Gnuxie
Copy link
Contributor

Gnuxie commented Nov 4, 2022

The mjolnirs will still compare the event against their joined/protected rooms deeper in the chain, so they won't act on any events in rooms they're not joined to or protecting, but this still is problematic and we should have defence in depth.

mjolnir/src/Mjolnir.ts

Lines 533 to 558 in 818e4cf

private async handleEvent(roomId: string, event: any) {
// Check for UISI errors
if (roomId === this.managementRoomId) {
if (event['type'] === 'm.room.message' && event['content'] && event['content']['body']) {
if (event['content']['body'] === "** Unable to decrypt: The sender's device has not sent us the keys for this message. **") {
// UISI
await this.client.unstableApis.addReactionToEvent(roomId, event['event_id'], '⚠');
await this.client.unstableApis.addReactionToEvent(roomId, event['event_id'], 'UISI');
await this.client.unstableApis.addReactionToEvent(roomId, event['event_id'], '🚨');
}
}
}
// Check for updated ban lists before checking protected rooms - the ban lists might be protected
// themselves.
const policyList = this.policyLists.find(list => list.roomId === roomId);
if (policyList !== undefined) {
if (ALL_BAN_LIST_RULE_TYPES.includes(event['type']) || event['type'] === 'm.room.redaction') {
policyList.updateForEvent(event.event_id)
}
}
if (event.sender !== this.clientUserId) {
this.protectedRoomsTracker.handleEvent(roomId, event);
}
}

if (!this.protectedRooms.has(roomId)) {
return; // We're not protecting this room.
}

Inspiration should be taken from bridges on how they manage tracking of rooms. The thing is you shouldn't do this naively because it does duplicate effort. Mjolnir instance already track which rooms they are joined to and are protecting, we just don't have a way to map from a roomId to a set of Mjolnirs that are joined to that room.

public onEvent(request: Request<WeakEvent>, context: BridgeContext) {
// We honestly don't know how we're going to map from bridge to user
// https://github.com/matrix-org/matrix-appservice-bridge/blob/6046d31c54d461ad53e6d6e244ce2d944b62f890/src/components/room-bridge-store.ts
// looks like it might work, but we will ask, figure it out later.
[...this.mjolnirs.values()].forEach((mj: ManagedMjolnir) => mj.onEvent(request));
}

@Gnuxie Gnuxie added T-Task Refactoring, enabling or disabling functionality, other engineering tasks A-Appservice labels Nov 4, 2022
@Gnuxie
Copy link
Contributor Author

Gnuxie commented Nov 4, 2022

Loosely related #411

@Gnuxie
Copy link
Contributor Author

Gnuxie commented Dec 8, 2022

One way to do this is to:

  • Provision bridge intents ourselves (whether we extend matrix-appservice-bridge or wrap the bridge class or provide some kind of injection API is TBD).
  • Special kind of intent client that has the same listeners as matrixEmitter it is just transparent with respect to whether the events are sourced from /sync or appservice magic
  • The intent only emits events when .start has been called like the bot-sdk syncing client
  • We keep a persisted cache of the joined rooms for each intent. We always update this cache when we notice the intent being added/removed from rooms.
  • When the intent is created, we call joined_rooms and shouldn't have to again.
  • We recognize that although the transactions api in theory ensures the appservice is informed about all events, this isn't always the case, state resets happen and we already had a misconfiguration issue on mjolnir.matrix.org where Synapse "forgot the appservice existed".
  • To counter this whenever we get an error for "user not in room" or "user banned" etc we invalidate the cache for that intent and recalled joined_rooms. This has to be a hidden process that is always active regardless of whether .start has been called and the intent is "running".
  • We need to decide on the semantics of .start and .stop, does the appservice queue events while the intent has been stopped? Or are we free to discard them?

@Gnuxie
Copy link
Contributor Author

Gnuxie commented Dec 8, 2022

Technically is blocked on #415 but if you just use the data store interface you'll be able to get most of it done

@Gnuxie Gnuxie added S-Critical Prevents work, causes data loss and/or has no workaround X-Release-Blocker This issue must be resolved before the next release can be made labels Dec 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Appservice S-Critical Prevents work, causes data loss and/or has no workaround T-Task Refactoring, enabling or disabling functionality, other engineering tasks X-Release-Blocker This issue must be resolved before the next release can be made
Projects
None yet
Development

No branches or pull requests

1 participant