From 3cfe0f932eaefdefa8390e0ce6c262266f6c89ca Mon Sep 17 00:00:00 2001 From: Viktor Scharf Date: Wed, 19 Jun 2024 16:15:38 +0200 Subject: [PATCH] first api test for ocm --- .drone.star | 43 +++++-- tests/TestHelpers/OcmHelper.php | 108 ++++++++++++++++++ tests/acceptance/config/behat.yml | 8 ++ tests/acceptance/features/apiOcm/ocm.feature | 20 ++++ .../features/bootstrap/OcmContext.php | 97 ++++++++++++++++ tests/config/drone/providers.json | 46 ++++++++ 6 files changed, 314 insertions(+), 8 deletions(-) create mode 100644 tests/TestHelpers/OcmHelper.php create mode 100755 tests/acceptance/features/apiOcm/ocm.feature create mode 100644 tests/acceptance/features/bootstrap/OcmContext.php create mode 100644 tests/config/drone/providers.json diff --git a/.drone.star b/.drone.star index e7b1f09452b..2924848194b 100644 --- a/.drone.star +++ b/.drone.star @@ -53,6 +53,7 @@ dirs = { "ocisRevaDataRoot": "/srv/app/tmp/ocis/owncloud/data", "ocisWrapper": "/drone/src/tests/ociswrapper", "bannedPasswordList": "tests/config/drone/banned-password-list.txt", + "ocmProviders": "tests/config/drone/providers.json", } # configuration @@ -134,6 +135,21 @@ config = { "skip": False, "tikaNeeded": True, }, + "apiOcm": { + "suites": [ + "apiOcm", + ], + "skip": False, + "federationServer": True, + "extraServerEnvironment": { + "OCIS_ADD_RUN_SERVICES": "ocm", + "GRAPH_INCLUDE_OCM_SHAREES": True, + "OCM_OCM_INVITE_MANAGER_INSECURE": True, + "OCM_OCM_SHARE_PROVIDER_INSECURE": True, + "OCM_OCM_STORAGE_PROVIDER_INSECURE": True, + "OCM_OCM_PROVIDER_AUTHORIZER_PROVIDERS_FILE": "%s" % dirs["ocmProviders"], + }, + }, }, "apiTests": { "numberOfParts": 10, @@ -797,6 +813,7 @@ def localApiTestPipeline(ctx): "emailNeeded": False, "antivirusNeeded": False, "tikaNeeded": False, + "federationServer": False, } if "localApiTests" in config: @@ -821,6 +838,7 @@ def localApiTestPipeline(ctx): ocisServer(storage, params["accounts_hash_difficulty"], extra_server_environment = params["extraServerEnvironment"], with_wrapper = True, tika_enabled = params["tikaNeeded"]) + (waitForClamavService() if params["antivirusNeeded"] else []) + (waitForEmailService() if params["emailNeeded"] else []) + + (ocisServer(storage, params["accounts_hash_difficulty"], deploy_type = "federation", extra_server_environment = params["extraServerEnvironment"]) if params["federationServer"] else []) + localApiTests(suite, storage, params["extraEnvironment"]) + logRequests(), "services": emailService() if params["emailNeeded"] else [] + clamavService() if params["antivirusNeeded"] else [], @@ -838,7 +856,8 @@ def localApiTestPipeline(ctx): def localApiTests(suite, storage, extra_environment = {}): environment = { "PATH_TO_OCIS": dirs["base"], - "TEST_SERVER_URL": "https://ocis-server:9200", + "TEST_SERVER_URL": OCIS_URL, + "TEST_SERVER_FED_URL": OCIS_FED_URL, "OCIS_REVA_DATA_ROOT": "%s" % (dirs["ocisRevaDataRoot"] if storage == "owncloud" else ""), "OCIS_SKELETON_STRATEGY": "%s" % ("copy" if storage == "owncloud" else "upload"), "SEND_SCENARIO_LINE_REFERENCES": "true", @@ -1058,7 +1077,7 @@ def coreApiTests(ctx, part_number = 1, number_of_parts = 1, storage = "ocis", ac "image": OC_CI_PHP % DEFAULT_PHP_VERSION, "environment": { "PATH_TO_OCIS": "%s" % dirs["base"], - "TEST_SERVER_URL": "https://ocis-server:9200", + "TEST_SERVER_URL": OCIS_URL, "OCIS_REVA_DATA_ROOT": "%s" % (dirs["ocisRevaDataRoot"] if storage == "owncloud" else ""), "OCIS_SKELETON_STRATEGY": "%s" % ("copy" if storage == "owncloud" else "upload"), "SEND_SCENARIO_LINE_REFERENCES": "true", @@ -1166,7 +1185,7 @@ def e2eTestPipeline(ctx): "name": "e2e-tests", "image": OC_CI_NODEJS % DEFAULT_NODEJS_VERSION, "environment": { - "BASE_URL_OCIS": "ocis-server:9200", + "BASE_URL_OCIS": OCIS_DOMAIN, "HEADLESS": "true", "RETRY": "1", "WEB_UI_CONFIG_FILE": "%s/%s" % (dirs["base"], dirs["ocisConfig"]), @@ -2002,6 +2021,7 @@ def notify(ctx): def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on = [], deploy_type = "", extra_server_environment = {}, with_wrapper = False, tika_enabled = False): user = "0:0" + container_name = "ocis-server" environment = { "OCIS_URL": OCIS_URL, "OCIS_CONFIG_DIR": "/root/.ocis/config", # needed for checking config later @@ -2039,7 +2059,11 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on = environment["APP_PROVIDER_WOPI_APP_URL"] = "http://fakeoffice:8080" environment["APP_PROVIDER_WOPI_INSECURE"] = "true" environment["APP_PROVIDER_WOPI_WOPI_SERVER_EXTERNAL_URL"] = "http://wopiserver:9300" - environment["APP_PROVIDER_WOPI_FOLDER_URL_BASE_URL"] = "https://ocis-server:9200" + environment["APP_PROVIDER_WOPI_FOLDER_URL_BASE_URL"] = OCIS_URL + + if deploy_type == "federation": + environment["OCIS_URL"] = OCIS_FED_URL + container_name = "federation-ocis-server" if tika_enabled: environment["FRONTEND_FULL_TEXT_SEARCH_ENABLED"] = True @@ -2061,22 +2085,24 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on = wrapper_commands = [ "make -C %s build" % dirs["ocisWrapper"], - "%s/bin/ociswrapper serve --bin %s --url %s --admin-username admin --admin-password admin" % (dirs["ocisWrapper"], ocis_bin, OCIS_URL), + "%s/bin/ociswrapper serve --bin %s --url %s --admin-username admin --admin-password admin" % (dirs["ocisWrapper"], ocis_bin, environment["OCIS_URL"]), ] wait_for_ocis = { - "name": "wait-for-ocis-server", + "name": "wait-for-%s" % (container_name), "image": OC_CI_ALPINE, "commands": [ # wait for ocis-server to be ready (5 minutes) - "timeout 300 bash -c 'while [ $(curl -sk -uadmin:admin https://ocis-server:9200/graph/v1.0/users/admin -w %{http_code} -o /dev/null) != 200 ]; do sleep 1; done'", + "timeout 300 bash -c 'while [ $(curl -sk -uadmin:admin " + + "%s/graph/v1.0/users/admin " % environment["OCIS_URL"] + + "-w %{http_code} -o /dev/null) != 200 ]; do sleep 1; done'", ], "depends_on": depends_on, } return [ { - "name": "ocis-server", + "name": container_name, "image": OC_CI_GOLANG, "detach": True, "environment": environment, @@ -2451,6 +2477,7 @@ def pipelineSanityChecks(ctx, pipelines): OCIS_URL = "https://ocis-server:9200" OCIS_DOMAIN = "ocis-server:9200" OC10_URL = "http://oc10:8080" +OCIS_FED_URL = "https://federation-ocis-server:9200" # step volumes stepVolumeOC10Templates = \ diff --git a/tests/TestHelpers/OcmHelper.php b/tests/TestHelpers/OcmHelper.php new file mode 100644 index 00000000000..fac65dce05f --- /dev/null +++ b/tests/TestHelpers/OcmHelper.php @@ -0,0 +1,108 @@ + + * @copyright Copyright (c) 2024 Viktor Scharf + */ + +namespace TestHelpers; + +use GuzzleHttp\Exception\GuzzleException; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +/** + * A helper class for managing federation server requests + */ +class OcmHelper { + /** + * @return string[] + */ + private static function getRequestHeaders(): array { + return [ + 'Content-Type' => 'application/json', + ]; + } + + /** + * @param string $baseUrl + * @param string $path + * + * @return string + */ + public static function getFullUrl(string $baseUrl, string $path): string { + $fullUrl = $baseUrl; + if (\substr($fullUrl, -1) !== '/') { + $fullUrl .= '/'; + } + $fullUrl .= 'sciencemesh/' . $path; + return $fullUrl; + } + + /** + * @param string $baseUrl + * @param string $xRequestId + * @param string $user + * @param string $password + * @param string|null $email + * @param string|null $description + * + * @return ResponseInterface + * @throws GuzzleException + */ + public static function createInvitation( + string $baseUrl, + string $xRequestId, + string $user, + string $password, + ?string $email = null, + ?string $description = null + ): ResponseInterface { + $body['params'] = [ + "description" => $description, + "recipient" => $email + ]; + $url = self::getFullUrl($baseUrl, 'generate-invite'); + return HttpRequestHelper::post( + $url, + $xRequestId, + $user, + $password, + self::getRequestHeaders(), + \json_encode($body) + ); + } + + /** + * @param string $baseUrl + * @param string $xRequestId + * @param string $user + * @param string $password + * @param string $token + * + * @return ResponseInterface + * @throws GuzzleException + */ + public static function acceptInvitation( + string $baseUrl, + string $xRequestId, + string $user, + string $password, + string $token + ): ResponseInterface { + $body = [ + "token" => $token, + "providerDomain" => 'ocis-server' + ]; + $url = self::getFullUrl($baseUrl, 'accept-invite'); + return HttpRequestHelper::post( + $url, + $xRequestId, + $user, + $password, + self::getRequestHeaders(), + \json_encode($body) + ); + } +} diff --git a/tests/acceptance/config/behat.yml b/tests/acceptance/config/behat.yml index 30040dc9a13..5add91e69ac 100644 --- a/tests/acceptance/config/behat.yml +++ b/tests/acceptance/config/behat.yml @@ -357,6 +357,14 @@ default: - PublicWebDavContext: - OcisConfigContext: + apiOcm: + paths: + - "%paths.base%/../features/apiOcm" + context: *common_ldap_suite_context + contexts: + - FeatureContext: *common_feature_context_params + - OcmContext: + extensions: rdx\behatvars\BehatVariablesExtension: ~ diff --git a/tests/acceptance/features/apiOcm/ocm.feature b/tests/acceptance/features/apiOcm/ocm.feature new file mode 100755 index 00000000000..42aeaaea7b0 --- /dev/null +++ b/tests/acceptance/features/apiOcm/ocm.feature @@ -0,0 +1,20 @@ +Feature: an user shares resources usin ScienceMesh application + As a user + I want to share resources between different ocis instances + + Background: + Given these users have been created with default attributes and without skeleton files: + | username | + | Alice | + And using server "REMOTE" + And user "Brian" has been created with default attributes and without skeleton files + + + Scenario: user generates invitation + Given using server "LOCAL" + When "Alice" generates invitation + Then the HTTP status code should be "200" + When using server "REMOTE" + And "Brian" accepts invitation + Then the HTTP status code should be "200" + \ No newline at end of file diff --git a/tests/acceptance/features/bootstrap/OcmContext.php b/tests/acceptance/features/bootstrap/OcmContext.php new file mode 100644 index 00000000000..8bbb6046b5c --- /dev/null +++ b/tests/acceptance/features/bootstrap/OcmContext.php @@ -0,0 +1,97 @@ + + * + * @copyright Copyright (c) 2024, ownCloud GmbH + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +use Behat\Behat\Context\Context; +use Behat\Behat\Hook\Scope\BeforeScenarioScope; +use GuzzleHttp\Exception\GuzzleException; +use TestHelpers\OcisHelper; +use TestHelpers\OcmHelper; + +/** + * Acceptance test steps related to testing sharing ng features + */ +class OcmContext implements Context { + private FeatureContext $featureContext; + private string $invitationToken; + + /** + * This will run before EVERY scenario. + * It will set the properties for this object. + * + * @BeforeScenario + * + * @param BeforeScenarioScope $scope + * + * @return void + */ + public function before(BeforeScenarioScope $scope): void { + if (OcisHelper::isTestingOnReva()) { + return; + } + // Get the environment + $environment = $scope->getEnvironment(); + // Get all the contexts you need in this context from here + $this->featureContext = $environment->getContext('FeatureContext'); + } + + /** + * @When :user generates invitation + * @When :user generates invitation with email :email and description :description + * + * @param string $user + * @param string $email + * @param string $description + * + * @return void + * @throws GuzzleException + */ + public function userGeneratesInvitation(string $user, $email = null, $description = null): void { + $response = OcmHelper::createInvitation( + $this->featureContext->getBaseUrl(), + $this->featureContext->getStepLineRef(), + $user, + $this->featureContext->getPasswordForUser($user), + $email, + $description + ); + $this->featureContext->setResponse($response); + $this->invitationToken = $this->featureContext->getJsonDecodedResponse($this->featureContext->getResponse())['token']; + } + + /** + * @When :user accepts invitation + * + * @param string $user + * + * @return void + * @throws GuzzleException + */ + public function userAcceptsInvitation(string $user): void { + $response = OcmHelper::acceptInvitation( + $this->featureContext->getBaseUrl(), + $this->featureContext->getStepLineRef(), + $user, + $this->featureContext->getPasswordForUser($user), + $this->invitationToken + ); + $this->featureContext->setResponse($response); + } +} diff --git a/tests/config/drone/providers.json b/tests/config/drone/providers.json new file mode 100644 index 00000000000..b1f7ea740b8 --- /dev/null +++ b/tests/config/drone/providers.json @@ -0,0 +1,46 @@ +[ + { + "name": "ocis-server:9200", + "full_name": "first-ocis-instance", + "organization": "Owncloud", + "domain": "ocis-server", + "homepage": "https://owncloud.com", + "services": [ + { + "endpoint": { + "type": { + "name": "OCM", + "description": "CERNBox Open Cloud Mesh API" + }, + "name": "CERNBox - OCM API", + "path": "https://ocis-server:9200/ocm/", + "is_monitored": true + }, + "api_version": "0.0.1", + "host": "ocis-server:9200" + } + ] + }, + { + "name": "federation-ocis-server:9200", + "full_name": "Federation ocis", + "organization": "Owncloud", + "domain": "federation-ocis-server", + "homepage": "https://owncloud.com", + "services": [ + { + "endpoint": { + "type": { + "name": "OCM", + "description": "CERNBox Open Cloud Mesh API" + }, + "name": "CERNBox - OCM API", + "path": "https:federation-ocis-server:9200/ocm/", + "is_monitored": true + }, + "api_version": "0.0.1", + "host": "federation-ocis-server:9200" + } + ] + } +]