Allow blocking invites from people you don't share a room with

Matrix currently has a significant moderation loophole, thanks to
invites. Right now, anyone can invite anyone to a room - and clients
like NeoChat will gladly display these rooms to them and even give you
a notification.

However, this creates a pretty easy attack since room names and avatars
are arbitrary and this is a known vector of harassment in the Matrix
community. There's currently no tools to block this server-side, so
let's try to improve the situation where we can.

This adds a new setting to the Security page, wherein it allows you to
block invites from people you don't share a room with. This prevents the
notification from appearing and NeoChat will attempt to leave the room
immediately.

Since this depends on MSC 2666 - a currently unstable feature - the
server may not support it and NeoChat will disable the setting in this
case.
This commit is contained in:
Joshua Goins
2024-07-25 15:03:22 -04:00
parent 11475259a1
commit ef5585d312
8 changed files with 122 additions and 17 deletions

View File

@@ -41,6 +41,7 @@
#include "events/joinrulesevent.h"
#include "events/pollevent.h"
#include "filetransferpseudojob.h"
#include "jobs/neochatgetcommonroomsjob.h"
#include "neochatconfig.h"
#include "notificationsmanager.h"
#include "roomlastmessageprovider.h"
@@ -129,14 +130,38 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS
return;
}
auto roomMemberEvent = currentState().get<RoomMemberEvent>(localMember().id());
QImage avatar_image;
if (roomMemberEvent && !member(roomMemberEvent->senderId()).avatarUrl().isEmpty()) {
avatar_image = memberAvatar(roomMemberEvent->senderId()).get(this->connection(), 128, [] {});
auto showNotification = [this, roomMemberEvent] {
QImage avatar_image;
if (roomMemberEvent && !member(roomMemberEvent->senderId()).avatarUrl().isEmpty()) {
avatar_image = memberAvatar(roomMemberEvent->senderId()).get(this->connection(), 128, [] {});
} else {
qWarning() << "using this room's avatar";
avatar_image = avatar(128);
}
NotificationsManager::instance().postInviteNotification(this,
displayName(),
member(roomMemberEvent->senderId()).htmlSafeDisplayName(),
avatar_image);
};
if (NeoChatConfig::allowUnknownInvites()) {
showNotification();
} else {
qWarning() << "using this room's avatar";
avatar_image = avatar(128);
auto job = this->connection()->callApi<NeochatGetCommonRoomsJob>(roomMemberEvent->senderId());
connect(job, &BaseJob::result, this, [this, job, roomMemberEvent, showNotification] {
QJsonObject replyData = job->jsonData();
if (replyData.contains(QStringLiteral("joined"))) {
const bool inAnyOfOurRooms = !replyData[QStringLiteral("joined")].toArray().isEmpty();
if (inAnyOfOurRooms) {
showNotification();
} else {
leaveRoom();
}
}
});
}
NotificationsManager::instance().postInviteNotification(this, displayName(), member(roomMemberEvent->senderId()).htmlSafeDisplayName(), avatar_image);
},
Qt::SingleShotConnection);
connect(this, &Room::changed, this, [this] {