From 8280017cee0a3b656f9114fcb8cfaf30c3b3f020 Mon Sep 17 00:00:00 2001 From: David Woloszyn Date: Wed, 22 May 2024 14:55:12 +1000 Subject: [PATCH 1/2] MDL-81951: Power levels can be fetched from roomState --- .../src/Controller/BackOfficeController.php | 6 +- .../src/Controller/MatrixController.php | 116 +++++++++++------- application/src/Entity/Room.php | 69 ++++++++--- 3 files changed, 123 insertions(+), 68 deletions(-) diff --git a/application/src/Controller/BackOfficeController.php b/application/src/Controller/BackOfficeController.php index 5fd6dfd..03e8d56 100644 --- a/application/src/Controller/BackOfficeController.php +++ b/application/src/Controller/BackOfficeController.php @@ -135,7 +135,11 @@ public function getAllRooms(string $serverID): JSONResponse 'rooms' => array_map(function ($room) { $roomdata = $room->jsonSerialize(); $roomdata->members = array_map( - fn($membership) => $membership->getUser()->jsonSerialize(), + function (RoomMember $membership) { + $memberdata = $membership->getUser()->jsonSerialize(); + $memberdata->powerlevel = $membership->getPowerLevel() ?? 0; + return $memberdata; + }, array_filter( $room->getMembers()->toArray(), function (RoomMember $membership): bool { diff --git a/application/src/Controller/MatrixController.php b/application/src/Controller/MatrixController.php index 92bf4f7..2dddee2 100644 --- a/application/src/Controller/MatrixController.php +++ b/application/src/Controller/MatrixController.php @@ -401,7 +401,7 @@ public function roomState(string $serverID, string $roomID, string $eventType, R // 1. Check call auth. // 2. Check HTTP method is accepted. - $accessCheck = $this->authHttpCheck(['PUT'], $request); + $accessCheck = $this->authHttpCheck(['PUT', 'GET'], $request); if (!$accessCheck['status']) { return $accessCheck['message']; } @@ -417,61 +417,83 @@ public function roomState(string $serverID, string $roomID, string $eventType, R return $this->getUnknownRoomResponse(); } - $payload = json_decode($request->getContent()); + $method = $request->getMethod(); - if ($eventType == 'm.room.topic') { - $check = $this->validateRequest((array)$payload, ['topic']); - if (!$check['status']) { - return $check['message']; - } - $room->setTopic($payload->topic); + // PUT requests. + if ($method == 'PUT') { - } elseif ($eventType == 'm.room.name') { - // Update room name. - $check = $this->validateRequest((array)$payload, ['name']); - if (!$check['status']) { - return $check['message']; - } - $room->setName($payload->name); + $payload = json_decode($request->getContent()); - } elseif ($eventType == 'm.room.avatar') { - // Update room avatar. - $check = $this->validateRequest((array)$payload, ['url']); - if (!$check['status']) { - return $check['message']; - } - $room->setAvatar($payload->url); - } elseif ($eventType == 'm.room.power_levels') { - // Room power level api call validation to check if the users are passed in the payload to update the power level. - $check = $this->validateRequest((array)$payload, ['users']); - if (!$check['status']) { - return $check['message']; - } - // Update power levels for each room member. - foreach ($payload->users as $userid => $level) { - if (!empty($level)) { - $user = $entityManager->getRepository(User::class)->findOneBy([ - 'serverid' => $serverID, - 'userid' => $userid, - ]); - if (!empty($user)) { - $membership = $entityManager->getRepository(RoomMember::class)->findOneBy([ + if ($eventType == 'm.room.topic') { + $check = $this->validateRequest((array)$payload, ['topic']); + if (!$check['status']) { + return $check['message']; + } + $room->setTopic($payload->topic); + + } elseif ($eventType == 'm.room.name') { + // Update room name. + $check = $this->validateRequest((array)$payload, ['name']); + if (!$check['status']) { + return $check['message']; + } + $room->setName($payload->name); + + } elseif ($eventType == 'm.room.avatar') { + // Update room avatar. + $check = $this->validateRequest((array)$payload, ['url']); + if (!$check['status']) { + return $check['message']; + } + $room->setAvatar($payload->url); + } elseif ($eventType == 'm.room.power_levels') { + // Room power level api call validation to check if the users are passed in the payload to update the power level. + $check = $this->validateRequest((array)$payload, ['users']); + if (!$check['status']) { + return $check['message']; + } + // Update power levels for each room member. + foreach ($payload->users as $userid => $level) { + if (!empty($level)) { + $user = $entityManager->getRepository(User::class)->findOneBy([ 'serverid' => $serverID, - 'room' => $room, - 'user' => $user, + 'userid' => $userid, ]); - if(!empty($membership)) { - $membership->setPowerLevel($level); + if (!empty($user)) { + $membership = $entityManager->getRepository(RoomMember::class)->findOneBy([ + 'serverid' => $serverID, + 'room' => $room, + 'user' => $user, + ]); + if(!empty($membership)) { + $membership->setPowerLevel($level); + } } } } + } else { + // Unknown state. + return new JsonResponse((object) [ + 'errcode' => 'M_UNRECOGNIZED', + 'error' => 'Unrecognized request' + ], 404); + } + + // GET requests. + } else if ($method == 'GET') { + + if ($eventType == 'm.room.power_levels') { + + $powerLevels = $room->getPowerLevels($request); + return new JsonResponse((object) $powerLevels, 200); + + } else { + // Unknown state. + return new JsonResponse((object) [ + 'errcode' => 'M_UNRECOGNIZED', + 'error' => 'Unrecognized request' + ], 404); } - } else { - // Unknown state. - return new JsonResponse((object) [ - 'errcode' => 'M_UNRECOGNIZED', - 'error' => 'Unrecognized request' - ], 404); } $entityManager = $this->getDoctrine()->getManager(); diff --git a/application/src/Entity/Room.php b/application/src/Entity/Room.php index a523fe8..deb624c 100644 --- a/application/src/Entity/Room.php +++ b/application/src/Entity/Room.php @@ -216,12 +216,18 @@ public function getRoomState(): array return $roomData; } + protected function getPowerLevelValues(): array + { + return [ + 'default' => 0, + 'moderator' => 50, + 'maximum' => 100, + ]; + } + protected function getPowerLevelState(): array { - // Power level values. - $powerLevelDefault = 0; - $powerLevelModerator = 50; - $powerLevelMaximum = 100; + $powerLevels = $this->getPowerLevelValues(); // Get the members of the room who have a powerlevel set. $members = $this->getMembers()->filter(function (RoomMember $member) { @@ -237,25 +243,48 @@ protected function getPowerLevelState(): array 'type' => 'm.room.power_levels', 'content' => [ 'users' => (object) $memberInfo, - 'users_default' => $powerLevelDefault, + 'users_default' => $powerLevels['default'], 'events' => [ - 'm.room.name' => $powerLevelModerator, - 'm.room.power_levels' => $powerLevelMaximum, - 'm.room.history_visibility' => $powerLevelMaximum, - 'm.room.canonical_alias' => $powerLevelModerator, - 'm.room.avatar' => $powerLevelModerator, - 'm.room.tombstone' => $powerLevelMaximum, - 'm.room.server_acl' => $powerLevelMaximum, - 'm.room.encryption' => $powerLevelMaximum, + 'm.room.name' => $powerLevels['moderator'], + 'm.room.power_levels' => $powerLevels['maximum'], + 'm.room.history_visibility' => $powerLevels['maximum'], + 'm.room.canonical_alias' => $powerLevels['moderator'], + 'm.room.avatar' => $powerLevels['moderator'], + 'm.room.tombstone' => $powerLevels['maximum'], + 'm.room.server_acl' => $powerLevels['maximum'], + 'm.room.encryption' => $powerLevels['maximum'], ], - 'events_default' => $powerLevelDefault, - 'state_default' => $powerLevelModerator, - 'ban' => $powerLevelModerator, - 'kick' => $powerLevelModerator, - 'redact' => $powerLevelModerator, - 'invite' => $powerLevelDefault, - 'historical' => $powerLevelMaximum, + 'events_default' => $powerLevels['default'], + 'state_default' => $powerLevels['moderator'], + 'ban' => $powerLevels['moderator'], + 'kick' => $powerLevels['moderator'], + 'redact' => $powerLevels['moderator'], + 'invite' => $powerLevels['default'], + 'historical' => $powerLevels['maximum'], ], ]; } + + public function getPowerLevels(): array + { + $powerLevels = $this->getPowerLevelValues(); + + // Get the members of the room who have a power level set. + $members = $this->getMembers()->filter(function (RoomMember $member) { + return $member->getPowerLevel() !== null; + }); + + // Build list of users and their power level. + $memberInfo = array_merge(...$members->map(fn(RoomMember $member) => [ + $member->getUser()->getUserid() => $member->getPowerLevel(), + ])->toArray()); + + return [ + 'users' => (object) $memberInfo, + 'ban' => $powerLevels['moderator'], + 'kick' => $powerLevels['moderator'], + 'redact' => $powerLevels['moderator'], + 'invite' => $powerLevels['default'], + ]; + } } From cce83c108454ce98b5923d298e2e4c2478e3b8cf Mon Sep 17 00:00:00 2001 From: David Woloszyn Date: Wed, 22 May 2024 17:10:22 +1000 Subject: [PATCH 2/2] Adjust power levels to match default Matrix values --- application/src/Entity/Room.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/Entity/Room.php b/application/src/Entity/Room.php index deb624c..14ee67b 100644 --- a/application/src/Entity/Room.php +++ b/application/src/Entity/Room.php @@ -259,7 +259,7 @@ protected function getPowerLevelState(): array 'ban' => $powerLevels['moderator'], 'kick' => $powerLevels['moderator'], 'redact' => $powerLevels['moderator'], - 'invite' => $powerLevels['default'], + 'invite' => $powerLevels['moderator'], 'historical' => $powerLevels['maximum'], ], ]; @@ -284,7 +284,7 @@ public function getPowerLevels(): array 'ban' => $powerLevels['moderator'], 'kick' => $powerLevels['moderator'], 'redact' => $powerLevels['moderator'], - 'invite' => $powerLevels['default'], + 'invite' => $powerLevels['moderator'], ]; } }