diff --git a/src/Room.c b/src/Room.c index 34f1161..bdd6398 100644 --- a/src/Room.c +++ b/src/Room.c @@ -605,6 +605,73 @@ AuthorizeInviteMembershipV1(Room * room, PduV1 pdu) return false; } static bool +AuthorizeLeaveMembershipV1(Room * room, PduV1 pdu) +{ + int64_t ban_level = RoomMinPL(room, pdu.event_id, NULL, "ban"); + int64_t kick_level = RoomMinPL(room, pdu.event_id, NULL, "kick"); + int64_t sender_level = RoomUserPL(room, pdu.event_id, pdu.sender); + int64_t target_level = RoomUserPL(room, pdu.state_key, pdu.sender); + /* Step 5.4.1: If the sender matches state_key, allow if and only if + * that user's current membership state is invite or join. */ + if (StrEquals(pdu.sender, pdu.state_key)) + { + return + RoomUserHasMembership(room, pdu.event_id, pdu.sender, "invite") || + RoomUserHasMembership(room, pdu.event_id, pdu.sender, "join"); + } + + /* Step 5.4.2: If the sender's current membership state is not join, + * reject. */ + if (!RoomUserHasMembership(room, pdu.event_id, pdu.sender, "join")) + { + return false; + } + + /* Step 5.4.3: If the target user's current membership state is ban, + * and the sender's power level is less than the ban level, reject. */ + if (RoomUserHasMembership(room, pdu.event_id, pdu.state_key, "ban") && + sender_level < ban_level) + { + return false; + } + + /* Step 5.4.4: If the sender's power level is greater than or equal to + * the kick level, and the target user's power level is less than the + * sender's power level, allow. */ + if ((sender_level >= kick_level) && target_level < sender_level) + { + return true; + } + + /* Step 5.4.5: Otherwise, reject. */ + return false; +} +static bool +AuthorizeBanMembershipV1(Room * room, PduV1 pdu) +{ + int64_t ban_pl, pdu_pl, target_pl; + + /* Step 5.5.1: If the sender's current membership state is not join, reject. */ + if (!RoomUserHasMembership(room, pdu.event_id, pdu.sender, "join")) + { + return false; + } + + /* Step 5.5.2: If the sender's power level is greater than or equal + * to the ban level, and the target user's power level is less than + * the sender's power level, allow. */ + ban_pl = RoomMinPL(room, pdu.event_id, NULL, "ban"); + pdu_pl = RoomUserPL(room, pdu.event_id, pdu.sender); + target_pl = RoomUserPL(room, pdu.state_key, pdu.sender); + if ((pdu_pl >= ban_pl) && (target_pl < pdu_pl)) + { + return true; + } + + /* Step 5.5.3: Otherwise, reject. */ + return false; +} +static bool AuthorizeJoinMembershipV1(Room * room, PduV1 pdu) { /* Step 5.2.1: If the only previous event is an m.room.create and the @@ -687,8 +754,14 @@ AuthoriseMemberV1(Room * room, PduV1 pdu) /* Step 5.2: If membership is join. */ JumpIfMembership("join", AuthorizeJoinMembershipV1); - /* Step 5.3: If membership is invite. */ + /* Step 5.3: If membership is invite. TODO */ JumpIfMembership("invite", AuthorizeInviteMembershipV1); + + /* Step 5.4: If membership is leave. */ + JumpIfMembership("leave", AuthorizeLeaveMembershipV1); + + /* Step 5.5: If membership is ban. */ + JumpIfMembership("ban", AuthorizeBanMembershipV1); /* Step 5.6: Otherwise, the membership is unknown. Reject. */ return false;