From 1eba52bb7a79ae6d71788eae74bbeeb9d3ea26e9 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Thu, 19 Feb 2026 17:55:02 -0500 Subject: [PATCH] Add a way to block invites from all users This is a useful safety feature, not just for people under attack but also if you have no use for this feature. Currently this is gated for servers that support Matrix CSAPI 1.18. Fixes #662 --- src/libneochat/neochatconnection.cpp | 19 +++++++++++++++++++ src/libneochat/neochatconnection.h | 9 +++++++++ src/settings/NeoChatSecurityPage.qml | 22 ++++++++++++++++++---- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/libneochat/neochatconnection.cpp b/src/libneochat/neochatconnection.cpp index 81d9b3f2b..fcd9edf5d 100644 --- a/src/libneochat/neochatconnection.cpp +++ b/src/libneochat/neochatconnection.cpp @@ -62,6 +62,9 @@ void NeoChatConnection::connectSignals() if (type == u"m.identity_server"_s) { Q_EMIT identityServerChanged(); } + if (type == u"m.invite_permission_config"_s) { + Q_EMIT blockAllInvitesChanged(); + } }); connect(this, &NeoChatConnection::requestFailed, this, [this](BaseJob *job) { if (job->error() == BaseJob::UserConsentRequired) { @@ -636,4 +639,20 @@ void NeoChatConnection::setNoteForUser(const QString &userId, const QString ¬ setAccountData(QStringLiteral("org.kde.neochat.user_note"), object); } +bool NeoChatConnection::blockAllInvites() const +{ + return accountDataJson("m.invite_permission_config"_L1)["default_action"_L1].toString() == "block"_L1; +} + +void NeoChatConnection::setBlockAllInvites(bool block) +{ + auto object = accountDataJson(QStringLiteral("m.invite_permission_config")); + if (block) { + object["default_action"_L1] = "block"_L1; + } else { + object.remove("default_action"_L1); + } + setAccountData(QStringLiteral("m.invite_permission_config"), object); +} + #include "moc_neochatconnection.cpp" diff --git a/src/libneochat/neochatconnection.h b/src/libneochat/neochatconnection.h index 547f96a39..e92efb557 100644 --- a/src/libneochat/neochatconnection.h +++ b/src/libneochat/neochatconnection.h @@ -100,6 +100,11 @@ class NeoChatConnection : public Quotient::Connection */ Q_PROPERTY(bool isVerifiedSession READ isVerifiedSession NOTIFY ownSessionVerified) + /** + * @brief True if this account is blocking invites for all users. + */ + Q_PROPERTY(bool blockAllInvites READ blockAllInvites WRITE setBlockAllInvites NOTIFY blockAllInvitesChanged) + public: /** * @brief Defines the status after an attempt to change the password on an account. @@ -244,6 +249,9 @@ public: */ Q_INVOKABLE void setNoteForUser(const QString &userId, const QString ¬e); + bool blockAllInvites() const; + void setBlockAllInvites(bool block); + Q_SIGNALS: void globalUrlPreviewEnabledChanged(); void labelChanged(); @@ -283,6 +291,7 @@ Q_SIGNALS: void keyBackupUnlocked(); void keyBackupError(); + void blockAllInvitesChanged(); private: static bool m_globalUrlPreviewDefault; diff --git a/src/settings/NeoChatSecurityPage.qml b/src/settings/NeoChatSecurityPage.qml index 1e87a12f6..488e4049e 100644 --- a/src/settings/NeoChatSecurityPage.qml +++ b/src/settings/NeoChatSecurityPage.qml @@ -87,17 +87,31 @@ FormCard.FormCardPage { title: i18nc("@title:group", "Invites") } FormCard.FormCard { - FormCard.FormCheckDelegate { + FormCard.FormRadioDelegate { + text: i18nc("@info:label", "Everyone") + checked: !NeoChatConfig.rejectUnknownInvites && !root.connection.blockAllInvites + description: i18nc("@info:description", "Anyone can send you invites.") + } + + FormCard.FormRadioDelegate { id: rejectInvitationsDelegate - text: i18nc("@option:check", "Reject invitations from unknown users") - description: root.connection.canCheckMutualRooms ? i18nc("@info", "If enabled, NeoChat will reject invitations from users you don't share a room with.") : i18nc("@info", "Your server does not support this setting.") + text: i18nc("@option:check", "Known users") + description: root.connection.canCheckMutualRooms ? i18nc("@info", "Only users you share a room with can send you invites.") : i18nc("@info", "Your server does not support this setting.") checked: NeoChatConfig.rejectUnknownInvites enabled: !NeoChatConfig.isRejectUnknownInvitesImmutable && root.connection.canCheckMutualRooms - onToggled: { + onCheckedChanged: { NeoChatConfig.rejectUnknownInvites = checked; NeoChatConfig.save(); } } + + FormCard.FormRadioDelegate { + text: i18nc("@info:label", "No one") + checked: root.connection.blockAllInvites + enabled: root.connection.supportsMatrixSpecVersion("v1.18") + description: root.connection.supportsMatrixSpecVersion("v1.18") ? i18nc("@info:description", "No one can send you invites.") : i18nc("@info", "Your server does not support this setting.") + onCheckedChanged: root.connection.blockAllInvites = checked + } } FormCard.FormHeader { title: i18nc("@title:group", "Encryption")