Skip to content

Commit

Permalink
Upstream canSetState and canSendEvent from NeoChat and use to check b…
Browse files Browse the repository at this point in the history
…efore setting state to avoid pinging the server with no chance of success.
  • Loading branch information
nvrWhere committed Sep 15, 2024
1 parent b883c61 commit 67354eb
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 0 deletions.
10 changes: 10 additions & 0 deletions Quotient/events/roompowerlevelsevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,13 @@ int RoomPowerLevelsEvent::powerLevelForUser(const QString& userId) const
{
return users().value(userId, usersDefault());
}

bool RoomPowerLevelsEvent::canSendEvent(const QString& eventTypeId, const QString& memberId) const
{
return powerLevelForUser(memberId) >= powerLevelForEvent(eventTypeId);
}

bool RoomPowerLevelsEvent::canSetState(const QString& eventTypeId, const QString& memberId) const
{
return powerLevelForUser(memberId) >= powerLevelForState(eventTypeId);
}
6 changes: 6 additions & 0 deletions Quotient/events/roompowerlevelsevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,11 @@ class QUOTIENT_API RoomPowerLevelsEvent
int powerLevelForEvent(const QString& eventTypeId) const;
int powerLevelForState(const QString& eventTypeId) const;
int powerLevelForUser(const QString& userId) const;

//! Convenience function to check if the given member ID can set the given event type
bool canSendEvent(const QString& eventTypeId, const QString& memberId) const;

//! Convenience function to check if the given member ID can set the given state event type
bool canSetState(const QString& eventTypeId, const QString& memberId) const;
};
} // namespace Quotient
45 changes: 45 additions & 0 deletions Quotient/room.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2212,6 +2212,32 @@ QString Room::postJson(const QString& matrixType, const QJsonObject& eventConten
return d->sendEvent(loadEvent<RoomEvent>(matrixType, eventContent))->transactionId();
}

bool Room::canSendEvent(const QString &eventTypeId, const QString& memberId) const
{
int eventPowerLevel;
auto plEvent = currentState().get<RoomPowerLevelsEvent>();
if (plEvent == nullptr) {
eventPowerLevel = 0;
} else {
eventPowerLevel = plEvent->powerLevelForEvent(eventTypeId);
}

return memberEffectivePowerLevel(memberId) >= eventPowerLevel;
}

bool Room::canSetState(const QString &eventTypeId, const QString& memberId) const
{
int statePowerLevel;
const auto plEvent = currentState().get<RoomPowerLevelsEvent>();
if (plEvent == nullptr) {
statePowerLevel = 50;
} else {
statePowerLevel = plEvent->powerLevelForState(eventTypeId);
}

return memberEffectivePowerLevel(memberId) >= statePowerLevel;
}

SetRoomStateWithKeyJob* Room::setState(const StateEvent& evt)
{
return setState(evt.matrixType(), evt.stateKey(), evt.contentJson());
Expand All @@ -2226,25 +2252,40 @@ SetRoomStateWithKeyJob* Room::setState(const QString& evtType,

void Room::setName(const QString& newName)
{
if (!canSetState(RoomNameEvent::TypeId)) {
qCWarning(EVENTS) << "You do not have permission to rename the room";
}
setState<RoomNameEvent>(newName);
}

void Room::setCanonicalAlias(const QString& newAlias)
{
if (!canSetState(RoomCanonicalAliasEvent::TypeId)) {
qCWarning(EVENTS) << "You do not have permission to set the room canonical alias";
}
setState<RoomCanonicalAliasEvent>(newAlias, altAliases());
}

void Room::setPinnedEvents(const QStringList& events)
{
if (canSetState(RoomPinnedEventsEvent::TypeId)) {
qCWarning(EVENTS) << "You do not have permission to pin an event in the room";
}
setState<RoomPinnedEventsEvent>(events);
}
void Room::setLocalAliases(const QStringList& aliases)
{
if (canSetState(RoomCanonicalAliasEvent::TypeId)) {
qCWarning(EVENTS) << "You do not have permission to set room local aliases";
}
setState<RoomCanonicalAliasEvent>(canonicalAlias(), aliases);
}

void Room::setTopic(const QString& newTopic)
{
if (canSetState(RoomTopicEvent::TypeId)) {
qCWarning(EVENTS) << "You do not have permission to set the room topic";
}
setState<RoomTopicEvent>(newTopic);
}

Expand Down Expand Up @@ -3457,6 +3498,10 @@ void Room::activateEncryption()
qCWarning(E2EE) << "Room" << objectName() << "is already encrypted";
return;
}
if (!canSetState(EncryptionEvent::TypeId)) {
qCWarning(E2EE) << "You do not have permission to encrypt the room";
return;
}
setState<EncryptionEvent>(EncryptionType::MegolmV1AesSha2);
}

Expand Down
12 changes: 12 additions & 0 deletions Quotient/room.h
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,18 @@ class QUOTIENT_API Room : public QObject {

PendingEventItem::future_type whenMessageMerged(QString txnId) const;

//! True if the given user can send the given event type
//!
//! \param eventTypedId the Matrix type for the event.
//! \param memberId the Matrix ID of the member to check. If blank the local member is used.
Q_INVOKABLE bool canSendEvent(const QString &eventTypeId, const QString& memberId = {}) const;

//! True if the given user can send the given state event type
//!
//! \param eventTypedId the Matrix type for the event.
//! \param memberId the Matrix ID of the member to check. If blank the local member is used.
Q_INVOKABLE bool canSetState(const QString &eventTypeId, const QString& memberId = {}) const;

//! Send a request to update the room state with the given event
SetRoomStateWithKeyJob* setState(const StateEvent& evt);

Expand Down
4 changes: 4 additions & 0 deletions Quotient/user.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ void User::rename(const QString& newName, Room* r)
rename(newName);
return;
}
if (!r->canSetState(RoomMemberEvent::TypeId, id())) {
qCWarning(MAIN) << "You do not have permission is rename" << id();
return;
}
// #481: take the current state and update it with the new name
if (const auto& maybeEvt = r->currentState().get<RoomMemberEvent>(id())) {
auto content = maybeEvt->content();
Expand Down
1 change: 1 addition & 0 deletions autotests/testolmaccount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ void TestOlmAccount::enableEncryption()
QThread::sleep(100);
}
auto room = alice->rooms(JoinState::Join)[0];
qWarning() << room->memberEffectivePowerLevel(alice->userId());
room->activateEncryption();
QSignalSpy encryptionSpy(room, &Room::encryption);
QVERIFY(encryptionSpy.wait(10000));
Expand Down

0 comments on commit 67354eb

Please sign in to comment.