Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
qWarning() <<statePowerLevel << memberEffectivePowerLevel(memberId);
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