diff options
-rw-r--r-- | Readme.md | 3 | ||||
-rwxr-xr-x | src/Controllers/AccountController.php | 35 | ||||
-rw-r--r-- | src/Controllers/KeyController.php | 4 | ||||
-rwxr-xr-x | src/Controllers/RoomController.php | 34 | ||||
-rwxr-xr-x | src/Controllers/SyncController.php | 71 | ||||
-rw-r--r-- | src/Models/User.php | 15 | ||||
-rw-r--r-- | src/Router/routes_client_server.php | 11 | ||||
-rw-r--r-- | src/Types/EventType.php | 1 | ||||
-rw-r--r-- | src/Types/MessageType.php | 8 |
9 files changed, 167 insertions, 15 deletions
@@ -1 +1,4 @@ Matrix Specification: https://spec.matrix.org/v1.15/ + + +# TODO: check if access_token is expired BEFORE using it to fetch the user diff --git a/src/Controllers/AccountController.php b/src/Controllers/AccountController.php new file mode 100755 index 0000000..858a6b5 --- /dev/null +++ b/src/Controllers/AccountController.php @@ -0,0 +1,35 @@ +<?php + +namespace App\Controllers; + +use App\Errors\UnauthorizedError; +use App\Models\Device; +use App\Models\User; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\JsonResponse; + +class AccountController +{ + /** + * GET /_matrix/client/v3/account/whoami + * + * @see https://spec.matrix.org/v1.15/client-server-api/#get_matrixclientv3accountwhoami + */ + public function whoami(Request $request): Response + { + $accessToken = str_replace("Bearer ", "", $request->headers->get("authorization") ?: ""); + $user = User::fetchWithAccessToken($accessToken); + + if (empty($user)) { + throw new UnauthorizedError(); + } + + $device = Device::fetch(userId: $user->getId()); + + return new JsonResponse([ + "device_id" => $device->getId(), + "user_id" => $user->getId(), + ]); + } +} diff --git a/src/Controllers/KeyController.php b/src/Controllers/KeyController.php index 53e9ff4..b2a17a6 100644 --- a/src/Controllers/KeyController.php +++ b/src/Controllers/KeyController.php @@ -31,7 +31,9 @@ class KeyController RequestValidator::validateJson(); return new JsonResponse([ - "one_time_key_counts" => count($body["one_time_keys"]), + "one_time_key_counts" => [ + "signed_curve25519" => count($body["one_time_keys"]) + ], ]); } diff --git a/src/Controllers/RoomController.php b/src/Controllers/RoomController.php index 1067d29..367d754 100755 --- a/src/Controllers/RoomController.php +++ b/src/Controllers/RoomController.php @@ -5,7 +5,12 @@ namespace App\Controllers; use App\Database; use App\Errors\AppException; use App\Errors\ErrorCode; +use App\Errors\UnauthorizedError; +use App\Models\User; use App\Support\Parser; +use App\Support\RequestValidator; +use App\Types\EventType; +use App\Types\MessageType; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\JsonResponse; @@ -51,4 +56,33 @@ class RoomController "servers" => [], ]); } + + /** + * PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId} + * + * @see https://spec.matrix.org/v1.15/client-server-api/#put_matrixclientv3roomsroomidsendeventtypetxnid + */ + public function send(Request $request): Response + { + $accessToken = str_replace("Bearer ", "", $request->headers->get("authorization") ?: ""); + $user = User::fetchWithAccessToken($accessToken); + + if (empty($user)) { + throw new UnauthorizedError(); + } + + $roomId = $request->attributes->get("roomId"); + $eventType = EventType::from($request->attributes->get("eventType")); + $transactionId = $request->attributes->get("txnId"); + + $body = json_decode($request->getContent(), true); + RequestValidator::validateJson(); + + $message = $body["body"]; + $messageType = MessageType::from($body["msgtype"]); + + return new JsonResponse([ + "event_id" => "\$asdfghjkl:" . $_ENV["DOMAIN"], + ]); + } } diff --git a/src/Controllers/SyncController.php b/src/Controllers/SyncController.php index 76b6a26..b7d51c3 100755 --- a/src/Controllers/SyncController.php +++ b/src/Controllers/SyncController.php @@ -5,6 +5,7 @@ namespace App\Controllers; use App\Database; use App\Errors\UnauthorizedError; use App\Events\PresenceEvent; +use App\Models\User; use App\Types\PresenceState; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -21,13 +22,7 @@ class SyncController public function sync(Request $request): Response { $accessToken = str_replace("Bearer ", "", $request->headers->get("authorization") ?: ""); - $user = Database::getInstance()->query(<<<SQL - select users.* from users left join tokens on tokens.user_id = users.id where tokens.access_token=:access_token - SQL, [ - "access_token" => $accessToken, - ])->fetch(); - - # TODO: token validation + $user = User::fetchWithAccessToken($accessToken); if (empty($user)) { throw new UnauthorizedError(); @@ -39,6 +34,49 @@ class SyncController $since = $request->query->get("since", ""); $timeout = $request->query->get("timeout", 0); + $rooms = Database::getInstance()->query(<<<SQL + select * from rooms + SQL)->fetchAll(); + + $joinedRooms = new \stdClass(); + if (! empty($rooms)) { + $joinedRooms = []; + foreach ($rooms as $room) { + $joinedRooms[$room["id"]] = [ + "account_data" => [ + "events" => [], + ], + + "ephemeral" => [ + "events" => [], + ], + + "state" => [ + "events" => [], + ], + + "summary" => [ + "m.heroes" => [], + "m.invited_member_count" => 0, + "m.joined_member_count" => 1, + ], + + "timeline" => [ + "events" => [], + "limited" => false, + "prev_batch" => "", + ], + + "unread_notifications" => [ + "highlight_count" => 1, + "notification_count" => 2, + ], + + "unread_thread_notifications" => new \stdClass(), + ]; + } + } + return new JsonResponse([ "account_data" => [ "events" => [ @@ -46,23 +84,28 @@ class SyncController ], ], - "device_lists" => [], + "device_lists" => [ + "changed" => [], + "left" => [], + ], - "device_one_time_keys_count" => 10, + "device_one_time_keys_count" => [ + "signed_curve25519" => 10, + ], "next_batch" => "next_batch_id", "presence" => [ "events" => [ - (new PresenceEvent(sender: $user["id"]))->toJsonEncodeable(), + (new PresenceEvent(sender: $user->getId()))->toJsonEncodeable(), ], ], "rooms" => [ - "invite" => [], - "join" => [], - "knock" => [], - "leave" => [], + "invite" => new \stdClass(), + "join" => $joinedRooms, + "knock" => new \stdClass(), + "leave" => new \stdClass(), ], "to_device" => [ diff --git a/src/Models/User.php b/src/Models/User.php index 354c466..423394a 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -50,6 +50,21 @@ class User implements ConnectsToDatabase return self::fromDatabase($row); } + public static function fetchWithAccessToken(string $accessToken): ?static + { + $row = Database::getInstance()->query(<<<SQL + select users.* from users left join tokens on tokens.user_id = users.id where tokens.access_token=:access_token + SQL, [ + "access_token" => $accessToken, + ])->fetch(); + + if (empty($row)) { + return null; + } + + return self::fromDatabase($row); + } + public static function new(string $id): self { return new self($id); diff --git a/src/Router/routes_client_server.php b/src/Router/routes_client_server.php index 6e7bb8d..7543892 100644 --- a/src/Router/routes_client_server.php +++ b/src/Router/routes_client_server.php @@ -2,6 +2,7 @@ namespace App\Router; +use App\Controllers\AccountController; use App\Controllers\KeyController; use App\Controllers\LoginController; use App\Controllers\RoomController; @@ -57,4 +58,14 @@ return function (RouteConfigurator $routes): void ->add("matrix_client_v3_directory_room_alias_get", "/_matrix/client/v3/directory/room/{roomAlias}") ->controller([RoomController::class, "resolveAlias"]) ->methods(["GET"]); + + $routes + ->add("matrix_client_v3_account_whoami", "/_matrix/client/v3/account/whoami") + ->controller([AccountController::class, "whoami"]) + ->methods(["GET"]); + + $routes + ->add("matrix_client_v3_rooms_id_send_event_transaction", "/_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}") + ->controller([RoomController::class, "send"]) + ->methods(["PUT"]); }; diff --git a/src/Types/EventType.php b/src/Types/EventType.php index a79debc..d599c6f 100644 --- a/src/Types/EventType.php +++ b/src/Types/EventType.php @@ -7,4 +7,5 @@ enum EventType: string case PRESENCE = "m.presence"; case ROOM_NAME = "m.room.name"; case ROOM_MEMBER = "m.room.member"; + case ROOM_MESSAGE = "m.room.message"; } diff --git a/src/Types/MessageType.php b/src/Types/MessageType.php new file mode 100644 index 0000000..ded17a0 --- /dev/null +++ b/src/Types/MessageType.php @@ -0,0 +1,8 @@ +<?php + +namespace App\Types; + +enum MessageType: string +{ + case TEXT = "m.text"; +} |