mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-29 14:18:49 +03:00
Add menu option to enable encryption in a private room
This commit is contained in:
parent
626c680911
commit
36cb62748b
6 changed files with 142 additions and 15 deletions
|
@ -342,6 +342,8 @@ public:
|
||||||
|
|
||||||
//! Mark a room that uses e2e encryption.
|
//! Mark a room that uses e2e encryption.
|
||||||
void setEncryptedRoom(const std::string &room_id);
|
void setEncryptedRoom(const std::string &room_id);
|
||||||
|
bool isRoomEncrypted(const std::string &room_id);
|
||||||
|
|
||||||
//! Save the public keys for a device.
|
//! Save the public keys for a device.
|
||||||
void saveDeviceKeys(const std::string &device_id);
|
void saveDeviceKeys(const std::string &device_id);
|
||||||
void getDeviceKeys(const std::string &device_id);
|
void getDeviceKeys(const std::string &device_id);
|
||||||
|
|
|
@ -5,16 +5,17 @@
|
||||||
|
|
||||||
#include "Cache.h"
|
#include "Cache.h"
|
||||||
|
|
||||||
class FlatButton;
|
|
||||||
class TextField;
|
|
||||||
class QHBoxLayout;
|
|
||||||
class Avatar;
|
class Avatar;
|
||||||
class QPixmap;
|
class FlatButton;
|
||||||
class QLayout;
|
|
||||||
class QLabel;
|
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class TextField;
|
class QHBoxLayout;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
|
class QLabel;
|
||||||
|
class QLayout;
|
||||||
|
class QPixmap;
|
||||||
|
class TextField;
|
||||||
|
class TextField;
|
||||||
|
class Toggle;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class QSharedPointer;
|
class QSharedPointer;
|
||||||
|
@ -84,6 +85,7 @@ public:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void closing();
|
void closing();
|
||||||
|
void enableEncryptionError(const QString &msg);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
@ -98,13 +100,15 @@ private:
|
||||||
void setupEditButton();
|
void setupEditButton();
|
||||||
//! Retrieve the current room information from cache.
|
//! Retrieve the current room information from cache.
|
||||||
void retrieveRoomInfo();
|
void retrieveRoomInfo();
|
||||||
|
void enableEncryption();
|
||||||
|
|
||||||
//! Whether the user would be able to change the name or the topic of the room.
|
//! Whether the user would be able to change the name or the topic of the room.
|
||||||
bool hasEditRights_ = true;
|
bool hasEditRights_ = true;
|
||||||
|
bool usesEncryption_ = false;
|
||||||
QHBoxLayout *editLayout_;
|
QHBoxLayout *editLayout_;
|
||||||
|
|
||||||
// Button section
|
// Button section
|
||||||
FlatButton *saveBtn_;
|
FlatButton *okBtn_;
|
||||||
FlatButton *cancelBtn_;
|
FlatButton *cancelBtn_;
|
||||||
|
|
||||||
FlatButton *editFieldsBtn_;
|
FlatButton *editFieldsBtn_;
|
||||||
|
@ -116,6 +120,7 @@ private:
|
||||||
TopSection *topSection_;
|
TopSection *topSection_;
|
||||||
|
|
||||||
QComboBox *accessCombo;
|
QComboBox *accessCombo;
|
||||||
|
Toggle *encryptionToggle_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // dialogs
|
} // dialogs
|
||||||
|
|
26
src/Cache.cc
26
src/Cache.cc
|
@ -60,7 +60,7 @@ constexpr auto DEVICES_DB("devices");
|
||||||
//! device_id -> device keys
|
//! device_id -> device keys
|
||||||
constexpr auto DEVICE_KEYS_DB("device_keys");
|
constexpr auto DEVICE_KEYS_DB("device_keys");
|
||||||
//! room_ids that have encryption enabled.
|
//! room_ids that have encryption enabled.
|
||||||
// constexpr auto ENCRYPTED_ROOMS_DB("encrypted_rooms");
|
constexpr auto ENCRYPTED_ROOMS_DB("encrypted_rooms");
|
||||||
|
|
||||||
//! MegolmSessionIndex -> pickled OlmInboundGroupSession
|
//! MegolmSessionIndex -> pickled OlmInboundGroupSession
|
||||||
constexpr auto INBOUND_MEGOLM_SESSIONS_DB("inbound_megolm_sessions");
|
constexpr auto INBOUND_MEGOLM_SESSIONS_DB("inbound_megolm_sessions");
|
||||||
|
@ -184,6 +184,30 @@ Cache::setup()
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cache::setEncryptedRoom(const std::string &room_id)
|
||||||
|
{
|
||||||
|
log::db()->info("mark room {} as encrypted", room_id);
|
||||||
|
|
||||||
|
auto txn = lmdb::txn::begin(env_);
|
||||||
|
auto db = lmdb::dbi::open(txn, ENCRYPTED_ROOMS_DB, MDB_CREATE);
|
||||||
|
lmdb::dbi_put(txn, db, lmdb::val(room_id), lmdb::val("0"));
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Cache::isRoomEncrypted(const std::string &room_id)
|
||||||
|
{
|
||||||
|
lmdb::val unused;
|
||||||
|
|
||||||
|
auto txn = lmdb::txn::begin(env_);
|
||||||
|
auto db = lmdb::dbi::open(txn, ENCRYPTED_ROOMS_DB, MDB_CREATE);
|
||||||
|
auto res = lmdb::dbi_get(txn, db, lmdb::val(room_id), unused);
|
||||||
|
txn.commit();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Device Management
|
// Device Management
|
||||||
//
|
//
|
||||||
|
|
|
@ -245,6 +245,10 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
typingRefresher_->stop();
|
typingRefresher_->stop();
|
||||||
|
|
||||||
|
if (current_room_.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
http::v2::client()->stop_typing(
|
http::v2::client()->stop_typing(
|
||||||
current_room_.toStdString(), [](mtx::http::RequestErr err) {
|
current_room_.toStdString(), [](mtx::http::RequestErr err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
|
#include "ChatPage.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "FlatButton.h"
|
#include "FlatButton.h"
|
||||||
|
#include "Logging.hpp"
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
#include "Painter.h"
|
#include "Painter.h"
|
||||||
#include "TextField.h"
|
#include "TextField.h"
|
||||||
#include "Theme.h"
|
#include "Theme.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "dialogs/RoomSettings.hpp"
|
#include "dialogs/RoomSettings.hpp"
|
||||||
|
#include "ui/ToggleButton.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
@ -188,8 +192,8 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
|
||||||
layout->setSpacing(15);
|
layout->setSpacing(15);
|
||||||
layout->setMargin(20);
|
layout->setMargin(20);
|
||||||
|
|
||||||
saveBtn_ = new FlatButton("SAVE", this);
|
okBtn_ = new FlatButton(tr("OK"), this);
|
||||||
saveBtn_->setFontSize(conf::btn::fontSize);
|
okBtn_->setFontSize(conf::btn::fontSize);
|
||||||
cancelBtn_ = new FlatButton(tr("CANCEL"), this);
|
cancelBtn_ = new FlatButton(tr("CANCEL"), this);
|
||||||
cancelBtn_->setFontSize(conf::btn::fontSize);
|
cancelBtn_->setFontSize(conf::btn::fontSize);
|
||||||
|
|
||||||
|
@ -197,7 +201,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
|
||||||
btnLayout->setSpacing(0);
|
btnLayout->setSpacing(0);
|
||||||
btnLayout->setMargin(0);
|
btnLayout->setMargin(0);
|
||||||
btnLayout->addStretch(1);
|
btnLayout->addStretch(1);
|
||||||
btnLayout->addWidget(saveBtn_);
|
btnLayout->addWidget(okBtn_);
|
||||||
btnLayout->addWidget(cancelBtn_);
|
btnLayout->addWidget(cancelBtn_);
|
||||||
|
|
||||||
auto notifOptionLayout_ = new QHBoxLayout;
|
auto notifOptionLayout_ = new QHBoxLayout;
|
||||||
|
@ -236,6 +240,61 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
|
||||||
accessOptionLayout->addWidget(accessLabel);
|
accessOptionLayout->addWidget(accessLabel);
|
||||||
accessOptionLayout->addWidget(accessCombo);
|
accessOptionLayout->addWidget(accessCombo);
|
||||||
|
|
||||||
|
auto encryptionOptionLayout = new QHBoxLayout;
|
||||||
|
encryptionOptionLayout->setMargin(SettingsMargin);
|
||||||
|
auto encryptionLabel = new QLabel(tr("Encryption"), this);
|
||||||
|
encryptionLabel->setStyleSheet("font-size: 15px;");
|
||||||
|
encryptionToggle_ = new Toggle(this);
|
||||||
|
connect(encryptionToggle_, &Toggle::toggled, this, [this](bool isOn) {
|
||||||
|
if (isOn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QFont font;
|
||||||
|
font.setPixelSize(conf::fontSize);
|
||||||
|
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setIcon(QMessageBox::Question);
|
||||||
|
msgBox.setFont(font);
|
||||||
|
msgBox.setWindowTitle(tr("End-to-End Encryption"));
|
||||||
|
msgBox.setText(tr(
|
||||||
|
"Encryption is currently experimental and things might break unexpectedly. <br>"
|
||||||
|
"Please take note that it can't be disabled afterwards."));
|
||||||
|
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Save);
|
||||||
|
int ret = msgBox.exec();
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case QMessageBox::Ok: {
|
||||||
|
encryptionToggle_->setState(false);
|
||||||
|
encryptionToggle_->setEnabled(false);
|
||||||
|
enableEncryption();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
encryptionToggle_->setState(true);
|
||||||
|
encryptionToggle_->setEnabled(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
encryptionOptionLayout->addWidget(encryptionLabel);
|
||||||
|
encryptionOptionLayout->addWidget(encryptionToggle_, 0, Qt::AlignBottom | Qt::AlignRight);
|
||||||
|
|
||||||
|
// Disable encryption button.
|
||||||
|
if (usesEncryption_) {
|
||||||
|
encryptionToggle_->setState(false);
|
||||||
|
encryptionToggle_->setEnabled(false);
|
||||||
|
} else {
|
||||||
|
encryptionToggle_->setState(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide encryption option for public rooms.
|
||||||
|
if (!usesEncryption_ && (info_.join_rule == JoinRule::Public)) {
|
||||||
|
encryptionToggle_->hide();
|
||||||
|
encryptionLabel->hide();
|
||||||
|
}
|
||||||
|
|
||||||
QFont font;
|
QFont font;
|
||||||
font.setPixelSize(18);
|
font.setPixelSize(18);
|
||||||
font.setWeight(70);
|
font.setWeight(70);
|
||||||
|
@ -255,10 +314,18 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
|
||||||
layout->addLayout(editLayout_);
|
layout->addLayout(editLayout_);
|
||||||
layout->addLayout(notifOptionLayout_);
|
layout->addLayout(notifOptionLayout_);
|
||||||
layout->addLayout(accessOptionLayout);
|
layout->addLayout(accessOptionLayout);
|
||||||
|
layout->addLayout(encryptionOptionLayout);
|
||||||
layout->addLayout(btnLayout);
|
layout->addLayout(btnLayout);
|
||||||
|
|
||||||
connect(cancelBtn_, &QPushButton::clicked, this, &RoomSettings::closing);
|
connect(cancelBtn_, &QPushButton::clicked, this, &RoomSettings::closing);
|
||||||
connect(saveBtn_, &QPushButton::clicked, this, &RoomSettings::saveSettings);
|
connect(okBtn_, &QPushButton::clicked, this, &RoomSettings::saveSettings);
|
||||||
|
|
||||||
|
connect(this, &RoomSettings::enableEncryptionError, this, [this](const QString &msg) {
|
||||||
|
encryptionToggle_->setState(true);
|
||||||
|
encryptionToggle_->setEnabled(true);
|
||||||
|
|
||||||
|
emit ChatPage::instance()->showNotification(msg);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -308,6 +375,7 @@ void
|
||||||
RoomSettings::retrieveRoomInfo()
|
RoomSettings::retrieveRoomInfo()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
usesEncryption_ = cache::client()->isRoomEncrypted(room_id_.toStdString());
|
||||||
info_ = cache::client()->singleRoomInfo(room_id_.toStdString());
|
info_ = cache::client()->singleRoomInfo(room_id_.toStdString());
|
||||||
setAvatar(QImage::fromData(cache::client()->image(info_.avatar_url)));
|
setAvatar(QImage::fromData(cache::client()->image(info_.avatar_url)));
|
||||||
} catch (const lmdb::error &e) {
|
} catch (const lmdb::error &e) {
|
||||||
|
@ -339,6 +407,28 @@ RoomSettings::saveSettings()
|
||||||
closing();
|
closing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RoomSettings::enableEncryption()
|
||||||
|
{
|
||||||
|
const auto room_id = room_id_.toStdString();
|
||||||
|
http::v2::client()->enable_encryption(
|
||||||
|
room_id, [room_id, this](const mtx::responses::EventId &, mtx::http::RequestErr err) {
|
||||||
|
if (err) {
|
||||||
|
int status_code = static_cast<int>(err->status_code);
|
||||||
|
log::net()->warn("failed to enable encryption in room ({}): {} {}",
|
||||||
|
room_id,
|
||||||
|
err->matrix_error.error,
|
||||||
|
status_code);
|
||||||
|
emit enableEncryptionError(
|
||||||
|
tr("Failed to enable encryption: %1")
|
||||||
|
.arg(QString::fromStdString(err->matrix_error.error)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log::net()->info("enabled encryption on room ({})", room_id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RoomSettings::paintEvent(QPaintEvent *)
|
RoomSettings::paintEvent(QPaintEvent *)
|
||||||
{
|
{
|
||||||
|
|
|
@ -284,6 +284,8 @@ TimelineView::parseMessageEvent(const mtx::events::collections::TimelineEvents &
|
||||||
auto decrypted =
|
auto decrypted =
|
||||||
parseEncryptedEvent(mpark::get<EncryptedEvent<msg::Encrypted>>(event));
|
parseEncryptedEvent(mpark::get<EncryptedEvent<msg::Encrypted>>(event));
|
||||||
return parseMessageEvent(decrypted, direction);
|
return parseMessageEvent(decrypted, direction);
|
||||||
|
} else if (mpark::holds_alternative<StateEvent<state::Encryption>>(event)) {
|
||||||
|
cache::client()->setEncryptedRoom(room_id_.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
Loading…
Reference in a new issue