From 791a9d0a4d04a6340e04a303d5e055acfd8ed53a Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Wed, 16 May 2018 23:30:50 +0300 Subject: [PATCH] Hide the edit menu when the user doesn't have enough power --- cmake/MatrixStructs.cmake | 2 +- include/Cache.h | 6 ++++ include/dialogs/RoomSettings.hpp | 6 ++++ src/Cache.cc | 39 +++++++++++++++++++++ src/dialogs/RoomSettings.cpp | 60 ++++++++++++++++++++++---------- 5 files changed, 93 insertions(+), 20 deletions(-) diff --git a/cmake/MatrixStructs.cmake b/cmake/MatrixStructs.cmake index cf8e471..b010ad2 100644 --- a/cmake/MatrixStructs.cmake +++ b/cmake/MatrixStructs.cmake @@ -21,7 +21,7 @@ ExternalProject_Add( MatrixStructs GIT_REPOSITORY https://github.com/mujx/matrix-structs - GIT_TAG 55a1a5aad0ead3cc45475fc1aed1bf54a56e352c + GIT_TAG ddba5a597be4bafd20e1dd37e5e7b7dc798b0997 BUILD_IN_SOURCE 1 SOURCE_DIR ${MATRIX_STRUCTS_ROOT} diff --git a/include/Cache.h b/include/Cache.h index 20f277a..d2574b7 100644 --- a/include/Cache.h +++ b/include/Cache.h @@ -206,6 +206,12 @@ public: bool isFormatValid(); void setCurrentFormat(); + //! Check if the given user has power leve greater than than + //! lowest power level of the given events. + bool hasEnoughPowerLevel(const std::vector &eventTypes, + const std::string &room_id, + const std::string &user_id); + //! Retrieves the saved room avatar. QImage getRoomAvatar(const QString &id); QImage getRoomAvatar(const std::string &id); diff --git a/include/dialogs/RoomSettings.hpp b/include/dialogs/RoomSettings.hpp index f414506..1434eee 100644 --- a/include/dialogs/RoomSettings.hpp +++ b/include/dialogs/RoomSettings.hpp @@ -7,6 +7,7 @@ class FlatButton; class TextField; +class QHBoxLayout; class Avatar; class QPixmap; class QLayout; @@ -91,6 +92,11 @@ private: static constexpr int AvatarSize = 64; void setAvatar(const QImage &img) { avatarImg_ = img; } + void setupEditButton(); + + //! Whether the user would be able to change the name or the topic of the room. + bool hasEditRights_ = true; + QHBoxLayout *editLayout_; // Button section FlatButton *saveBtn_; diff --git a/src/Cache.cc b/src/Cache.cc index 31e86a6..c055ab0 100644 --- a/src/Cache.cc +++ b/src/Cache.cc @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +#include #include #include @@ -1223,6 +1224,44 @@ Cache::isNotificationSent(const std::string &event_id) return res; } +bool +Cache::hasEnoughPowerLevel(const std::vector &eventTypes, + const std::string &room_id, + const std::string &user_id) +{ + using namespace mtx::events; + using namespace mtx::events::state; + + auto txn = lmdb::txn::begin(env_); + auto db = getStatesDb(txn, room_id); + + uint16_t min_event_level = std::numeric_limits::max(); + uint16_t user_level = std::numeric_limits::min(); + + lmdb::val event; + bool res = lmdb::dbi_get(txn, db, lmdb::val(to_string(EventType::RoomPowerLevels)), event); + + if (res) { + try { + StateEvent msg = + json::parse(std::string(event.data(), event.size())); + + user_level = msg.content.user_level(user_id); + + for (const auto &ty : eventTypes) + min_event_level = + std::min(min_event_level, + (uint16_t)msg.content.state_level(to_string(ty))); + } catch (const json::exception &e) { + qWarning() << "hasEnoughPowerLevel: " << e.what(); + } + } + + txn.commit(); + + return user_level >= min_event_level; +} + QHash Cache::DisplayNames; QHash Cache::AvatarUrls; diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp index 4a7ea4f..294969d 100644 --- a/src/dialogs/RoomSettings.cpp +++ b/src/dialogs/RoomSettings.cpp @@ -11,11 +11,13 @@ #include #include #include +#include #include #include #include using namespace dialogs; +using namespace mtx::events; EditModal::EditModal(const QString &roomId, QWidget *parent) : QWidget(parent) @@ -86,7 +88,7 @@ EditModal::EditModal(const QString &roomId, QWidget *parent) &StateEventProxy::stateEventSent, this, [this, proxy, newName]() { - proxy->deleteLater(); + Q_UNUSED(proxy); errorField_->hide(); emit nameChanged(newName); close(); @@ -96,7 +98,7 @@ EditModal::EditModal(const QString &roomId, QWidget *parent) &StateEventProxy::stateEventError, this, [this, proxy, newName](const QString &msg) { - proxy->deleteLater(); + Q_UNUSED(proxy); errorField_->setText(msg); errorField_->show(); }); @@ -113,7 +115,7 @@ EditModal::EditModal(const QString &roomId, QWidget *parent) &StateEventProxy::stateEventSent, this, [this, proxy, newTopic]() { - proxy->deleteLater(); + Q_UNUSED(proxy); errorField_->hide(); close(); }); @@ -122,7 +124,7 @@ EditModal::EditModal(const QString &roomId, QWidget *parent) &StateEventProxy::stateEventError, this, [this, proxy, newTopic](const QString &msg) { - proxy->deleteLater(); + Q_UNUSED(proxy); errorField_->setText(msg); errorField_->show(); }); @@ -242,9 +244,43 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) auto menuLabel = new QLabel("Room Settings", this); menuLabel->setFont(font); + topSection_ = new TopSection(info_, avatarImg_, this); + + editLayout_ = new QHBoxLayout; + editLayout_->setMargin(0); + editLayout_->addWidget(topSection_); + + setupEditButton(); + + layout->addWidget(menuLabel); + layout->addLayout(editLayout_); + layout->addLayout(notifOptionLayout_); + layout->addLayout(accessOptionLayout); + layout->addLayout(btnLayout); + + connect(cancelBtn_, &QPushButton::clicked, this, &RoomSettings::closing); + connect(saveBtn_, &QPushButton::clicked, this, &RoomSettings::saveSettings); +} + +void +RoomSettings::setupEditButton() +{ + try { + QSettings settings; + auto userId = settings.value("auth/user_id").toString().toStdString(); + + hasEditRights_ = cache::client()->hasEnoughPowerLevel( + {EventType::RoomName, EventType::RoomTopic}, room_id_.toStdString(), userId); + } catch (const lmdb::error &e) { + qWarning() << "lmdb error" << e.what(); + } + constexpr int buttonSize = 36; constexpr int iconSize = buttonSize / 2; + if (!hasEditRights_) + return; + QIcon editIcon; editIcon.addFile(":/icons/icons/ui/edit.svg"); editFieldsBtn_ = new FlatButton(this); @@ -264,21 +300,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent) }); }); - topSection_ = new TopSection(info_, avatarImg_, this); - - auto editLayout = new QHBoxLayout; - editLayout->setMargin(0); - editLayout->addWidget(topSection_); - editLayout->addWidget(editFieldsBtn_, 0, Qt::AlignRight | Qt::AlignTop); - - layout->addWidget(menuLabel); - layout->addLayout(editLayout); - layout->addLayout(notifOptionLayout_); - layout->addLayout(accessOptionLayout); - layout->addLayout(btnLayout); - - connect(cancelBtn_, &QPushButton::clicked, this, &RoomSettings::closing); - connect(saveBtn_, &QPushButton::clicked, this, &RoomSettings::saveSettings); + editLayout_->addWidget(editFieldsBtn_, 0, Qt::AlignRight | Qt::AlignTop); } void