diff options
Diffstat (limited to 'src/Controllers')
| -rw-r--r-- | src/Controllers/LoginController.php | 12 | ||||
| -rwxr-xr-x | src/Controllers/RoomController.php | 154 | ||||
| -rw-r--r-- | src/Controllers/ServerDiscoveryController.php | 2 | ||||
| -rwxr-xr-x | src/Controllers/SyncController.php | 168 | ||||
| -rwxr-xr-x | src/Controllers/UserController.php | 27 |
5 files changed, 274 insertions, 89 deletions
diff --git a/src/Controllers/LoginController.php b/src/Controllers/LoginController.php index c520e25..9ae3a48 100644 --- a/src/Controllers/LoginController.php +++ b/src/Controllers/LoginController.php @@ -9,10 +9,12 @@ use App\Errors\UnknownError; use App\Models\Device; use App\Models\Tokens; use App\Models\User; +use App\Support\Logger; +use App\Support\Parser; use App\Support\RequestValidator; -use App\Types\UserRegistrationKind; use Matrix\Data\LoginFlow; use Matrix\Enums\LoginType; +use Matrix\Enums\UserRegistrationKind; use Matrix\Responses\ClientLoginGetResponse; use Matrix\Responses\ClientLoginPostResponse; use Matrix\Responses\ClientRegisterPostResponse; @@ -37,6 +39,8 @@ class LoginController */ public function login(Request $request): Response { + Logger::logRequestToFile($request); + $body = json_decode($request->getContent(), true); RequestValidator::validateJson(); @@ -49,7 +53,11 @@ class LoginController } // get user id - $userId = $body["identifier"]["user"]; + $userId = Parser::parseUser($body["identifier"]["user"]); + if (empty($userId["server"])) { + #$userId = "@$userId[username]:$_ENV[DOMAIN]"; + $userId = "@$userId[username]:localhost"; + } #if ($loginType == LoginType::PASSWORD) {} diff --git a/src/Controllers/RoomController.php b/src/Controllers/RoomController.php index c02d5ce..dcc0415 100755 --- a/src/Controllers/RoomController.php +++ b/src/Controllers/RoomController.php @@ -7,18 +7,155 @@ use App\Errors\AppException; use App\Errors\ErrorCode; use App\Errors\UnauthorizedError; use App\Events\RoomMessageEvent; +use App\Models\RoomEvent; use App\Models\User; +use App\Support\Id; use App\Support\Parser; use App\Support\RequestValidator; -use App\Types\EventType; -use App\Types\MembershipState; -use App\Types\MessageType; +use Matrix\Enums\EventType; +use Matrix\Enums\MembershipState; +use Matrix\Enums\MessageType; +use Matrix\Enums\RoomGuestAccess; +use Matrix\Enums\RoomHistoryVisibility; +use Matrix\Enums\RoomJoinRule; +use Matrix\Enums\RoomVisibility; +use Matrix\Events\Room\CreateEvent; +use Matrix\Events\Room\GuestAccessEvent; +use Matrix\Events\Room\HistoryVisibilityEvent; +use Matrix\Events\Room\JoinRulesEvent; +use Matrix\Events\Room\MemberEvent; +use Matrix\Events\Room\NameEvent; +use Matrix\Events\Room\PowerLevelsEvent; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\JsonResponse; class RoomController { + public function createRoom(Request $request): Response + { + $user = User::authenticateWithRequest($request); + $body = json_decode($request->getContent(), true); + RequestValidator::validateJson(); + + $creationContent = $body["creation_content"] ?? []; + $initialState = $body["initial_state"] ?? []; + $invite = $body["invite"] ?? []; + $body["invite_3pid"] ?? []; + $body["is_direct"] ?? false; + $name = $body["name"] ?? ""; + $body["power_level_content_override"] ?? []; + $preset = $body["preset"] ?? ""; + $roomAliasName = $body["room_alias_name"] ?? ""; + $roomVersion = $body["room_version"] ?? "DEFAULT_ROOM_VERSION"; + $topic = $body["topic"] ?? ""; + $visibility = RoomVisibility::tryFrom($body["visibility"] ?? "private"); + + if (! $preset) { + $preset = $visibility->value . "_chat"; + } + + # TODO: get events for preset + # TODO: override preset events with initial state + # TODO: override events with name and topic if applicable + $state = []; + + if ($name) { + $state[EventType::ROOM_NAME->value] = $name; + } + + if ($topic) { + $state[EventType::ROOM_TOPIC->value] = $topic; + } + + // create room + $roomId = Id::generateRoomId(); + Database::getInstance()->query(<<<SQL + insert into rooms (id, name) values (:id, :name) + SQL, [ + "id" => $roomId, + "name" => $roomAliasName, # "#$roomAliasName:$_ENV[DOMAIN]", + ]); + + $roomCreateEvent = new RoomEvent(new CreateEvent( + eventId: Id::generateEventId(), + originServerTimestamp: time(), + roomId: $roomId, + sender: $user->getId(), + roomVersion: "12", + )); + $roomCreateEvent->insert(); + + $roomMemberEvent = new RoomEvent(new MemberEvent( + eventId: Id::generateEventId(), + originServerTimestamp: time(), + roomId: $roomId, + sender: $user->getId(), + stateKey: $user->getId(), + isDirect: false, + membership: MembershipState::JOIN, + displayName: $user->getName(), + )); + $roomMemberEvent->insert(); + + $roomPowerLevelsEvent = new RoomEvent(new PowerLevelsEvent( + eventId: Id::generateEventId(), + originServerTimestamp: time(), + roomId: $roomId, + sender: $user->getId(), + )); + $roomPowerLevelsEvent->insert(); + + $roomJoinRulesEvent = new RoomEvent(new JoinRulesEvent( + eventId: Id::generateEventId(), + originServerTimestamp: time(), + roomId: $roomId, + sender: $user->getId(), + joinRule: RoomJoinRule::INVITE, + )); + $roomJoinRulesEvent->insert(); + + $roomHistoryVisibilityEvent = new RoomEvent(new HistoryVisibilityEvent( + eventId: Id::generateEventId(), + originServerTimestamp: time(), + roomId: $roomId, + sender: $user->getId(), + historyVisibility: RoomHistoryVisibility::SHARED, + )); + $roomHistoryVisibilityEvent->insert(); + + $roomGuestAccessEvent = new RoomEvent(new GuestAccessEvent( + eventId: Id::generateEventId(), + originServerTimestamp: time(), + roomId: $roomId, + sender: $user->getId(), + guestAccess: RoomGuestAccess::CAN_JOIN, + )); + $roomGuestAccessEvent->insert(); + + $roomNameEvent = new RoomEvent(new NameEvent( + eventId: Id::generateEventId(), + originServerTimestamp: time(), + roomId: $roomId, + sender: $user->getId(), + name: $roomAliasName, + )); + $roomNameEvent->insert(); + + Database::getInstance()->query(<<<SQL + insert into room_memberships (room_id, user_id, state) + values (:room_id, :user_id, :state) + SQL, [ + "room_id" => $roomId, + "user_id" => $user->getId(), + "state" => MembershipState::JOIN->value, + ]); + + return new JsonResponse([ + "room_id" => $roomId, + ]); + } + /** * GET /_matrix/client/v3/directory/room/{roomAlias} * @@ -59,6 +196,17 @@ class RoomController ]); } + public function readMarkers(Request $request): Response + { + $user = User::authenticateWithRequest($request); + $body = json_decode($request->getContent(), true); + RequestValidator::validateJson(); + + $roomId = $request->attributes->get("roomId"); + + return new JsonResponse(); + } + /** * PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId} * diff --git a/src/Controllers/ServerDiscoveryController.php b/src/Controllers/ServerDiscoveryController.php index f3b96b2..917df14 100644 --- a/src/Controllers/ServerDiscoveryController.php +++ b/src/Controllers/ServerDiscoveryController.php @@ -19,7 +19,7 @@ class ServerDiscoveryController { return new JsonResponse([ "m.homeserver" => [ - "base_url" => "https://$_ENV[DOMAIN]", + "base_url" => "http://$_ENV[DOMAIN]", ], ]); } diff --git a/src/Controllers/SyncController.php b/src/Controllers/SyncController.php index 243fab5..acebb11 100755 --- a/src/Controllers/SyncController.php +++ b/src/Controllers/SyncController.php @@ -3,13 +3,23 @@ namespace App\Controllers; use App\Database; -use App\Errors\UnauthorizedError; -use App\Events\PresenceEvent; -use App\Events\RoomMemberEvent; -use App\Events\RoomMessageEvent; +use App\Models\RoomEvent; use App\Models\User; -use App\Types\MembershipState; -use App\Types\PresenceState; +use Matrix\Data\AccountData; +use Matrix\Data\DeviceLists; +use Matrix\Data\Presence; +use Matrix\Data\Room\Ephemeral; +use Matrix\Data\Room\JoinedRoom; +use Matrix\Data\Room\RoomSummary; +use Matrix\Data\Room\Rooms; +use Matrix\Data\Room\State; +use Matrix\Data\Room\Timeline; +use Matrix\Data\Room\UnreadNotificationCounts; +use Matrix\Data\ToDevice; +use Matrix\Enums\MembershipState; +use Matrix\Enums\PresenceState; +use Matrix\Events\PresenceEvent; +use Matrix\Responses\ClientSyncGetResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\JsonResponse; @@ -24,99 +34,93 @@ class SyncController */ public function sync(Request $request): Response { - $accessToken = str_replace("Bearer ", "", $request->headers->get("authorization") ?: ""); - $user = User::fetchWithAccessToken($accessToken); - - if (empty($user)) { - throw new UnauthorizedError(); - } + $user = User::authenticateWithRequest($request); $filter = $request->query->get("filter", ""); $syncFullState = $request->query->get("full_state", false); $setPresence = PresenceState::tryFrom($request->query->get("set_presence") ?? "") ?? PresenceState::ONLINE; $since = $request->query->get("since", ""); $timeout = $request->query->get("timeout", 0); + $useStateAfter = $request->query->get("use_state_after", false); + + if (! empty($filter)) { + if (str_starts_with($filter, "{")) { + $filter = json_decode($filter, true); + } else { + $filter = Database::getInstance()->query("select * from filters where id=:id", ["id" => $filter])->fetch(); + } + } $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" => [ - (new RoomMemberEvent($user->getId(), $user->getId(), MembershipState::JOIN))->toJsonEncodeable(), - (new RoomMessageEvent($user->getId(), "Hallo Test Nachricht"))->toJsonEncodeable(), - ], - "limited" => false, - "prev_batch" => "", - ], - - "unread_notifications" => [ - "highlight_count" => random_int(0, 1), - "notification_count" => random_int(0, 10), - ], - - "unread_thread_notifications" => new \stdClass(), - ]; + left join room_memberships + on rooms.id = room_memberships.room_id + where room_memberships.user_id = :user_id + SQL, [ + "user_id" => $user->getId(), + ])->fetchAll(); + + $invitedRooms = []; + $joinedRooms = []; + $knockedRooms = []; + $leftRooms = []; + + foreach ($rooms as $room) { + $events = Database::getInstance()->query(<<<SQL + select * from room_events + where room_id = :room_id + SQL, [ + "room_id" => $room["room_id"], + #"limit" => ($filter["room"]["timeline"]["limit"] ?? false) ? "limit " . $filter["room"]["timeline"]["limit"] : "", + ])->fetchAll(); + + if ($since === "" && MembershipState::tryFrom($room["state"]) === MembershipState::JOIN) { + $joinedRooms[$room["room_id"]] = new JoinedRoom( + accountData: new AccountData([]), + ephemeral: new Ephemeral([]), + state: new State([]), + summary: new RoomSummary( + heroes: [], + invitedMemberCount: 0, + joinedMemberCount: 1, + ), + timeline: new Timeline( + events: array_map([RoomEvent::class, "transformEvent"], $events), + limited: false,# $filter["room"]["timeline"]["limit"] ?? false, + previousBatch: null, + ), + unreadNotifications: new UnreadNotificationCounts(0, 0), + unreadThreadNotifications: [], + ); } } - return new JsonResponse([ - "account_data" => [ - "events" => [ + return new JsonResponse(new ClientSyncGetResponse( + nextBatch: "1", - ], - ], + accountData: new AccountData([]), - "device_lists" => [ - "changed" => [], - "left" => [], - ], + deviceLists: new DeviceLists([], []), - "device_one_time_keys_count" => [ + deviceOneTimeKeysCount: [ "signed_curve25519" => 10, ], - "next_batch" => "next_batch_id", - - "presence" => [ - "events" => [ - (new PresenceEvent(sender: $user->getId()))->toJsonEncodeable(), - ], - ], - - "rooms" => [ - "invite" => new \stdClass(), - "join" => $joinedRooms, - "knock" => new \stdClass(), - "leave" => new \stdClass(), - ], - - "to_device" => [ - "events" => [], - ], - ]); + presence: new Presence([ + new PresenceEvent( + sender: $user->getId(), + presence: $setPresence, + ), + ]), + + rooms: new Rooms( + $invitedRooms, + $joinedRooms, + $knockedRooms, + $leftRooms, + ), + + toDevice: new ToDevice([]), + )); } } diff --git a/src/Controllers/UserController.php b/src/Controllers/UserController.php index a056e1d..d102160 100755 --- a/src/Controllers/UserController.php +++ b/src/Controllers/UserController.php @@ -2,8 +2,10 @@ namespace App\Controllers; +use App\Database; use App\Errors\UnauthorizedError; use App\Models\User; +use App\Support\RequestValidator; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\JsonResponse; @@ -25,8 +27,31 @@ class UserController throw new UnauthorizedError(); } + $userId = $request->get("userId"); + if ($user->getId() !== $userId) { + throw new UnauthorizedError(); + } + + $body = json_decode($request->getContent(), true); + RequestValidator::validateJson(); + + $filterId = md5($userId . random_bytes(512)); + + Database::getInstance()->query(<<<SQL + insert into filters (id, account_data, event_fields, event_format, presence, room, user_id) + values (:id, :account_data, :event_fields, :event_format, :presence, :room, :user_id) + SQL, [ + "id" => $filterId, + "account_data" => isset($body["account_data"]) ? json_encode($body["account_data"]) : null, + "event_fields" => isset($body["event_fields"]) ? json_encode($body["event_fields"]) : null, + "event_format" => isset($body["event_format"]) ? json_encode($body["event_format"]) : null, + "presence" => isset($body["presence"]) ? json_encode($body["presence"]) : null, + "room" => isset($body["room"]) ? json_encode($body["room"]) : null, + "user_id" => $userId, + ]); + return new JsonResponse([ - "filter_id" => "1234", + "filter_id" => $filterId, ]); } } |
