Merge pull request #6427 from nextcloud/integration-tests-for-invites

Start with integration tests for invites
This commit is contained in:
Joas Schilling 2021-11-10 14:15:50 +01:00 коммит произвёл GitHub
Родитель a5c5f5a546 a8fd7fc03b
Коммит 7f1828094f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 140 добавлений и 11 удалений

Просмотреть файл

@ -44,6 +44,7 @@ use OCA\Talk\Events\AttendeesAddedEvent;
use OCA\Talk\Events\AttendeesRemovedEvent;
use OCA\Talk\Events\ChatEvent;
use OCA\Talk\Events\RoomEvent;
use OCA\Talk\Federation\CloudFederationProviderTalk;
use OCA\Talk\Files\Listener as FilesListener;
use OCA\Talk\Files\TemplateLoader as FilesTemplateLoader;
use OCA\Talk\Flow\RegisterOperationsListener;
@ -79,12 +80,16 @@ use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\AppFramework\IAppContainer;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Collaboration\Resources\IProviderManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\ICloudFederationProvider;
use OCP\Federation\ICloudFederationProviderManager;
use OCP\Group\Events\GroupDeletedEvent;
use OCP\Group\Events\UserAddedEvent;
use OCP\Group\Events\UserRemovedEvent;
use OCP\IConfig;
use OCP\IServerContainer;
use OCP\IUser;
use OCP\Security\CSP\AddContentSecurityPolicyEvent;
@ -166,6 +171,7 @@ class Application extends App implements IBootstrap {
$this->registerRoomActivityHooks($dispatcher);
$this->registerChatHooks($dispatcher);
$context->injectFn(\Closure::fromCallable([$this, 'registerCloudFederationProviderManager']));
}
protected function registerNotifier(IServerContainer $server): void {
@ -226,4 +232,21 @@ class Application extends App implements IBootstrap {
};
$dispatcher->addListener(Room::EVENT_AFTER_ROOM_DELETE, $listener);
}
protected function registerCloudFederationProviderManager(
IConfig $config,
ICloudFederationProviderManager $manager,
IAppContainer $appContainer): void {
if ($config->getAppValue('spreed', 'federation_enabled', 'no') !== 'yes') {
return;
}
$manager->addCloudFederationProvider(
'talk-room',
'Talk Federation',
static function () use ($appContainer): ICloudFederationProvider {
return $appContainer->get(CloudFederationProviderTalk::class);
}
);
}
}

Просмотреть файл

@ -92,6 +92,14 @@ class Config {
&& $this->getDialInInfo() !== '';
}
/**
* Determine if Talk federation is enabled on this instance
*/
public function isFederationEnabled(): bool {
// TODO: Set to default true once implementation is complete
return $this->config->getAppValue('spreed', 'federation_enabled', 'no') === 'yes';
}
public function getDialInInfo(): string {
return $this->config->getAppValue('spreed', 'sip_bridge_dialin_info');
}

Просмотреть файл

@ -37,7 +37,6 @@ use OCA\Talk\Exceptions\InvalidPasswordException;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Exceptions\UnauthorizedException;
use OCA\Talk\Federation\FederationManager;
use OCA\Talk\GuestManager;
use OCA\Talk\Manager;
use OCA\Talk\MatterbridgeManager;
@ -67,6 +66,7 @@ use OCP\IUserManager;
use OCP\User\Events\UserLiveStatusEvent;
use OCP\UserStatus\IManager as IUserStatusManager;
use OCP\UserStatus\IUserStatus;
use Psr\Log\LoggerInterface;
class RoomController extends AEnvironmentAwareController {
public const EVENT_BEFORE_ROOMS_GET = self::class . '::preGetRooms';
@ -109,8 +109,8 @@ class RoomController extends AEnvironmentAwareController {
protected $config;
/** @var Config */
protected $talkConfig;
/** @var FederationManager */
protected $federationManager;
/** @var LoggerInterface */
protected $logger;
/** @var array */
protected $commonReadMessages = [];
@ -135,7 +135,8 @@ class RoomController extends AEnvironmentAwareController {
IL10N $l10n,
IConfig $config,
Config $talkConfig,
ICloudIdManager $cloudIdManager) {
ICloudIdManager $cloudIdManager,
LoggerInterface $logger) {
parent::__construct($appName, $request);
$this->session = $session;
$this->appManager = $appManager;
@ -156,6 +157,7 @@ class RoomController extends AEnvironmentAwareController {
$this->config = $config;
$this->talkConfig = $talkConfig;
$this->cloudIdManager = $cloudIdManager;
$this->logger = $logger;
}
protected function getTalkHashHeader(): array {
@ -1129,13 +1131,16 @@ class RoomController extends AEnvironmentAwareController {
$this->guestManager->sendEmailInvitation($this->room, $participant);
return new DataResponse($data);
} elseif ($source === 'remote') {
if (!$this->federationManager->isEnabled()) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
} elseif ($source === 'remotes') {
if (!$this->talkConfig->isFederationEnabled()) {
return new DataResponse([], Http::STATUS_NOT_IMPLEMENTED);
}
try {
$newUser = $this->cloudIdManager->resolveCloudId($newParticipant);
} catch (\InvalidArgumentException $e) {
$this->logger->error($e->getMessage(), [
'exception' => $e,
]);
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
@ -1145,6 +1150,7 @@ class RoomController extends AEnvironmentAwareController {
'displayName' => $newUser->getDisplayId(),
];
} else {
$this->logger->error('Trying to add participant from unsupported source ' . $source);
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}

Просмотреть файл

@ -85,10 +85,11 @@ class FederationManager {
/**
* Determine if Talk federation is enabled on this instance
* @return bool
* @deprecated use \OCA\Talk\Config::isFederationEnabled()
*/
public function isEnabled(): bool {
// TODO: Set to default true once implementation is complete
return $this->config->getAppValue(Application::APP_ID, 'federation_enabled', 'false') === 'true';
return $this->config->getAppValue(Application::APP_ID, 'federation_enabled', 'no') === 'yes';
}
/**

Просмотреть файл

@ -236,7 +236,7 @@ class Notifications {
}
private function prepareRemoteUrl(string $remote): string {
if ($this->addressHandler->urlContainProtocol($remote)) {
if (!$this->addressHandler->urlContainProtocol($remote)) {
return 'https://' . $remote;
}
return $remote;

Просмотреть файл

@ -77,6 +77,11 @@ trait TInitialState {
'grid_videos_limit_enforced',
$this->talkConfig->getGridVideosLimitEnforced()
);
$this->initialState->provideInitialState(
'federation_enabled',
$this->talkConfig->isFederationEnabled()
);
}
protected function publishInitialStateForUser(IUser $user, IRootFolder $rootFolder, IAppManager $appManager): void {

Просмотреть файл

@ -54,6 +54,14 @@
:items="addableCircles"
@click="handleClickParticipant" />
</template>
<template v-if="addableRemotes.length !== 0">
<AppNavigationCaption
:title="t('spreed', 'Add federated users')" />
<ParticipantsList
:items="addableRemotes"
@click="handleClickParticipant" />
</template>
<AppNavigationCaption v-if="sourcesWithoutResults"
:title="sourcesWithoutResultsList" />
<Hint v-if="contactsLoading" :hint="t('spreed', 'Searching …')" />
@ -214,6 +222,12 @@ export default {
}
return []
},
addableRemotes() {
if (this.searchResults !== []) {
return this.searchResults.filter((item) => item.source === 'remotes')
}
return []
},
// Determines whether this component is used in the new group conversation creation
// context
isNewGroupConversation() {

Просмотреть файл

@ -21,6 +21,7 @@
*/
import axios from '@nextcloud/axios'
import { loadState } from '@nextcloud/initial-state'
import { generateOcsUrl } from '@nextcloud/router'
import { CONVERSATION, SHARE } from '../constants'
@ -80,6 +81,10 @@ const searchPossibleConversations = async function({ searchText, token, onlyUser
shareTypes.push(SHARE.TYPE.CIRCLE)
if (token !== 'new') {
shareTypes.push(SHARE.TYPE.EMAIL)
if (loadState('spreed', 'federation_enabled')) {
shareTypes.push(SHARE.TYPE.REMOTE)
}
}
}

Просмотреть файл

@ -1,9 +1,29 @@
import mockAxios from '../__mocks__/axios'
import { generateOcsUrl } from '@nextcloud/router'
import { loadState } from '@nextcloud/initial-state'
import { searchPossibleConversations } from './conversationsService'
import { SHARE } from '../constants'
jest.mock('@nextcloud/initial-state', () => ({
loadState: jest.fn(),
}))
describe('conversationsService', () => {
let loadStateSettings
beforeEach(() => {
loadStateSettings = {
federation_enabled: false,
}
loadState.mockImplementation((app, key) => {
if (app === 'spreed') {
return loadStateSettings[key]
}
return null
})
})
afterEach(() => {
// cleaning up the mess left behind the previous test
mockAxios.reset()

Просмотреть файл

@ -426,6 +426,11 @@ class FeatureContext implements Context, SnippetAcceptingContext {
if (isset($attendee['actorId']) && substr($attendee['actorId'], 0, strlen('"guest')) === '"guest') {
$attendee['actorId'] = sha1(self::$userToSessionId[trim($attendee['actorId'], '"')]);
}
if (isset($attendee['actorId'], $attendee['actorType']) && $attendee['actorType'] === 'federated_users') {
$attendee['actorId'] .= '@' . rtrim($this->baseUrl, '/');
}
if (isset($attendee['participantType'])) {
$attendee['participantType'] = (string)$this->mapParticipantTypeTestInput($attendee['participantType']);
}
@ -1069,7 +1074,7 @@ class FeatureContext implements Context, SnippetAcceptingContext {
}
/**
* @Then /^user "([^"]*)" adds (user|group|email|circle) "([^"]*)" to room "([^"]*)" with (\d+) \((v4)\)$/
* @Then /^user "([^"]*)" adds (user|group|email|circle|remote) "([^"]*)" to room "([^"]*)" with (\d+) \((v4)\)$/
*
* @param string $user
* @param string $newType
@ -1080,6 +1085,11 @@ class FeatureContext implements Context, SnippetAcceptingContext {
*/
public function userAddAttendeeToRoom(string $user, string $newType, string $newId, string $identifier, int $statusCode, string $apiVersion): void {
$this->setCurrentUser($user);
if ($newType === 'remote') {
$newId .= '@' . $this->baseUrl;
}
$this->sendRequest(
'POST', '/apps/spreed/api/' . $apiVersion . '/room/' . self::$identifierToToken[$identifier] . '/participants',
new TableNode([
@ -2108,6 +2118,8 @@ class FeatureContext implements Context, SnippetAcceptingContext {
$this->response = $client->{$verb}($fullUrl, $options);
} catch (ClientException $ex) {
$this->response = $ex->getResponse();
} catch (\GuzzleHttp\Exception\ServerException $ex) {
$this->response = $ex->getResponse();
}
}

Просмотреть файл

@ -0,0 +1,27 @@
Feature: federation/invite
Background:
Given user "participant1" exists
Given user "participant2" exists
Scenario: federation is disabled
Given the following app config is set
| federation_enabled | no |
Given user "participant1" creates room "room" (v4)
| roomType | 3 |
| roomName | room |
And user "participant1" adds remote "participant2" to room "room" with 501 (v4)
When user "participant1" sees the following attendees in room "room" with 200 (v4)
| actorType | actorId | participantType |
| users | participant1 | 1 |
Scenario: federation is enabled
Given the following app config is set
| federation_enabled | yes |
Given user "participant1" creates room "room" (v4)
| roomType | 3 |
| roomName | room |
And user "participant1" adds remote "participant2" to room "room" with 200 (v4)
When user "participant1" sees the following attendees in room "room" with 200 (v4)
| actorType | actorId | participantType |
| users | participant1 | 1 |
| federated_users | participant2 | 3 |

Просмотреть файл

@ -112,7 +112,7 @@ class FederationTest extends TestCase {
$providerId = '3';
$roomId = 5;
$token = 'abcdefghijklmno';
$shareWith = 'test@remote.test.local';
$shareWith = 'test@https://remote.test.local';
$name = 'abcdefgh';
$owner = 'Owner\'s name';
$ownerId = 'owner';
@ -321,6 +321,10 @@ class FederationTest extends TestCase {
->with($remote, $notification)
->willReturn([]);
$this->addressHandler->method('urlContainProtocol')
->with($remote)
->willReturn(true);
$success = $this->notifications->sendShareAccepted($remote, $id, $token);
$this->assertEquals(true, $success);
@ -354,6 +358,10 @@ class FederationTest extends TestCase {
->with($remote, $notification)
->willReturn([]);
$this->addressHandler->method('urlContainProtocol')
->with($remote)
->willReturn(true);
$success = $this->notifications->sendShareDeclined($remote, $id, $token);
$this->assertEquals(true, $success);