Add menu option to enable encryption in a private room

This commit is contained in:
Konstantinos Sideris 2018-06-12 09:45:26 +03:00
parent 626c680911
commit 36cb62748b
6 changed files with 142 additions and 15 deletions

View file

@ -342,6 +342,8 @@ public:
//! Mark a room that uses e2e encryption.
void setEncryptedRoom(const std::string &room_id);
bool isRoomEncrypted(const std::string &room_id);
//! Save the public keys for a device.
void saveDeviceKeys(const std::string &device_id);
void getDeviceKeys(const std::string &device_id);

View file

@ -5,16 +5,17 @@
#include "Cache.h"
class FlatButton;
class TextField;
class QHBoxLayout;
class Avatar;
class QPixmap;
class QLayout;
class QLabel;
class FlatButton;
class QComboBox;
class TextField;
class QHBoxLayout;
class QLabel;
class QLabel;
class QLayout;
class QPixmap;
class TextField;
class TextField;
class Toggle;
template<class T>
class QSharedPointer;
@ -84,6 +85,7 @@ public:
signals:
void closing();
void enableEncryptionError(const QString &msg);
protected:
void paintEvent(QPaintEvent *event) override;
@ -98,13 +100,15 @@ private:
void setupEditButton();
//! Retrieve the current room information from cache.
void retrieveRoomInfo();
void enableEncryption();
//! 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_;
// Button section
FlatButton *saveBtn_;
FlatButton *okBtn_;
FlatButton *cancelBtn_;
FlatButton *editFieldsBtn_;
@ -116,6 +120,7 @@ private:
TopSection *topSection_;
QComboBox *accessCombo;
Toggle *encryptionToggle_;
};
} // dialogs

View file

@ -60,7 +60,7 @@ constexpr auto DEVICES_DB("devices");
//! device_id -> device keys
constexpr auto DEVICE_KEYS_DB("device_keys");
//! room_ids that have encryption enabled.
// constexpr auto ENCRYPTED_ROOMS_DB("encrypted_rooms");
constexpr auto ENCRYPTED_ROOMS_DB("encrypted_rooms");
//! MegolmSessionIndex -> pickled OlmInboundGroupSession
constexpr auto INBOUND_MEGOLM_SESSIONS_DB("inbound_megolm_sessions");
@ -184,6 +184,30 @@ Cache::setup()
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
//

View file

@ -245,6 +245,10 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
return;
typingRefresher_->stop();
if (current_room_.isEmpty())
return;
http::v2::client()->stop_typing(
current_room_.toStdString(), [](mtx::http::RequestErr err) {
if (err) {

View file

@ -1,16 +1,20 @@
#include "Avatar.h"
#include "ChatPage.h"
#include "Config.h"
#include "FlatButton.h"
#include "Logging.hpp"
#include "MatrixClient.h"
#include "Painter.h"
#include "TextField.h"
#include "Theme.h"
#include "Utils.h"
#include "dialogs/RoomSettings.hpp"
#include "ui/ToggleButton.h"
#include <QApplication>
#include <QComboBox>
#include <QLabel>
#include <QMessageBox>
#include <QPainter>
#include <QPixmap>
#include <QSettings>
@ -188,8 +192,8 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
layout->setSpacing(15);
layout->setMargin(20);
saveBtn_ = new FlatButton("SAVE", this);
saveBtn_->setFontSize(conf::btn::fontSize);
okBtn_ = new FlatButton(tr("OK"), this);
okBtn_->setFontSize(conf::btn::fontSize);
cancelBtn_ = new FlatButton(tr("CANCEL"), this);
cancelBtn_->setFontSize(conf::btn::fontSize);
@ -197,7 +201,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
btnLayout->setSpacing(0);
btnLayout->setMargin(0);
btnLayout->addStretch(1);
btnLayout->addWidget(saveBtn_);
btnLayout->addWidget(okBtn_);
btnLayout->addWidget(cancelBtn_);
auto notifOptionLayout_ = new QHBoxLayout;
@ -236,6 +240,61 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
accessOptionLayout->addWidget(accessLabel);
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;
font.setPixelSize(18);
font.setWeight(70);
@ -255,10 +314,18 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
layout->addLayout(editLayout_);
layout->addLayout(notifOptionLayout_);
layout->addLayout(accessOptionLayout);
layout->addLayout(encryptionOptionLayout);
layout->addLayout(btnLayout);
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
@ -308,7 +375,8 @@ void
RoomSettings::retrieveRoomInfo()
{
try {
info_ = cache::client()->singleRoomInfo(room_id_.toStdString());
usesEncryption_ = cache::client()->isRoomEncrypted(room_id_.toStdString());
info_ = cache::client()->singleRoomInfo(room_id_.toStdString());
setAvatar(QImage::fromData(cache::client()->image(info_.avatar_url)));
} catch (const lmdb::error &e) {
qWarning() << "failed to retrieve room info from cache" << room_id_;
@ -339,6 +407,28 @@ RoomSettings::saveSettings()
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
RoomSettings::paintEvent(QPaintEvent *)
{

View file

@ -284,6 +284,8 @@ TimelineView::parseMessageEvent(const mtx::events::collections::TimelineEvents &
auto decrypted =
parseEncryptedEvent(mpark::get<EncryptedEvent<msg::Encrypted>>(event));
return parseMessageEvent(decrypted, direction);
} else if (mpark::holds_alternative<StateEvent<state::Encryption>>(event)) {
cache::client()->setEncryptedRoom(room_id_.toStdString());
}
return nullptr;