Skip to content

Commit

Permalink
Make JoinRule into an enum and add Room helper functions
Browse files Browse the repository at this point in the history
  • Loading branch information
nvrWhere committed Jan 26, 2025
1 parent a9f121c commit 77de0ec
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 27 deletions.
69 changes: 42 additions & 27 deletions Quotient/events/roomjoinrulesevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,43 @@
namespace Quotient
{
namespace EventContent {
//! \brief Definition of an allow AllowCondition
//!
//! see https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules for the
//! full definition.
struct AllowCondition {
QString roomId;
QString type;
};
Q_NAMESPACE_EXPORT(QUOTIENT_API)

//! \brief The content of a join rule event
//!
//! see https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules for the
//! full definition.
struct JoinRuleContent {
QString joinRule;
QList<AllowCondition> allow;
};
//! \brief Definition of an allow AllowCondition
//!
//! \sa https://spec.matrix.org/latest/client-server-api/#mroomjoin_ruless
struct AllowCondition {
QString roomId;
QString type;
};

//! Enum representing the available room join rules
enum JoinRule {
Public,
Knock,
Invite,
Private,
Restricted,
KnockRestricted,
};
Q_ENUM_NS(JoinRule)

[[maybe_unused]] constexpr std::array JoinRuleStrings {
"public"_L1,
"knock"_L1,
"invite"_L1,
"private"_L1,
"restricted"_L1,
"knock_restricted"_L1,
};

//! \brief The content of a join rule event
//!
//! \sa https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules
struct JoinRuleContent {
JoinRule joinRule;
QList<AllowCondition> allow;
};
} // namespace EventContent

template<>
Expand All @@ -49,7 +69,7 @@ template<>
inline EventContent::JoinRuleContent fromJson(const QJsonObject& jo)
{
return EventContent::JoinRuleContent {
fromJson<QString>(jo["join_rule"_L1]),
enumFromJsonString<EventContent::JoinRule>(jo["join_rule"_L1].toString(), EventContent::JoinRuleStrings).value_or(EventContent::Public),
fromJson<QList<EventContent::AllowCondition>>(jo["allow"_L1])
};
}
Expand All @@ -58,17 +78,14 @@ template<>
inline auto toJson(const EventContent::JoinRuleContent& c)
{
QJsonObject jo;
addParam<IfNotEmpty>(jo, "join_rule"_L1, c.joinRule);
addParam<IfNotEmpty>(jo, "join_rule"_L1, enumToJsonString<EventContent::JoinRule>(c.joinRule, EventContent::JoinRuleStrings));
addParam<IfNotEmpty>(jo, "allow"_L1, c.allow);
return jo;
}

//! \brief Class to define a join rule state event.
//!
//! see https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules for the
//! full definition.
//!
//! \sa Quotient::StateEvent
//! \sa Quotient::StateEvent, https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules
class JoinRulesEvent : public KeylessStateEventBase<JoinRulesEvent,
EventContent::JoinRuleContent>
{
Expand All @@ -78,14 +95,12 @@ class JoinRulesEvent : public KeylessStateEventBase<JoinRulesEvent,

//! \brief The join rule for the room.
//!
//! see https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules for
//! the available join rules for a room.
QString joinRule() const { return content().joinRule; }
//! \sa https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules
EventContent::JoinRule joinRule() const { return content().joinRule; }

//! \brief The allow rules for restricted rooms.
//!
//! see https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules for
//! the full details on allow rules.
//! \sa https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules
QList<EventContent::AllowCondition> allow() const { return content().allow; }
};
} // namespace Quotient
39 changes: 39 additions & 0 deletions Quotient/room.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include "events/roomavatarevent.h"
#include "events/roomcanonicalaliasevent.h"
#include "events/roomcreateevent.h"
#include "events/roomjoinrulesevent.h"
#include "events/roommemberevent.h"
#include "events/roompowerlevelsevent.h"
#include "events/roomtombstoneevent.h"
Expand Down Expand Up @@ -1534,6 +1535,36 @@ RoomStateView Room::currentState() const
return d->currentState;
}

EventContent::JoinRule Room::joinRule() const
{
return currentState().queryOr(&JoinRulesEvent::joinRule, EventContent::Public);
}

QList<QString> Room::allowIds() const
{
QList<QString> allowIds;
for (const auto& allowCondition : currentState().queryOr(&JoinRulesEvent::allow, QList<EventContent::AllowCondition>())) {
allowIds.append(allowCondition.roomId);
}
return allowIds;
}

void Room::setJoinRule(EventContent::JoinRule newRule, const QList<QString>& allowedRooms)
{
if (memberEffectivePowerLevel() < powerLevelFor<JoinRulesEvent>()) {
return;
}

EventContent::JoinRule actualRule = (newRule == EventContent::Restricted || newRule == EventContent::KnockRestricted) && allowedRooms.isEmpty() ? EventContent::Invite : newRule;
QList<EventContent::AllowCondition> newAllow;
for (const auto& room :allowedRooms) {
newAllow.append({room, "m.room_membership"_L1});
}
setState<JoinRulesEvent>(actualRule, newAllow);
// Not emitting joinRuleChanged() here, since that would override the change
// in the UI with the *current* value, which is not the *new* value.
}

int Room::memberEffectivePowerLevel(const UserId& memberId) const
{
return currentState().get<RoomPowerLevelsEvent>()->powerLevelForUser(
Expand Down Expand Up @@ -3208,6 +3239,14 @@ Room::Change Room::Private::processStateEvent(const RoomEvent& curEvent,

return Change::Other;
},
[this, oldEvent](const JoinRulesEvent& evt) {
if (const auto* oldJRE = static_cast<const JoinRulesEvent*>(oldEvent);
oldJRE && oldJRE->content().joinRule != evt.content().joinRule
) {
emit q->joinRuleChanged();
}
return Change::Other;
},
Change::Other);
}

Expand Down
35 changes: 35 additions & 0 deletions Quotient/room.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "events/roommessageevent.h"
#include "events/roompowerlevelsevent.h"
#include "events/roomtombstoneevent.h"
#include <Quotient/events/roomjoinrulesevent.h>

#include <QtCore/QJsonObject>
#include <QtGui/QImage>
Expand Down Expand Up @@ -165,6 +166,8 @@ class QUOTIENT_API Room : public QObject {
Q_PROPERTY(QStringList tagNames READ tagNames NOTIFY tagsChanged)
Q_PROPERTY(bool isFavourite READ isFavourite NOTIFY tagsChanged STORED false)
Q_PROPERTY(bool isLowPriority READ isLowPriority NOTIFY tagsChanged STORED false)
Q_PROPERTY(EventContent::JoinRule joinRule READ joinRule WRITE setJoinRule NOTIFY joinRuleChanged)
Q_PROPERTY(QList<QString> allowIds READ allowIds NOTIFY joinRuleChanged)

Q_PROPERTY(GetRoomEventsJob* eventsHistoryJob READ eventsHistoryJob NOTIFY eventsHistoryJobChanged)
Q_PROPERTY(int requestedHistorySize READ requestedHistorySize NOTIFY eventsHistoryJobChanged)
Expand Down Expand Up @@ -672,6 +675,35 @@ class QUOTIENT_API Room : public QObject {
/// \brief Get the current room state
RoomStateView currentState() const;

//! \brief The current Join Rule for the room
//!
//! \sa https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules
EventContent::JoinRule joinRule() const;

//! \brief Set the Join Rule for the room
//!
//! If the local user does not have a high enough power level the request is rejected.
//!
//! \param newRule the new JoinRule to apply to the room
//! \param allowedRooms only required when the join rule is restricted. This is a
//! list of room IDs that members of can join without an invite.
//! If the rule is restricted and this list is empty it is treated as a join
//! rule of invite instead.
//!
//! \note While any room ID is permitted it is designed to be only spaces that are
//! input. I.e. only memebers of space `x` can join this room.
//!
//! \sa https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules
Q_INVOKABLE void setJoinRule(EventContent::JoinRule newRule, const QList<QString>& allowedRooms = {});

//! \brief The list of Room IDs for when the join rule is Restricted
//!
//! This value will be empty when the Join Rule is not Restricted or
//! Knock-Restricted.
//!
//! \sa https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules
QList<QString> allowIds() const;

//! \brief The effective power level of the given member in the room
//!
//! This is normally the same as calling `RoomPowerLevelEvent::powerLevelForUser(userId)` but
Expand Down Expand Up @@ -896,6 +928,9 @@ public Q_SLOTS:
void topicChanged();
void avatarChanged();

//! \brief The join rule for the room has changed
void joinRuleChanged();

//! \brief A new member has joined the room
//!
//! This can be from any previous state or a member previously unknown to
Expand Down

0 comments on commit 77de0ec

Please sign in to comment.