From 1ee202dc245c513f9c5c469cfa733678d020c9d9 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 4 Jul 2022 19:05:01 +0200 Subject: [PATCH] Add a test for remote authentication Signed-off-by: Joas Schilling --- .../features/bootstrap/FeatureContext.php | 34 ++++++++++++++++--- .../features/federation/invite.feature | 22 ++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/tests/integration/features/bootstrap/FeatureContext.php b/tests/integration/features/bootstrap/FeatureContext.php index 91a1c43c170..f3e4b95dae1 100644 --- a/tests/integration/features/bootstrap/FeatureContext.php +++ b/tests/integration/features/bootstrap/FeatureContext.php @@ -57,6 +57,8 @@ class FeatureContext implements Context, SnippetAcceptingContext { protected static array $remoteToInviteId; /** @var array */ protected static array $inviteIdToRemote; + /** @var array */ + protected static array $remoteAuth; /** @var array */ protected static array $questionToPollId; /** @var array[] */ @@ -367,6 +369,9 @@ private function assertRooms($rooms, TableNode $formData, bool $shouldOrder = fa } Assert::assertEquals($expected, array_map(function ($room, $expectedRoom) { + if (isset($room['remoteAccessToken'])) { + self::$remoteAuth[self::translateRemoteServer($room['remoteServer']) . '#' . self::$identifierToToken[$room['name']]] = $room['remoteAccessToken']; + } if (!isset(self::$identifierToToken[$room['name']])) { self::$identifierToToken[$room['name']] = $room['token']; } @@ -1044,7 +1049,7 @@ public function userCreatesThePasswordRequestRoomForLastShare(string $user, int * @param TableNode|null $formData */ public function userJoinsRoom(string $user, string $identifier, int $statusCode, string $apiVersion, TableNode $formData = null): void { - $this->setCurrentUser($user); + $this->setCurrentUser($user, $identifier); $this->sendRequest( 'POST', '/apps/spreed/api/' . $apiVersion . '/room/' . self::$identifierToToken[$identifier] . '/participants/active', $formData @@ -1301,7 +1306,7 @@ public function userDeletesRoom(string $user, string $identifier, int $statusCod * @param string $apiVersion */ public function userGetsRoom(string $user, string $identifier, int $statusCode, string $apiVersion = 'v4', TableNode $formData = null): void { - $this->setCurrentUser($user); + $this->setCurrentUser($user, $identifier); $this->sendRequest('GET', '/apps/spreed/api/' . $apiVersion . '/room/' . self::$identifierToToken[$identifier]); $this->assertStatusCode($this->response, $statusCode); @@ -1777,7 +1782,7 @@ public function userSendsMessageToRoom(string $user, string $sendingMode, string $body = new TableNode([['message', $message]]); } - $this->setCurrentUser($user); + $this->setCurrentUser($user, $identifier); $this->sendRequest( 'POST', '/apps/spreed/api/' . $apiVersion . '/chat/' . self::$identifierToToken[$identifier], $body @@ -2448,7 +2453,7 @@ protected function compareDataResponse(TableNode $formData = null) { $data = [ 'room' => self::$tokenToIdentifier[$message['token']], 'actorType' => $message['actorType'], - 'actorId' => ($message['actorType'] === 'guests')? self::$sessionIdToUser[$message['actorId']]: $message['actorId'], + 'actorId' => $message['actorType'] === 'guests' ? self::$sessionIdToUser[$message['actorId']] : $message['actorId'], 'actorDisplayName' => $message['actorDisplayName'], // TODO test timestamp; it may require using Runkit, php-timecop // or something like that. @@ -3095,8 +3100,22 @@ public function resetGuestsAppState() { /** * @Given /^as user "([^"]*)"$/ */ - public function setCurrentUser(?string $user): ?string { + public function setCurrentUser(?string $user, ?string $identifier = null): ?string { $oldUser = $this->currentUser; + + if ($identifier && str_starts_with($user, 'federation/')) { + $user = substr($user, 11); + + $authArrayKey = 'LOCAL#' . self::$identifierToToken[$identifier]; + if (!isset(self::$remoteAuth[$authArrayKey])) { + throw new \Exception( + 'No remote auth available for: ' . 'LOCAL#' . self::$identifierToToken[$identifier] + . '. Did you pull rooms for the recipient? (user: ' . $user . ')' + ); + } + $user = 'federation#' . urlencode($user . '@' . 'http://localhost:8180') . '#' . self::$remoteAuth[$authArrayKey]; + } + $this->currentUser = $user; return $oldUser; } @@ -3977,6 +3996,11 @@ public function sendRequestFullUrl($verb, $fullUrl, $body = null, array $headers $options = array_merge($options, ['cookies' => $this->getUserCookieJar($this->currentUser)]); if ($this->currentUser === 'admin') { $options['auth'] = ['admin', 'admin']; + } elseif (str_starts_with($this->currentUser, 'federation')) { + $auth = explode('#', $this->currentUser); + array_shift($auth); + $options['auth'] = $auth; + $headers['X-Nextcloud-Federation'] = 1; } elseif ($this->currentUser !== null && !str_starts_with($this->currentUser, 'guest')) { $options['auth'] = [$this->currentUser, self::TEST_PASSWORD]; } diff --git a/tests/integration/features/federation/invite.feature b/tests/integration/features/federation/invite.feature index 1ea48f73993..1bff38b3d69 100644 --- a/tests/integration/features/federation/invite.feature +++ b/tests/integration/features/federation/invite.feature @@ -78,3 +78,25 @@ Feature: federation/invite | room | federated_users | participant2@http://localhost:8180 | federated_user_removed | {federated_user} declined the invitation | {"actor":{"type":"user","id":"participant2","name":"participant2@localhost:8180","server":"http:\/\/localhost:8180"},"federated_user":{"type":"user","id":"participant2","name":"participant2@localhost:8180","server":"http:\/\/localhost:8180"}} | | room | users | participant1 | federated_user_added | You invited {user} | {"actor":{"type":"user","id":"participant1","name":"participant1-displayname"},"federated_user":{"type":"user","id":"participant2","name":"participant2@localhost:8180","server":"http:\/\/localhost:8180"}} | | room | users | participant1 | conversation_created | You created the conversation | {"actor":{"type":"user","id":"participant1","name":"participant1-displayname"}} | + + Scenario: Authenticate as a federation user + Given the following "spreed" app config is set + | federation_enabled | yes | + Given user "participant1" creates room "room" (v4) + | roomType | 2 | + | roomName | room | + And user "participant1" adds remote "participant2" to room "room" with 200 (v4) + And user "participant2" has the following invitations (v1) + | remote_server | remote_token | + | LOCAL | room | + And user "participant2" accepts invite to room "room" of server "LOCAL" (v1) + And user "participant2" has the following invitations (v1) + Then user "participant2" is participant of the following rooms (v4) + | id | type | + | room | 2 | + Then user "federation/participant2" gets room "room" with 200 (v4) + Then user "federation/participant2" joins room "room" with 200 (v4) + And user "federation/participant2" sends message "Message 1" to room "room" with 201 + Then user "participant1" sees the following messages in room "room" with 200 + | room | actorType | actorId | actorDisplayName | message | messageParameters | parentMessage | + | room |federated_users | participant2@http://localhost:8180 | participant2@http://localhost:8180 | Message 1 | [] | |