diff --git a/Makefile b/Makefile index deab47a..16ddb5c 100644 --- a/Makefile +++ b/Makefile @@ -193,7 +193,6 @@ buildapp-tests: ln -s ../ $(app_name) && \ tar cvzfh $(appstore_package_name).tar.gz \ --exclude="$(app_name)/build" \ - --exclude="$(app_name)/Makefile" \ --exclude="$(app_name)/*.log" \ --exclude="$(app_name)/js/node_modules" \ --exclude="$(app_name)/js/tests" \ diff --git a/appinfo/routes.php b/appinfo/routes.php index 02cb425..ed120de 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -8,85 +8,37 @@ * without the controller part, the stuff after the hash is the method. * eg. page#index -> OCA\Invitation\Controller\PageController->index() * - * + * * General endpoint syntax follows REST good practices: * /resource/{resourceProperty}?param=value - * + * * Query parameter names are written camel case: * eg. GET /remote-users?cloudId=jimmie@rd-1.nl@surf.nl * Query filter, sorting, pagination, navigation parameter names are written snake case: - * eg. _next, - * _sort, - * timestamp_after ('_after' filter parameter name appended to entity parameter name) - * + * eg. _next, + * _sort, + * timestamp_after ('_after' filter parameter name appended to parameter (resource property) name) + * */ declare(strict_types=1); return [ - 'resources' => [ - 'note' => ['url' => '/notes'], - 'note_api' => ['url' => '/api/0.1/notes'] - ], - 'ocs' => [ - ['root' => '/invitation', 'name' => 'ocs#find_by_token', 'url' => '/invitations/{token}', 'verb' => 'GET'], - ], 'routes' => [ - // bespoke API - invitation - // ['name' => 'invitation#index', 'url' => '/index', 'verb' => 'GET'], - ['name' => 'invitation#find_by_token', 'url' => '/invitations/{token}', 'verb' => 'GET'], - ['name' => 'invitation#find', 'url' => '/invitations', 'verb' => 'GET'], + ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], - // unprotected endpoint /invitation - ['name' => 'invitation#invitation', 'url' => '/invite/{token}', 'verb' => 'GET'], - ['name' => 'invitation#invitation_form', 'url' => '/invitation-form', 'verb' => 'GET'], - ['name' => 'invitation#generate_invite', 'url' => '/generate-invite', 'verb' => 'POST'], - ['name' => 'invitation#handle_invite', 'url' => '/handle-invite', 'verb' => 'GET'], - ['name' => 'invitation#accept_invite', 'url' => '/accept-invite/{token}', 'verb' => 'PUT'], - ['name' => 'invitation#decline_invite', 'url' => '/decline-invite/{token}', 'verb' => 'PUT'], - ['name' => 'invitation#update', 'url' => '/update-invitation', 'verb' => 'PUT'], + ['name' => 'invitation#get_by_token', 'url' => '/invitations/{token}', 'verb' => 'GET'], + ['name' => 'invitation#update', 'url' => '/invitations/{token}', 'verb' => 'PUT'], + ['name' => 'invitation#find', 'url' => '/invitations', 'verb' => 'GET'], + ['name' => 'invitation#generate_invite', 'url' => '/invitations', 'verb' => 'POST'], - // bespoke API - remote user - ['name' => 'remote_user#search', 'url' => '/remote-user/search', 'verb' => 'GET'], - ['name' => 'remote_user#get_remote_user', 'url' => '/remote-user', 'verb' => 'GET'], - - // bespoke API - mesh registry - ['name' => 'mesh_registry#forward_invite', 'url' => '/registry/forward-invite', 'verb' => 'GET'], - - // route '/registry/invitation-service-provider' concerns remote invitation service providers - // returns the properties of the invitation service provider like endpoint, domain, name + // unprotected ['name' => 'mesh_registry#invitation_service_provider', 'url' => '/registry/invitation-service-provider', 'verb' => 'GET'], - // adds a remote invitation service provider - ['name' => 'mesh_registry#add_invitation_service_provider', 'url' => '/registry/invitation-service-provider', 'verb' => 'POST'], - // update the properties of this invitation service provider - ['name' => 'mesh_registry#update_invitation_service_provider', 'url' => '/registry/invitation-service-provider', 'verb' => 'PUT'], - ['name' => 'mesh_registry#delete_invitation_service_provider', 'url' => '/registry/invitation-service-provider', 'verb' => 'DELETE'], - - // route '/registry/invitation-service-providers' returns all providers - ['name' => 'mesh_registry#invitation_service_providers', 'url' => '/registry/invitation-service-providers', 'verb' => 'GET'], - - // route '/endpoint' of this instance - ['name' => 'mesh_registry#get_endpoint', 'url' => '/registry/endpoint', 'verb' => 'GET'], - ['name' => 'mesh_registry#set_endpoint', 'url' => '/registry/endpoint', 'verb' => 'PUT'], - - // route '/name' of this instance - ['name' => 'mesh_registry#get_name', 'url' => '/registry/name', 'verb' => 'GET'], - ['name' => 'mesh_registry#set_name', 'url' => '/registry/name', 'verb' => 'PUT'], - - // route '/share-with-invited-users-only' of this instance - ['name' => 'mesh_registry#get_allow_sharing_with_invited_users_only', 'url' => '/share-with-invited-users-only', 'verb' => 'GET'], - ['name' => 'mesh_registry#set_allow_sharing_with_invited_users_only', 'url' => '/share-with-invited-users-only', 'verb' => 'PUT'], + // unprotected + ['name' => 'mesh_registry#get_name', 'url' => '/registry/name', 'verb' => 'GET'], // OCM - Open Cloud Mesh protocol - ['name' => 'ocm#invite_accepted', 'url' => '/ocm/invite-accepted', 'verb' => 'POST'], - - // miscellaneous endpoints - ['name' => 'page#wayf', 'url' => '/page/wayf', 'verb' => 'GET'], - ['name' => 'error#invitation', 'url' => 'error/invitation', 'verb' => 'GET'], - - [ - 'name' => 'note_api#preflighted_cors', 'url' => '/api/0.1/{path}', - 'verb' => 'OPTIONS', 'requirements' => ['path' => '.+'] - ] + // unprotected + ['name' => 'ocm#invite_accepted', 'url' => '/ocm/invite-accepted', 'verb' => 'POST'], ] ]; diff --git a/composer.json b/composer.json index 6e3a36f..bc4c02a 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "nextcloud/invitation", - "description": "Enhanced federated sharing between Nextcloud instances.", + "description": "Enhanced federated sharing between EFSS instances.", "type": "project", "license": "AGPL-3.0-or-later", "authors": [ @@ -8,6 +8,9 @@ "name": "Antoon Prins" } ], + "require": { + "ramsey/uuid": "4.2.3" + }, "require-dev": { "phpunit/phpunit": "^9", "sabre/dav": "^4.1", diff --git a/img/app.svg b/img/app.svg new file mode 100644 index 0000000..f3e08e1 --- /dev/null +++ b/img/app.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 19bed00..a104114 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -18,6 +18,8 @@ class Application extends App implements IBootstrap public const CONFIG_ALLOW_SHARING_WITH_INVITED_USERS_ONLY = 'allow_sharing_with_invited_users_only'; + public const INVITATION_EMAIL_SUBJECT = 'INVITATION_EMAIL_SUBJECT'; + public function __construct() { parent::__construct(self::APP_ID); diff --git a/lib/Controller/Errors.php b/lib/Controller/Errors.php new file mode 100644 index 0000000..a328067 --- /dev/null +++ b/lib/Controller/Errors.php @@ -0,0 +1,26 @@ + +// SPDX-License-Identifier: AGPL-3.0-or-later + +namespace OCA\Invitation\Controller; + +use Closure; +use OCA\Invitation\Service\NoteNotFound; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; + +trait Errors +{ + protected function handleNotFound(Closure $callback): DataResponse + { + try { + return new DataResponse($callback()); + } catch (NoteNotFound $e) { + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } + } +} diff --git a/lib/Controller/InvitationController.php b/lib/Controller/InvitationController.php index b0bb0b1..ce6ef5a 100644 --- a/lib/Controller/InvitationController.php +++ b/lib/Controller/InvitationController.php @@ -12,119 +12,128 @@ use OCA\Invitation\AppInfo\Application; use OCA\Invitation\Db\Schema; use OCA\Invitation\Federation\Invitation; +use OCA\Invitation\HttpClient; +use OCA\Invitation\Service\ApplicationConfigurationException; use OCA\Invitation\Service\InvitationService; use OCA\Invitation\Service\MeshRegistry\MeshRegistryService; use OCA\Invitation\Service\NotFoundException; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; -use OCP\ILogger; +use OCP\IAppConfig; +use OCP\IConfig; +use OCP\IL10N; use OCP\IRequest; +use OCP\IUserSession; +use OCP\Template; +use OCP\Util; use Psr\Log\LoggerInterface; +use Ramsey\Uuid\Uuid; class InvitationController extends Controller { - private InvitationService $service; + private IConfig $systemConfig; + private IAppConfig $appConfig; + private IUserSession $session; + private InvitationService $invitationService; + private MeshRegistryService $meshRegistryService; + private IL10N $il10n; private LoggerInterface $logger; public function __construct( IRequest $request, - InvitationService $service, + IConfig $systemConfig, + IAppConfig $appConfig, + IUserSession $session, + InvitationService $invitationService, + MeshRegistryService $meshRegistryService, + IL10N $il10n, LoggerInterface $logger ) { parent::__construct(Application::APP_ID, $request); - $this->service = $service; + $this->systemConfig = $systemConfig; + $this->appConfig = $appConfig; + $this->session = $session; + $this->invitationService = $invitationService; + $this->meshRegistryService = $meshRegistryService; + $this->il10n = $il10n; $this->logger = $logger; } - // /** - // * - // * @NoAdminRequired - // * @NoCSRFRequired - // * @return TemplateResponse - // */ - // public function index(): TemplateResponse - // { - // return new TemplateResponse($this->appName, 'invitation.main'); - // } - /** - * Removes the notification that is associated with the invitation with specified token. + * Route: GET /invitation/{token} * - * @param string $token - * @return void + * @NoAdminRequired + * @NoCSRFRequired */ - private function removeInvitationNotification(string $token): void + public function getByToken(string $token = null): DataResponse { - $this->logger->debug(" - removing notification for invitation with token '$token'"); + if (!isset($token)) { + return new DataResponse( + [ + 'message' => AppError::REQUEST_MISSING_PARAMETER, + ], + Http::STATUS_NOT_FOUND, + ); + } try { - $manager = \OC::$server->getNotificationManager(); - $notification = $manager->createNotification(); - $notification - ->setApp(Application::APP_ID) - ->setUser(\OC::$server->getUserSession()->getUser()->getUID()) - ->setObject(MeshRegistryService::PARAM_NAME_TOKEN, $token); - $manager->markProcessed($notification); + $invitation = $this->invitationService->getByToken($token); + return new DataResponse( + [ + 'data' => $invitation->jsonSerialize(), + ], + Http::STATUS_OK, + ); + } catch (NotFoundException $e) { + $this->logger->error("invitation not found for token '$token'. Error: " . $e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::INVITATION_NOT_FOUND, + ], + Http::STATUS_NOT_FOUND, + ); } catch (Exception $e) { - $this->logger->error('Remove notification failed: ' . $e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); - throw $e; + $this->logger->error("invitation not found for token '$token'. Error: " . $e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::ERROR, + ], + Http::STATUS_NOT_FOUND, + ); } } /** - * Verify the /invite-accepted response for all required fields. + * Route: GET /invitations + * Example: + * https://rd-1.nl/apps/invitation/invitations?status=open|accepted + * Available parameter value operators: + * | or + * If multiple parameters are specified they all must apply (logical AND). * - * @param array $response the response to verify - * @return bool true if the response is valid, false otherwise - */ - private function verifiedInviteAcceptedResponse(array $response): bool - { - if (!isset($response) || $response[MeshRegistryService::PARAM_NAME_USER_ID] == '') { - $this->logger->error('/invite-accepted response does not contain the user id of the sender of the invitation.'); - return false; - } - if (!isset($response[MeshRegistryService::PARAM_NAME_EMAIL]) || $response[MeshRegistryService::PARAM_NAME_EMAIL] == '') { - $this->logger->error('/invite-accepted response does not contain the email of the sender of the invitation.'); - return false; - } - if (!isset($response[MeshRegistryService::PARAM_NAME_NAME]) || $response[MeshRegistryService::PARAM_NAME_NAME] == '') { - $this->logger->error('/invite-accepted response does not contain the name of the sender of the invitation.'); - return false; - } - return true; - } - - /** - * example url: https://rd-1.nl/apps/invitation/invitations?status=open,accepted - * - * @PublicPage * @NoAdminRequired * @NoCSRFRequired */ - public function find(string $status = null): DataResponse + public function find(string $status = ""): DataResponse { try { $fieldsAndValues = []; - if (isset($status)) { - // status param uses the OR operator + if ($status != "") { $fieldsAndValues['status'] = explode('|', $status); } if (empty($fieldsAndValues)) { - $this->logger->error("findAll() - missing query parameter.", ['app' => Application::APP_ID]); return new DataResponse( [ - 'success' => false, - 'error_message' => AppError::REQUEST_MISSING_PARAMETER, + 'message' => AppError::REQUEST_MISSING_PARAMETER, ], Http::STATUS_NOT_FOUND, ); } - - $invitations = $this->service->findAll($fieldsAndValues); + + $invitations = $this->invitationService->findAll($fieldsAndValues); return new DataResponse( [ - 'success' => true, 'data' => $invitations, ], Http::STATUS_OK @@ -133,8 +142,7 @@ public function find(string $status = null): DataResponse $this->logger->error('invitations not found for fields: ' . print_r($status, true) . 'Error: ' . $e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); return new DataResponse( [ - 'success' => false, - 'error_message' => AppError::ERROR, + 'message' => AppError::ERROR, ], Http::STATUS_NOT_FOUND, ); @@ -142,46 +150,328 @@ public function find(string $status = null): DataResponse } /** + * Generates an invite and sends it to the specified email address. * * @NoAdminRequired * @NoCSRFRequired + * @param string $email the email address to send the invite to + * @param string $recipientName the name of the recipient + * @param string $senderName the name of the sender + * @param string $message the message for the receiver + * @return DataResponse the result */ - public function findByToken(string $token = null): DataResponse + public function generateInvite(string $email = "", string $recipientName = "", string $senderName = "", string $message = ""): DataResponse { - if (!isset($token)) { - $this->logger->error("findByToken() - missing parameter 'token'.", ['app' => Application::APP_ID]); + if ("" == $email) { return new DataResponse( [ - 'success' => false, - 'error_message' => AppError::REQUEST_MISSING_PARAMETER, + 'message' => AppError::CREATE_INVITATION_NO_RECIPIENT_EMAIL, ], - Http::STATUS_NOT_FOUND, + Http::STATUS_NOT_FOUND + ); + } + if ("" == $recipientName) { + return new DataResponse( + [ + 'message' => AppError::CREATE_INVITATION_NO_RECIPIENT_NAME, + ], + Http::STATUS_NOT_FOUND ); } + if ("" == $senderName) { + return new DataResponse( + [ + 'message' => AppError::CREATE_INVITATION_NO_SENDER_NAME, + ], + Http::STATUS_NOT_FOUND + ); + } + if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { + return new DataResponse( + [ + 'message' => AppError::CREATE_INVITATION_EMAIL_INVALID, + ], + Http::STATUS_NOT_FOUND + ); + } + + // check pre-conditions + $preConditionFailed = $this->generateInvitePreCondition(); + if ($preConditionFailed->getStatus() != Http::STATUS_OK) { + return $preConditionFailed; + } + + if ($email === $this->session->getUser()->getEMailAddress()) { + return new DataResponse( + [ + 'message' => AppError::CREATE_INVITATION_EMAIL_IS_OWN_EMAIL, + ], + Http::STATUS_NOT_FOUND + ); + } + + $inviteLink = ''; try { - $invitation = $this->service->findByToken($token); + // generate the token + $token = Uuid::uuid4()->toString(); + + $params = [ + MeshRegistryService::PARAM_NAME_TOKEN => $token, + MeshRegistryService::PARAM_NAME_PROVIDER_ENDPOINT => $this->meshRegistryService->getInvitationServiceProvider()->getEndpoint(), + ]; + + // Check for existing open and accepted invitations for the same recipient email + // Note that accepted invitations might have another recipient's email set, so there might still already be an existing invitation + // but this will be dealt with upon acceptance of this new invitation + $fieldsAndValues = [ + Schema::VINVITATION_STATUS => [Invitation::STATUS_OPEN, Invitation::STATUS_ACCEPTED], + Schema::VINVITATION_REMOTE_USER_EMAIL => [$email] + ]; + + $invitations = $this->invitationService->findAll($fieldsAndValues); + if (count($invitations) > 0) { + return new DataResponse( + [ + "message" => AppError::CREATE_INVITATION_EXISTS, + ], + Http::STATUS_NOT_FOUND, + ); + } + + $inviteLink = $this->meshRegistryService->inviteLink($params); + } catch (ApplicationConfigurationException $e) { + $this->logger->error("An error has occurred: " . $e->getMessage() . " Stacktrace: " . $e->getTraceAsString(), ['app' => Application::APP_ID]); return new DataResponse( [ - 'success' => true, - 'data' => $invitation->jsonSerialize(), + 'message' => AppError::APPLICATION_CONFIGURATION_EXCEPTION, ], - Http::STATUS_OK, + Http::STATUS_NOT_FOUND, ); - } catch (NotFoundException $e) { - $this->logger->error("invitation not found for token '$token'. Error: " . $e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + } catch (Exception $e) { + $this->logger->error("An error has occurred: " . $e->getMessage() . " Stacktrace: " . $e->getTraceAsString(), ['app' => Application::APP_ID]); return new DataResponse( [ - 'success' => false, - 'error_message' => AppError::INVITATION_NOT_FOUND, + 'message' => AppError::CREATE_INVITATION_ERROR, ], Http::STATUS_NOT_FOUND, ); + } + + // persist the invite to send + $invitation = new Invitation(); + $invitation->setUserCloudId($this->session->getUser()->getCloudId()); + $invitation->setToken($token); + $invitation->setProviderEndpoint($this->meshRegistryService->getInvitationServiceProvider()->getEndpoint()); + $invitation->setSenderCloudId($this->session->getUser()->getCloudId()); + $invitation->setSenderEmail($this->session->getUser()->getEMailAddress()); + $invitation->setSenderName($senderName); + $invitation->setRecipientEmail($email); + $invitation->setTimestamp(time()); + $invitation->setStatus(Invitation::STATUS_NEW); + + try { + $mailer = \OC::$server->getMailer(); + $mail = $mailer->createMessage(); + $mail->setSubject($this->il10n->t(Application::INVITATION_EMAIL_SUBJECT)); + $mail->setFrom([$this->getEmailFromAddress('invitation-no-reply')]); + $mail->setTo(array($email => $email)); + $language = 'en'; // actually not used, the email itself is multi language + $htmlText = $this->getMailBody($inviteLink, $recipientName, $message, 'html', $language); + $mail->setHtmlBody($htmlText); + $plainText = $this->getMailBody($inviteLink, $recipientName, $message, 'text', $language); + $mail->setPlainBody($plainText); + $failedRecipients = $mailer->send($mail); + if (sizeof($failedRecipients) > 0) { + $this->logger->error(' - failed recipients: ' . print_r($failedRecipients, true), ['app' => Application::APP_ID]); + } } catch (Exception $e) { - $this->logger->error("invitation not found for token '$token'. Error: " . $e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + // TODO Instead of failing, we could continue and still insert and display the invitation as failed in the list + // this would probably work best with a modify and resend option + + // So just continue for now + } + + // when all's well set status to open and persist + $invitation->setStatus(Invitation::STATUS_OPEN); + try { + $newInvitation = $this->invitationService->insert($invitation); + $this->logger->debug(print_r($newInvitation, true)); + } catch (Exception $e) { + $this->logger->error('An error occurred while generating the invite: ' . $e->getMessage(), ['app' => Application::APP_ID]); return new DataResponse( [ - 'success' => false, - 'error_message' => AppError::ERROR, + 'message' => AppError::CREATE_INVITATION_ERROR, + ], + Http::STATUS_NOT_FOUND + ); + } + + if (isset($newInvitation) && $invitation->getId() > 0) { + return new DataResponse( + [ + 'data' => [ + 'token' => $newInvitation->getToken(), + 'inviteLink' => $inviteLink, + 'email' => $email, + 'recipientName' => $recipientName, + 'senderName' => $senderName, + 'message' => $message, + ], + ], + Http::STATUS_OK + ); + } + $this->logger->error("Create invitation failed with no further info.", ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::CREATE_INVITATION_ERROR + ], + Http::STATUS_NOT_FOUND + ); + } + + /** + * Accept the received invitation with the specified token. + * + * @param string $token the token + * @return DataResponse if successfull, echoes the invitation token + */ + private function acceptInvite(string $token = ''): DataResponse + { + try { + if ($token == '') { + $this->logger->error('acceptInvite: missing parameter token.', ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::REQUEST_MISSING_PARAMETER + ], + Http::STATUS_NOT_FOUND + ); + } + + $invitation = null; + try { + $invitation = $this->invitationService->getByToken($token); + } catch (NotFoundException $e) { + $this->logger->error("acceptInvite: invitation not found for token '$token'", ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::INVITATION_NOT_FOUND + ], + Http::STATUS_NOT_FOUND + ); + } + + // check pre-conditions + $preConditionFailed = $this->acceptInvitePreCondition(); + if ($preConditionFailed->getStatus() != Http::STATUS_OK) { + return $preConditionFailed; + } + + $recipientEndpoint = $this->meshRegistryService->getEndpoint(); + $recipientCloudID = $this->session->getUser()->getCloudId(); + $recipientEmail = $this->session->getUser()->getEMailAddress(); + $recipientName = $this->session->getUser()->getDisplayName(); + $params = [ + MeshRegistryService::PARAM_NAME_RECIPIENT_PROVIDER => $recipientEndpoint, + MeshRegistryService::PARAM_NAME_TOKEN => $token, + MeshRegistryService::PARAM_NAME_USER_ID => $recipientCloudID, + MeshRegistryService::PARAM_NAME_EMAIL => $recipientEmail, + MeshRegistryService::PARAM_NAME_NAME => $recipientName, + ]; + + $url = $this->meshRegistryService->getFullInviteAcceptedEndpointURL($invitation->getProviderEndpoint()); + $httpClient = new HttpClient($this->logger); + $response = $httpClient->curlPost($url, $params); + + if (isset($response['success']) && $response['success'] == false) { + $this->logger->error('Failed to accept the invitation: /invite-accepted failed with response: ' . print_r($response, true), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => (isset($response['error_message']) ? $response['error_message'] : AppError::HANDLE_INVITATION_ERROR) + ], + Http::STATUS_NOT_FOUND + ); + } + // note: beware of the format of response of the OCM call, it has no 'data' field + if ($this->verifiedInviteAcceptedResponse($response) == false) { + $this->logger->error('Failed to accept the invitation - returned fields not valid: ' . print_r($response, true), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::HANDLE_INVITATION_OCM_INVITE_ACCEPTED_RESPONSE_FIELDS_INVALID + ], + Http::STATUS_NOT_FOUND + ); + } + + // withdraw any previous accepted invitation from the same inviter + $existingInvitationsReceived = $this->invitationService->findAll([ + [Schema::VINVITATION_SENDER_CLOUD_ID => $response[MeshRegistryService::PARAM_NAME_USER_ID]], + [Schema::VINVITATION_RECIPIENT_CLOUD_ID => $recipientCloudID], + [Schema::VINVITATION_STATUS => Invitation::STATUS_ACCEPTED], + ]); + $existingInvitationsSent = $this->invitationService->findAll([ + [Schema::VINVITATION_RECIPIENT_CLOUD_ID => $response[MeshRegistryService::PARAM_NAME_USER_ID]], + [Schema::VINVITATION_SENDER_CLOUD_ID => $recipientCloudID], + [Schema::VINVITATION_STATUS => Invitation::STATUS_ACCEPTED], + ]); + $existingInvitations = array_merge($existingInvitationsReceived, $existingInvitationsSent); + if (count($existingInvitations) > 0) { + foreach ($existingInvitations as $existingInvitation) { + $this->logger->debug("A previous invitation for remote user with name " . $response[MeshRegistryService::PARAM_NAME_NAME] . " was accepted already. Withdrawing that one", ['app' => Application::APP_ID]); + $updateResult = $this->invitationService->update([ + Schema::INVITATION_TOKEN => $existingInvitation->getToken(), + Schema::INVITATION_STATUS => Invitation::STATUS_WITHDRAWN, + ]); + if ($updateResult == false) { + return new DataResponse( + [ + 'message' => AppError::ACCEPT_INVITE_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + } + } + + // all's well, update the open invitation + $updateResult = $this->invitationService->update( + [ + Schema::INVITATION_TOKEN => $invitation->getToken(), + Schema::INVITATION_SENDER_CLOUD_ID => $response[MeshRegistryService::PARAM_NAME_USER_ID], + Schema::INVITATION_SENDER_EMAIL => $response[MeshRegistryService::PARAM_NAME_EMAIL], + Schema::INVITATION_SENDER_NAME => $response[MeshRegistryService::PARAM_NAME_NAME], + Schema::INVITATION_STATUS => Invitation::STATUS_ACCEPTED, + ], + true + ); + if ($updateResult == false) { + $this->logger->error("Failed to handle /accept-invite (invitation with token '$token' could not be updated).", ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::ACCEPT_INVITE_ERROR, + ], + Http::STATUS_NOT_FOUND + ); + } + + $this->removeInvitationNotification($token); + + return new DataResponse( + [ + 'data' => [ + "token" => $token, + "status" => Invitation::STATUS_ACCEPTED + ], + ], + Http::STATUS_OK + ); + } catch (Exception $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app]' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::ACCEPT_INVITE_ERROR, ], Http::STATUS_NOT_FOUND, ); @@ -203,14 +493,17 @@ public function update(string $token, string $status): DataResponse if (!isset($token) && !isset($status)) { return new DataResponse( [ - 'success' => false, - 'error_message' => AppError::UPDATE_INVITATION_ERROR + 'message' => AppError::UPDATE_INVITATION_ERROR ], Http::STATUS_NOT_FOUND, ); } - $result = $this->service->update([ + if (Invitation::STATUS_ACCEPTED === $status) { + return $this->acceptInvite($token); + } + + $result = $this->invitationService->update([ Schema::INVITATION_TOKEN => $token, Schema::INVITATION_STATUS => $status, ]); @@ -226,18 +519,154 @@ public function update(string $token, string $status): DataResponse if ($result === true) { return new DataResponse( [ - 'success' => true, - 'data' => $result, + 'data' => [ + "token" => $token, + "status" => $status + ], ], Http::STATUS_OK, ); } return new DataResponse( [ - 'success' => false, - 'error_message' => AppError::UPDATE_INVITATION_ERROR + 'message' => AppError::UPDATE_INVITATION_ERROR ], Http::STATUS_NOT_FOUND, ); } + + /** + * Returns a DataResponse with an error why the precondition failed, + * or null when it hasn't. + */ + private function generateInvitePreCondition(): DataResponse + { + $_userEmail = $this->session->getUser()->getEMailAddress(); + if (!isset($_userEmail) || $_userEmail === '') { + return new DataResponse( + [ + 'message' => AppError::CREATE_INVITATION_ERROR_SENDER_EMAIL_MISSING, + ], + Http::STATUS_NOT_FOUND, + ); + } + return new DataResponse( + [ + 'success' => true, + ], + Http::STATUS_OK, + ); + } + + /** + * Get the email from address. + * Can be explicitly set using system config: 'invitation_mail_from_address'. + * Otherwise uses the default config which uses the optional system config 'mail_from_address' and 'mail_domain' keys. + * + * @param string $address the address part in 'address@maildomain.com' + * @return string + */ + private function getEmailFromAddress(string $address = null) + { + if (empty($address)) { + $address = 'no-reply'; + } + $senderAddress = Util::getDefaultEmailAddress($address); + return $this->systemConfig->getSystemValue('invitation_mail_from_address', $senderAddress); + } + + /** + * Returns the mail body rendered according to the specified target template. + * @param string $inviteLink the invite link + * @param string $recipientName the name of the recipient + * @param string $message additional message to render + * @param string $targetTemplate on of 'html', 'text' + * @param string $languageCode the language code to use + * @return string the rendered body + */ + private function getMailBody(string $inviteLink, string $recipientName, string $message, string $targetTemplate = 'html', string $languageCode = '') + { + $tmpl = new Template('invitation', "mail/$targetTemplate", '', false, $languageCode); + $tmpl->assign('recipientName', $recipientName); + $tmpl->assign('fromName', $this->session->getUser()->getDisplayName()); + $tmpl->assign('inviteLink', $inviteLink); + $tmpl->assign('message', $message); + return $tmpl->fetchPage(); + } + + /** + * Removes the notification that is associated with the invitation with specified token. + * + * @param string $token + * @return void + */ + private function removeInvitationNotification(string $token): void + { + $this->logger->debug(" - removing notification for invitation with token '$token'"); + try { + $manager = \OC::$server->getNotificationManager(); + $notification = $manager->createNotification(); + $notification + ->setApp(Application::APP_ID) + ->setUser($this->session->getUser()->getUID()) + ->setObject(MeshRegistryService::PARAM_NAME_TOKEN, $token); + $manager->markProcessed($notification); + } catch (Exception $e) { + $this->logger->error('Remove notification failed: ' . $e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => InvitationApp::APP_NAME]); + throw $e; + } + } + + /** + * Returns a DataResponse with an error why the precondition failed, + * or null when it hasn't. + */ + private function acceptInvitePreCondition(): DataResponse + { + $_userEmail = $this->session->getUser()->getEMailAddress(); + if (!isset($_userEmail) || $_userEmail === '') { + return new DataResponse( + [ + 'message' => AppError::ACCEPT_INVITE_ERROR_RECIPIENT_EMAIL_MISSING, + ], + Http::STATUS_NOT_FOUND, + ); + } + $_userName = $this->session->getUser()->getDisplayName(); + if (!isset($_userName) || $_userName === '') { + return new DataResponse( + [ + 'message' => AppError::ACCEPT_INVITE_ERROR_RECIPIENT_NAME_MISSING, + ], + Http::STATUS_NOT_FOUND, + ); + } + return new DataResponse( + [], + Http::STATUS_OK, + ); + } + + /** + * Verify the /invite-accepted response for all required fields. + * + * @param array $response the response to verify + * @return bool true if the response is valid, false otherwise + */ + private function verifiedInviteAcceptedResponse(array $response): bool + { + if (!isset($response) || $response[MeshRegistryService::PARAM_NAME_USER_ID] == '') { + $this->logger->error('/invite-accepted response does not contain the user id of the sender of the invitation.'); + return false; + } + if (!isset($response[MeshRegistryService::PARAM_NAME_EMAIL]) || $response[MeshRegistryService::PARAM_NAME_EMAIL] == '') { + $this->logger->error('/invite-accepted response does not contain the email of the sender of the invitation.'); + return false; + } + if (!isset($response[MeshRegistryService::PARAM_NAME_NAME]) || $response[MeshRegistryService::PARAM_NAME_NAME] == '') { + $this->logger->error('/invite-accepted response does not contain the name of the sender of the invitation.'); + return false; + } + return true; + } } diff --git a/lib/Controller/MeshRegistryController.php b/lib/Controller/MeshRegistryController.php new file mode 100644 index 0000000..e58db61 --- /dev/null +++ b/lib/Controller/MeshRegistryController.php @@ -0,0 +1,521 @@ +meshRegistryService = $meshRegistryService; + $this->logger = $logger; + } + + /** + * Provides the caller with a list (WAYF page) of mesh EFSS invitation service providers to choose from. + + * @NoCSRFRequired + * @PublicPage + * + * @param string $token the token + * @param string $providerEndpoint the endpoint of the sender + * @param string $name the name of the sender + * @return Response + */ + public function forwardInvite(string $token = '', string $providerEndpoint = ''): Response + { + $urlGenerator = \OC::$server->getURLGenerator(); + + if ($token == '') { + $this->logger->error('Invite is missing the token.', ['app' => Application::APP_ID]); + return new RedirectResponse( + $urlGenerator->linkToRoute( + Application::APP_ID . '.error.invitation', + [ + 'message' => AppError::HANDLE_INVITATION_MISSING_TOKEN + ] + ) + ); + } + if ($providerEndpoint == '') { + $this->logger->error('Invite is missing the invitation service provider endpoint.', ['app' => Application::APP_ID]); + return new RedirectResponse( + $urlGenerator->linkToRoute( + Application::APP_ID . '.error.invitation', + [ + 'message' => AppError::HANDLE_INVITATION_MISSING_PROVIDER_ENDPOINT + ] + ) + ); + } + if (!$this->meshRegistryService->isKnowInvitationServiceProvider($providerEndpoint)) { + $this->logger->error("Invitation service provider endpoint '$providerEndpoint' is unknown.", ['app' => Application::APP_ID]); + return new RedirectResponse( + $urlGenerator->linkToRoute( + Application::APP_ID . '.error.invitation', + [ + 'message' => AppError::HANDLE_INVITATION_PROVIDER_UNKNOWN + ] + ) + ); + } + + $urlGenerator = \OC::$server->getURLGenerator(); + $params = [ + MeshRegistryService::PARAM_NAME_TOKEN => $token, + MeshRegistryService::PARAM_NAME_PROVIDER_ENDPOINT => $providerEndpoint, + ]; + return new RedirectResponse( + $urlGenerator->linkToRoute($this->meshRegistryService->getWayfPageRoute(), $params) + ); + } + + /** + * Returns the properties of the this invitation service provider. + * + * @PublicPage + * @NoCSRFRequired + * + * @return DataResponse ['data' => :InvitationServiceProvider] + */ + public function invitationServiceProvider(): DataResponse + { + try { + return new DataResponse( + [ + 'data' => $this->meshRegistryService->getInvitationServiceProvider()->jsonSerialize(), + ], + Http::STATUS_OK, + ); + } catch (NotFoundException $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_GET_PROVIDER_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + } + + /** + * Updates this instance's invitation service provider properties. + * + * @NoCSRFRequired + * + * @param string $endpoint + * @param string $name + * @return DataResponse + */ + public function updateInvitationServiceProvider(string $endpoint, string $name): DataResponse + { + try { + $fieldsArray = ['endpoint' => $endpoint, 'name' => $name]; + + $endpoint = ""; + try { + $endpoint = $this->meshRegistryService->getEndpoint(); + } catch (ApplicationConfigurationException $e) { + // no endpoint yet, this is the initialization of this instances provider + } + + // check the endpoint connection + $url = $this->meshRegistryService->getFullInvitationServiceProviderEndpointUrl($fieldsArray['endpoint']); + $httpClient = new HttpClient($this->logger); + $response = $httpClient->curlGet($url); + if ($response['success'] == false) { + $this->logger->error('Failed to call ' . MeshRegistryService::ENDPOINT_INVITATION_SERVICE_PROVIDER . " on endpoint '$endpoint'. Response: " . print_r($response, true), ['app' => Application::APP_ID]); + throw new ServiceException("Failed to call endpoint '$endpoint'"); + } + + $isp = $this->meshRegistryService->updateInvitationServiceProvider($endpoint, $fieldsArray); + + return new DataResponse( + [ + 'data' => $isp->jsonSerialize(), + ], + Http::STATUS_OK, + ); + } catch (Exception $e) { + $this->logger->error($e->getMessage() . " Trace: " . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_SET_ENDPOINT_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + } + + /** + * Returns all registered invitation service providers. + * + * @NoCSRFRequired + * @PublicPage + * @return DataResponse ['data' => [:InvitationServiceProvider](an array of InvitationServiceProvider objects)] + */ + public function invitationServiceProviders(): DataResponse + { + try { + $providers = $this->meshRegistryService->allInvitationServiceProviders(); + return new DataResponse( + [ + 'data' => $providers, + ], + Http::STATUS_OK, + ); + } catch (ServiceException $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_ALL_PROVIDERS_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + } + + /** + * Adds a new invitation service provider with the specified endpoint. + * The properties of the provider will be requested through the specified endpoint. + * If this fails an HTTP error will be returned. + * + * Note: if the provider already exists it's properties will become updated + * through the remote provider /registry/invitation-service-provider call. + * + * @NoCSRFRequired + * + * @param string $endpoint the endpoint of the new invitation service provider + * @return DataResponse [ ..., 'data' => :InvitationServiceProvider ] + */ + public function addInvitationServiceProvider(string $endpoint): DataResponse + { + try { + // some sanitizing + $endpoint = trim(trim($endpoint), '/'); + + if ($endpoint === $this->meshRegistryService->getEndpoint()) { + return new DataResponse( + [ + 'message' => AppError::SETTINGS_ADD_PROVIDER_IS_NOT_REMOTE_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + + // check whether the provider is not already registered + try { + $provider = $this->meshRegistryService->findInvitationServiceProvider($endpoint); + $this->logger->error("The provider with endpoint $endpoint is already registered", ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_ADD_PROVIDER_EXISTS_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } catch (NotFoundException $e) { + // all good + } + + $url = $this->meshRegistryService->getFullInvitationServiceProviderEndpointUrl($endpoint); + $httpClient = new HttpClient($this->logger); + $response = $httpClient->curlGet($url); + if ($response['success'] == false) { + $this->logger->error('Failed to call ' . MeshRegistryService::ENDPOINT_INVITATION_SERVICE_PROVIDER . " on endpoint '$endpoint'. Response: " . print_r($response, true), ['app' => Application::APP_ID]); + throw new ServiceException("Failed to call endpoint '$endpoint'"); + } + + $data = (array)$response['data']; + $verified = $this->verifyInvitationServiceProviderResponse($data); + $this->logger->debug(print_r($data, true)); + if ($verified === true) { + $invitationServiceProvider = new InvitationServiceProvider(); + $invitationServiceProvider->setEndpoint($data[Schema::INVITATION_SERVICE_PROVIDER_ENDPOINT]); + $invitationServiceProvider->setDomain($data[Schema::INVITATION_SERVICE_PROVIDER_DOMAIN]); + $invitationServiceProvider->setName($data[Schema::INVITATION_SERVICE_PROVIDER_NAME]); + + $invitationServiceProvider = $this->meshRegistryService->addInvitationServiceProvider($invitationServiceProvider); + + return new DataResponse( + [ + 'data' => $invitationServiceProvider->jsonSerialize(), + ] + ); + } + + throw new ServiceException(AppError::MESH_REGISTRY_ENDPOINT_INVITATION_SERVICE_PROVIDER_RESPONSE_INVALID); + } catch (ServiceException $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + // try to delete the previously inserted new provider + $this->meshRegistryService->deleteInvitationServiceProvider($endpoint); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_ADD_PROVIDER_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } catch (Exception $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + // final effort trying to delete the previously inserted new provider + $this->meshRegistryService->deleteInvitationServiceProvider($endpoint); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_ADD_PROVIDER_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + } + + /** + * Validates the service provider response fields + * + * @param array $params + * @return bool true if validated, false otherwise + */ + private function verifyInvitationServiceProviderResponse(array $params): bool + { + if ( + is_array($params) + && isset($params[Schema::INVITATION_SERVICE_PROVIDER_ENDPOINT]) + && isset($params[Schema::INVITATION_SERVICE_PROVIDER_DOMAIN]) + && isset($params[Schema::INVITATION_SERVICE_PROVIDER_NAME]) + ) { + return true; + } + $this->logger->error('Could not validate the response fields. Fields: ' . print_r($params, true), ['app' => Application::APP_ID]); + return false; + } + + /** + * Deletes the invitation service provider with the specified endpoint. + * + * @NoCSRFRequired + * + * @param string $endpoint the endpoint of the invitation service provider to delete + * @return DataResponse if successfull, echoes the endpoint of the deleted service provider + */ + public function deleteInvitationServiceProvider(string $endpoint): DataResponse + { + try { + $invitationServiceProvider = $this->meshRegistryService->deleteInvitationServiceProvider($endpoint); + return new DataResponse( + [ + 'data' => $endpoint + ], + Http::STATUS_OK, + ); + } catch (ServiceException $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_DELETE_PROVIDER_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + } + + /** + * Whether only sharing with invited users is allowed. + * + * @NoCSRFRequired + * + * @param bool $allow + * @return DataResponse + */ + public function setAllowSharingWithInvitedUsersOnly(bool $allow): DataResponse + { + try { + $result = $this->meshRegistryService->setAllowSharingWithInvitedUsersOnly(boolval($allow)); + return new DataResponse( + [ + 'data' => $result, + ], + Http::STATUS_OK + ); + } catch (Exception $e) { + $this->logger->error("Unable to set 'allow_sharing_with_invited_users_only' config param. " . $e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_SET_ALLOW_SHARING_WITH_INVITED_USERS_ONLY_ERROR + ], + Http::STATUS_NOT_FOUND + ); + } + } + + /** + * Returnes this instance's invitation service provider endpoint. + * + * @PublicPage + * @NoCSRFRequired + * + * @return DataResponse + */ + public function getEndpoint(): DataResponse + { + try { + $endpoint = $this->meshRegistryService->getEndpoint(); + return new DataResponse( + [ + 'data' => $endpoint, + ], + Http::STATUS_OK, + ); + } catch (ServiceException $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_GET_ENDPOINT_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + } + + /** + * Sets the endpoint of this invitation service provider + * + * @NoCSRFRequired + * + * @param string $endpoint + * @return DataResponse + */ + public function setEndpoint(string $endpoint): DataResponse + { + try { + $endpoint = $this->meshRegistryService->setEndpoint($endpoint); + return new DataResponse( + [ + 'data' => $endpoint, + ], + Http::STATUS_OK, + ); + } catch (ServiceException $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_GET_ENDPOINT_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + } + + /** + * Returnes this instance's invitation service provider name. + * + * @PublicPage + * @NoCSRFRequired + * + * @return DataResponse + */ + public function getName(): DataResponse + { + try { + $name = $this->meshRegistryService->getName(); + return new DataResponse( + [ + 'data' => $name, + ], + Http::STATUS_OK, + ); + } catch (ServiceException $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_GET_NAME_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + } + + /** + * Sets this instance's invitation service provider name. + * + * @NoCSRFRequired + * + * @param string $name + * @return DataResponse + */ + public function setName(string $name): DataResponse + { + try { + $name = $this->meshRegistryService->setName($name); + return new DataResponse( + [ + 'data' => $name, + ], + Http::STATUS_OK, + ); + } catch (ServiceException $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_SET_NAME_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + } + + /** + * Whether only sharing with invited users is allowed. + * + * @NoCSRFRequired + * + * @return DataResponse + */ + public function getAllowSharingWithInvitedUsersOnly(): DataResponse + { + try { + $result = $this->meshRegistryService->getAllowSharingWithInvitedUsersOnly(); + return new DataResponse( + [ + 'data' => $result, + ], + Http::STATUS_OK + ); + } catch (Exception $e) { + $this->logger->error("Unable to get 'allow_sharing_with_invited_users_only' config param. " . $e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::MESH_REGISTRY_SET_ALLOW_SHARING_WITH_INVITED_USERS_ONLY_ERROR + ], + Http::STATUS_NOT_FOUND + ); + } + } +} diff --git a/lib/Controller/OcmController.php b/lib/Controller/OcmController.php new file mode 100644 index 0000000..e6237a3 --- /dev/null +++ b/lib/Controller/OcmController.php @@ -0,0 +1,184 @@ +invitationService = $invitationService; + $this->logger = $logger; + } + + /** + * Inform the sender of the invite that it has been accepted by the recipient. + * + * A previously established invitation relationship between sender and receiver will be replaced with this new one, + * provided there is an actual open invite for this /invite-accepted request. + * + * @NoCSRFRequired + * @PublicPage + * @param string $recipientProvider maps to recipient_endpoint in the Invitation entity + * @param string $token the invite token + * @param string $userID the recipient cloud ID + * @param string $email the recipient email + * @param string $name the recipient name + * @return DataResponse + */ + public function inviteAccepted( + string $recipientProvider = '', + string $token = '', + string $userID = '', + string $email = '', + string $name = '' + ): DataResponse { + $this->logger->debug(" - request: " . print_r(\OC::$server->getRequest(), true)); + if (trim($recipientProvider) == '') { + return new DataResponse( + [ + 'message' => 'recipient provider missing' + ], + Http::STATUS_NOT_FOUND + ); + } + if ($token == '') { + return new DataResponse( + [ + 'message' => 'sender token missing' + ], + Http::STATUS_NOT_FOUND + ); + } + if ($userID == '') { + return new DataResponse( + [ + 'message' => 'recipient user ID missing' + ], + Http::STATUS_NOT_FOUND + ); + } + if ($email == '') { + return new DataResponse( + [ + 'message' => 'recipient email missing' + ], + Http::STATUS_NOT_FOUND + ); + } + if ($name == '') { + return new DataResponse( + [ + 'message' => 'recipient name missing' + ], + Http::STATUS_NOT_FOUND + ); + } + + $invitation = null; + try { + $invitation = $this->invitationService->getByToken($token, false); + } catch (NotFoundException $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::OCM_INVITE_ACCEPTED_NOT_FOUND + ], + Http::STATUS_NOT_FOUND + ); + } catch (ServiceException $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::OCM_INVITE_ACCEPTED_ERROR + ], + Http::STATUS_NOT_FOUND + ); + } + + // check if there are not an established invitation relations already + // and remove those + $existingInvitationsSent = $this->invitationService->findAll([ + Schema::VINVITATION_SENDER_CLOUD_ID => [$invitation->getSenderCloudId()], + Schema::VINVITATION_RECIPIENT_CLOUD_ID => [$userID], + Schema::VINVITATION_STATUS => [Invitation::STATUS_ACCEPTED], + ], false); + $existingInvitationsReceived = $this->invitationService->findAll([ + Schema::VINVITATION_RECIPIENT_CLOUD_ID => [$invitation->getSenderCloudId()], + Schema::VINVITATION_SENDER_CLOUD_ID => [$userID], + Schema::VINVITATION_STATUS => [Invitation::STATUS_ACCEPTED], + ], false); + $existingInvitations = array_merge($existingInvitationsSent, $existingInvitationsReceived); + if (count($existingInvitations) > 0) { + foreach ($existingInvitations as $existingInvitation) { + $this->logger->debug("A previous established invitation relation exists. Withdrawing that one.", ['app' => Application::APP_ID]); + $updateResult = $this->invitationService->update([ + Schema::INVITATION_TOKEN => $existingInvitation->getToken(), + Schema::INVITATION_STATUS => Invitation::STATUS_WITHDRAWN, + ], false); + if ($updateResult == false) { + return new DataResponse( + [ + 'message' => AppError::OCM_INVITE_ACCEPTED_ERROR, + ], + Http::STATUS_NOT_FOUND, + ); + } + } + } + + // update the invitation with the receiver's info + $updateResult = $this->invitationService->update([ + Schema::VINVITATION_TOKEN => $invitation->getToken(), + Schema::VINVITATION_RECIPIENT_ENDPOINT => $recipientProvider, + Schema::VINVITATION_RECIPIENT_CLOUD_ID => $userID, + Schema::VINVITATION_RECIPIENT_EMAIL => $email, + Schema::VINVITATION_RECIPIENT_NAME => $name, + Schema::VINVITATION_STATUS => Invitation::STATUS_ACCEPTED, + ], false); + if ($updateResult == false) { + $this->logger->error("Update failed for invitation with token '$token'", ['app' => Application::APP_ID]); + return new DataResponse( + [ + 'message' => AppError::OCM_INVITE_ACCEPTED_ERROR + ], + Http::STATUS_NOT_FOUND + ); + } + + return new DataResponse( + [ + 'userID' => $invitation->getSenderCloudId(), + 'email' => $invitation->getSenderEmail(), + 'name' => $invitation->getSenderName(), + ], + Http::STATUS_OK + ); + } +} diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php new file mode 100644 index 0000000..0764eba --- /dev/null +++ b/lib/Controller/PageController.php @@ -0,0 +1,33 @@ + +// SPDX-License-Identifier: AGPL-3.0-or-later + +namespace OCA\Invitation\Controller; + +use OCA\Invitation\AppInfo\Application; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\IRequest; +use OCP\Util; + +class PageController extends Controller +{ + public function __construct(IRequest $request) + { + parent::__construct(Application::APP_ID, $request); + } + + /** + * @NoAdminRequired + * @NoCSRFRequired + */ + public function index(): TemplateResponse + { + Util::addScript(Application::APP_ID, 'invitation-main'); + + return new TemplateResponse(Application::APP_ID, 'main'); + } +} diff --git a/lib/Federation/InvitationMapper.php b/lib/Federation/InvitationMapper.php index 46e137c..27f6aee 100644 --- a/lib/Federation/InvitationMapper.php +++ b/lib/Federation/InvitationMapper.php @@ -50,7 +50,7 @@ public function find(int $id) * @return VInvitation * @throws NotFoundException */ - public function findByToken(string $token) + public function getByToken(string $token) { try { $qb = $this->db->getQueryBuilder(); @@ -86,6 +86,7 @@ public function findByToken(string $token) */ public function findAll(array $criteria): array { + $this->logger->debug(print_r($criteria, true)); $qb = $this->db->getQueryBuilder(); $qb->automaticTablePrefix(false); $query = $qb->select('*')->from(Schema::VIEW_INVITATIONS, 'i'); @@ -94,7 +95,7 @@ public function findAll(array $criteria): array if ($i == 0) { $or = $qb->expr()->orX(); foreach ($values as $value) { - $or->add($qb->expr()->eq("i.status", $qb->createNamedParameter($value))); + $or->add($qb->expr()->eq("i.$field", $qb->createNamedParameter($value))); } $query->where($or); } else { @@ -106,6 +107,7 @@ public function findAll(array $criteria): array } ++$i; } + $this->logger->debug($query->getSQL()); $query->addOrderBy(Schema::INVITATION_TIMESTAMP, 'DESC'); return $this->getVInvitations($query->executeQuery()->fetchAll()); @@ -136,7 +138,8 @@ public function updateInvitation(array $fieldsAndValues, string $userCloudID = ' $andWhere->add($qb->expr()->eq('i.' . Schema::INVITATION_USER_CLOUD_ID, $qb->createNamedParameter($userCloudID))); } $updateQuery->where($andWhere); - $result = $updateQuery->executeQuery(); + $this->logger->debug($updateQuery->getSQL()); + $result = $updateQuery->executeStatement(); if ($result === 1) { return true; } diff --git a/lib/Federation/InvitationServiceProvider.php b/lib/Federation/InvitationServiceProvider.php new file mode 100644 index 0000000..ec57c85 --- /dev/null +++ b/lib/Federation/InvitationServiceProvider.php @@ -0,0 +1,39 @@ +columnToProperty(Schema::INVITATION_SERVICE_PROVIDER_DOMAIN) => $this->domain, + $this->columnToProperty(Schema::INVITATION_SERVICE_PROVIDER_ENDPOINT) => $this->endpoint, + $this->columnToProperty(Schema::INVITATION_SERVICE_PROVIDER_NAME) => $this->name, + ]; + } +} diff --git a/lib/Federation/InvitationServiceProviderMapper.php b/lib/Federation/InvitationServiceProviderMapper.php new file mode 100644 index 0000000..298cbf7 --- /dev/null +++ b/lib/Federation/InvitationServiceProviderMapper.php @@ -0,0 +1,105 @@ +logger = $logger; + } + + /** + * Returns the local (this instance's) invitation service provider. + * + * @param string $endpoint + * @return InvitationServiceProvider + * @throws NotFoundException + */ + public function getInvitationServiceProvider(string $endpoint): InvitationServiceProvider + { + try { + $qb = $this->db->getQueryBuilder(); + $result = $qb->select('*') + ->from(Schema::TABLE_INVITATION_SERVICE_PROVIDERS, 'dp') + ->where($qb->expr()->eq('dp.' . Schema::INVITATION_SERVICE_PROVIDER_ENDPOINT, $qb->createNamedParameter($endpoint))) + ->executeQuery()->fetch(); + if (is_array($result)) { + return $this->createInvitationServiceProvider($result); + } + throw new NotFoundException("Error retrieving the invitation service provider with endpoint '$endpoint'"); + } catch (Exception $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => InvitationApp::APP_NAME]); + throw new NotFoundException("Error retrieving the endpoint provider with endpoint '$endpoint'"); + } + } + + /** + * Returns all invitation service providers + * + * @return array + * @throws NotFoundException + */ + public function allInvitationServiceProviders(): array + { + try { + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from(Schema::TABLE_INVITATION_SERVICE_PROVIDERS, 'dp'); + return $this->createInvitationServiceProviders($qb->executeQuery()->fetchAll()); + } catch (Exception $e) { + $this->logger->error($e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => InvitationApp::APP_NAME]); + throw new NotFoundException('Error retrieving all invitation service providers'); + } + } + + /** + * Builds and returns a new InvitationServiceProvider object from the specified associative array. + * @param array $associativeArray + * @return InvitationServiceProvider + */ + private function createInvitationServiceProvider(array $associativeArray): InvitationServiceProvider + { + if (isset($associativeArray) && count($associativeArray) > 0) { + $invitationServiceProvider = new InvitationServiceProvider(); + $invitationServiceProvider->setId($associativeArray['id']); + $invitationServiceProvider->setDomain($associativeArray[Schema::INVITATION_SERVICE_PROVIDER_DOMAIN]); + $invitationServiceProvider->setEndpoint($associativeArray[Schema::INVITATION_SERVICE_PROVIDER_ENDPOINT]); + $invitationServiceProvider->setName($associativeArray[Schema::INVITATION_SERVICE_PROVIDER_NAME]); + return $invitationServiceProvider; + } + $this->logger->error('Unable to create a new InvitationServiceProvider from associative array: ' . print_r($associativeArray, true), ['app' => InvitationApp::APP_NAME]); + return null; + } + + /** + * Builds and returns an array of new InvitationServiceProvider objects from the specified associatives array. + * @param array $associativeArrays + * @return array + */ + private function createInvitationServiceProviders(array $associativeArrays): array + { + $invitationServiceProviders = []; + if (isset($associativeArrays) && count($associativeArrays) > 0) { + foreach ($associativeArrays as $associativeArray) { + array_push($invitationServiceProviders, $this->createInvitationServiceProvider($associativeArray)); + } + } + return $invitationServiceProviders; + } +} diff --git a/lib/HttpClient.php b/lib/HttpClient.php new file mode 100644 index 0000000..9da0dfd --- /dev/null +++ b/lib/HttpClient.php @@ -0,0 +1,90 @@ +logger = $logger; + } + + /** + * Executes a POST request. + * + * @param string $url + * @param array $params post fields + * @return mixed returns an array in the standardized format: + * [ + * 'data' => if success is true + * or + * 'message' => if success is false + * ] + * @throws HttpException + */ + public function curlPost(string $url, array $params = []) + { + try { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params, JSON_PRETTY_PRINT)); + $output = json_decode(curl_exec($ch)); + $info = curl_getinfo($ch); + curl_close($ch); + if (!isset($output) || $output == false) { + $this->logger->debug('curl_getinfo: ' . print_r($info, true)); + throw new HttpException(AppError::HTTP_POST_CURL_REQUEST_ERROR); + } + return (array)$output; + } catch (HttpException $e) { + throw $e; + } catch (Exception $e) { + throw new HttpException(AppError::HTTP_POST_CURL_REQUEST_ERROR); + } + } + + /** + * Executes a GET request. + * + * @param string $url + * @return mixed returns an array in the standardized format: + * [ + * 'data' => if success is true + * or + * 'message' => if success is false + * ] + * @throws HttpException + */ + public function curlGet(string $url) + { + try { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); + $output = json_decode(curl_exec($ch)); + $info = curl_getinfo($ch); + curl_close($ch); + if (!isset($output) || $output == false) { + $this->logger->debug('curl_getinfo: ' . print_r($info, true)); + throw new HttpException(AppError::HTTP_GET_CURL_REQUEST_ERROR); + } + return (array)$output; + } catch (HttpException $e) { + throw $e; + } catch (Exception $e) { + throw new HttpException(AppError::HTTP_POST_CURL_REQUEST_ERROR); + } + } +} diff --git a/lib/HttpException.php b/lib/HttpException.php new file mode 100644 index 0000000..98d1d69 --- /dev/null +++ b/lib/HttpException.php @@ -0,0 +1,15 @@ +addIndex([Schema::INVITATION_TOKEN], 'invitation_token_index'); $sql = $this->dbc->getDatabasePlatform()->getCreateTableSQL($table); - foreach($sql as $statement) { + foreach ($sql as $statement) { $this->logger->debug(print_r($statement, true)); } $this->dbc->executeStatement($sql[0]); @@ -153,7 +153,7 @@ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $op $table->addUniqueIndex([Schema::INVITATION_SERVICE_PROVIDER_ENDPOINT], 'endpoint_index'); $sql = $this->dbc->getDatabasePlatform()->getCreateTableSQL($table); - foreach($sql as $statement) { + foreach ($sql as $statement) { $this->logger->debug(print_r($statement, true)); } $this->dbc->executeStatement($sql[0]); diff --git a/lib/Migration/Version20231130125300.php b/lib/Migration/Version20231130125300.php index 6f15541..f50e72c 100644 --- a/lib/Migration/Version20231130125300.php +++ b/lib/Migration/Version20231130125300.php @@ -14,7 +14,6 @@ */ class Version20231130125300 extends SimpleMigrationStep { - /** @var IDBConnection */ private $dbc; /** @var LoggerInterface */ diff --git a/lib/Service/ApplicationConfigurationException.php b/lib/Service/ApplicationConfigurationException.php new file mode 100644 index 0000000..44b7e1c --- /dev/null +++ b/lib/Service/ApplicationConfigurationException.php @@ -0,0 +1,15 @@ +mapper->findByToken($token); + $invitation = $this->mapper->getByToken($token); } catch (NotFoundException $e) { $this->logger->error("Invitation not found for token '$token'.", ['app' => Application::APP_ID]); throw new NotFoundException("An exception occurred trying to retrieve the invitation with token '$token'."); } - if ($loginRequired == true && $this->userSession->getUser() == null) { + if ($protected == true && $this->userSession->getUser() == null) { throw new ServiceException("Unable to find invitation, unauthenticated."); } if ( - $loginRequired == false + $protected == false || $this->userSession->getUser()->getCloudId() === $invitation->getUserCloudID() ) { return $invitation; @@ -90,9 +90,13 @@ public function findByToken(string $token, bool $loginRequired = true): VInvitat * @return array * @throws ServiceException */ - public function findAll(array $criteria): array + public function findAll(array $criteria, bool $protected = true): array { try { + // add access restriction + if ($protected) { + $criteria[Schema::VINVITATION_USER_CLOUD_ID] = [$this->userSession->getUser()->getCloudId()]; + } return $this->mapper->findAll($criteria); } catch (Exception $e) { $this->logger->error('findAll failed with error: ' . $e->getMessage() . ' Trace: ' . $e->getTraceAsString(), ['app' => Application::APP_ID]); @@ -121,12 +125,12 @@ public function insert(Invitation $invitation): Invitation * Updates the invitation according to the specified fields and values. * * @param array $fieldsAndValues one of which must be the token - * @param bool $loginRequired true if we need session user access check, default is true + * @param bool $protected true if we need session user access check, default is true * @return bool true if update succeeded, otherwise false */ - public function update(array $fieldsAndValues, bool $loginRequired = true): bool + public function update(array $fieldsAndValues, bool $protected = true): bool { - if ($loginRequired === true) { + if ($protected === true) { if ($this->userSession->getUser() == null) { $this->logger->debug('Unable to update invitation, unauthenticated.', ['app' => Application::APP_ID]); return false; diff --git a/lib/Service/MeshRegistry/MeshRegistryService.php b/lib/Service/MeshRegistry/MeshRegistryService.php index a891ad1..178054a 100644 --- a/lib/Service/MeshRegistry/MeshRegistryService.php +++ b/lib/Service/MeshRegistry/MeshRegistryService.php @@ -11,18 +11,19 @@ use OCA\Invitation\AppInfo\Application; use OCA\Invitation\Db\Schema; use OCA\Invitation\Federation\InvitationServiceProvider; +use OCA\Invitation\Federation\InvitationServiceProviderMapper; use OCA\Invitation\Service\ApplicationConfigurationException; use OCA\Invitation\Service\NotFoundException; use OCA\Invitation\Service\ServiceException; use OCP\IConfig; -use OCP\ILogger; +use Psr\Log\LoggerInterface; class MeshRegistryService { private string $appName; private IConfig $config; private InvitationServiceProviderMapper $invitationServiceProviderMapper; - private ILogger $logger; + private LoggerInterface $logger; private const ENDPOINT_FORWARD_INVITE = '/registry/forward-invite'; public const ENDPOINT_GET_INVITE = '/invite'; @@ -48,12 +49,12 @@ class MeshRegistryService public const PARAM_NAME_NAME = 'name'; - public function __construct($appName, IConfig $config, InvitationServiceProviderMapper $invitationServiceProviderMapper) + public function __construct($appName, IConfig $config, InvitationServiceProviderMapper $invitationServiceProviderMapper, LoggerInterface $logger) { $this->appName = $appName; $this->config = $config; $this->invitationServiceProviderMapper = $invitationServiceProviderMapper; - $this->logger = \OC::$server->getLogger(); + $this->logger = $logger; } /** @@ -103,7 +104,7 @@ public function getFullAcceptInviteEndpointURL(): string } /** - * Returns the full 'https://{invitation_service_provider}/invite-accepted' endpoint URL of this EFSS instance. + * Returns the full 'https://{invitation_service_provider}/ocm/invite-accepted' endpoint URL of this EFSS instance. * * @param string $senderHost the host of the sender of the invitation * @return string the full /invite-accepted endpoint URL @@ -111,7 +112,7 @@ public function getFullAcceptInviteEndpointURL(): string public function getFullInviteAcceptedEndpointURL(string $senderInvitationServiceProviderEndpoint = ""): string { if ($senderInvitationServiceProviderEndpoint == "") { - return ['error' => "unable to build full '/invite-accepted' endpoint URL, sender invitation service provider endpoint not specified"]; + return ['error' => "unable to build full '/ocm/invite-accepted' endpoint URL, sender invitation service provider endpoint not specified"]; } $endpoint = trim(trim($senderInvitationServiceProviderEndpoint), '/'); $inviteAcceptedEndpoint = trim(trim(self::ENDPOINT_INVITE_ACCEPTED), "/"); diff --git a/lib/Util.php b/lib/Util.php new file mode 100644 index 0000000..0b516e4 --- /dev/null +++ b/lib/Util.php @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
  + <?php p($theme->getName()); ?> +
 
  + +

-- English version below --

+ t('Hallo ' . $_['recipientName'] . ',')); ?> +
+ U bent uitgenodigd om uw cloud IDs uit te wisselen met . + Als u deze uitnodiging accepteerd zult u onderling efficienter gefedereerd bestanden kunnen delen.
+ +
+ Het volgende persoonlijke bericht is meegestuurd met deze uitnodiging: +

+ +
+ +

+ +
+ Via de onderstaande link kunt u de uitnodiging accepteren of afwijzen. + Als u de uitnodiging accepteerd zullen de cloud IDs van u en , nodig voor het creëren van federated shares, onderling worden uitgewisseld.
+
+ Klik om in te loggen in uw Research Drive instance.
+
+ * Wanneer u de afzender van deze email niet kent of u bent niet bekend met Research Drive verzoeken wij u deze email te verwijderen.
+
+ Voor het verkrijgen van een Research Drive account neemt u contact op met de IT service helpdesk van uw organisatie.
+
+ Op de wikipagina vindt u alle informatie over het gebruik van SURF Research Drive.
+ Voor vragen en opmerkingen kunt u contact opnemen met de Research Drive helpdesk via servicedesk@surf.nl.
+
+ Met vriendelijke groet,
+ SURF Research Drive team
+
+
+ t('Hello ' . $_['recipientName'] . ',')); ?> +
+ You have been invited to exchange cloud IDs with . + If you accept this invitation you will be able to create federated shares with each other more efficiently.
+ +
+ The following personal message was send with the invitation: +

+ +
+ +

+ +
+ Please follow the link below to either accept or decline this invitation. + If you accept this invitation, you and will exchange the federated cloud IDs which are needed to create federated shares.
+
+ Click to log into your Research Drive instance.
+
+ * If you do not know the sender of this email or are not familiar with Research Drive, please delete this email.
+
+ To obtain an account on Research Drive you should contact the IT service helpdesk within your organization.
+
+ On the wiki you will find more information about the usage of SURF Research Drive.
+ For questions or remarks, you can contact your Research Drive helpdesk via servicedesk@surf.nl.
+
+ Kind regards,
+ SURF Research Drive team +
 
  + inc('html.mail.footer', ['app' => 'core'])); ?> +
 
+ + + \ No newline at end of file diff --git a/templates/mail/text.php b/templates/mail/text.php new file mode 100644 index 0000000..6223089 --- /dev/null +++ b/templates/mail/text.php @@ -0,0 +1,60 @@ + +-- English version below -- + +t('Hallo,')); ?> + +U bent uitgenodigd om uw cloud IDs uit te wisselen met . +Als u deze uitnodiging accepteerd zult u onderling efficienter gefedereerd bestanden kunnen delen. + +Het volgende persoonlijke bericht is meegestuurd met deze uitnodiging: + + + + + + +Via de onderstaande link kunt u de uitnodiging accepteren of afwijzen. Als u de uitnodiging accepteerd zullen de cloud IDs van u en , nodig voor het creëren van federated shares, onderling worden uitgewisseld. + + + +* Wanneer u de afzender van deze email niet kent of u bent niet bekend met Research Drive verzoeken wij u deze email te verwijderen. + +Op de wikipagina (https://wiki.surfnet.nl/display/RDRIVE) vindt u alle informatie over het gebruik van SURF Research Drive. +Voor vragen en opmerkingen kunt u contact opnemen met de Research Drive helpdesk via servicedesk@surf.nl + +Met vriendelijke groet, +SURF Research Drive team + +------------------------------------------------------------------------------------------------------------ +t('Hello,')); ?> + +You have been invited to exchange cloud IDs with . +If you accept this invitation you will be able to create federated shares with each other more efficiently. + +The following personal message was send with the invitation: + + + + + + +Please follow the link below to either accept or decline this invitation. If you accept this invitation, you and will exchange the federated cloud IDs which are needed to create federated shares. + + + +* If you do not know the sender of this email or are not familiar with Research Drive, please delete this email. + +On the wiki (https://wiki.surfnet.nl/display/RDRIVE) you will find more information about the usage of SURF Research Drive. +For questions or remarks, you can contact your Research Drive helpdesk via servicedesk@surf.nl + +Kind regards, +SURF Research Drive team + + +inc('plain.mail.footer', ['app' => 'core'])); ?> \ No newline at end of file diff --git a/templates/main.php b/templates/main.php new file mode 100644 index 0000000..7fa5416 --- /dev/null +++ b/templates/main.php @@ -0,0 +1,8 @@ + +// SPDX-License-Identifier: AGPL-3.0-or-later +?> +
Main index page
diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..d125272 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,7 @@ + +// SPDX-License-Identifier: AGPL-3.0-or-later + +require_once __DIR__ . '/../../../tests/bootstrap.php'; diff --git a/tests/docker/.env b/tests/docker/.env index 56dddc1..f901b3a 100644 --- a/tests/docker/.env +++ b/tests/docker/.env @@ -1,3 +1,4 @@ -TEST_UUID_1=c33056f9-2abf-4a1c-98d3-b579b1db8e31 -TEST_UUID_2=5f23338a-b767-41e3-9233-1c1249444663 -ADMIN_PASS=passw \ No newline at end of file +TOKEN_ACCEPTED_INVITATION=c33056f9-2abf-4a1c-98d3-b579b1db8e31 +TOKEN_OPEN_SENT_INVITATION=5f23338a-b767-41e3-9233-1c1249444663 +TOKEN_OPEN_RECEIVED_INVITATION=90107d0b-1847-47c2-ba28-3b74fd591a3e +ADMIN_PASS=admin \ No newline at end of file diff --git a/tests/docker/docker-cleanup.sh b/tests/docker/docker-cleanup.sh new file mode 100644 index 0000000..8d47569 --- /dev/null +++ b/tests/docker/docker-cleanup.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +docker compose -f docker-compose-local.yaml stop +docker system prune -f +docker volume rm -f docker_files-nc-1 +docker volume rm -f docker_mysql-nc-1 diff --git a/tests/docker/docker-compose-github.yaml b/tests/docker/docker-compose-github.yaml index f4ffe9a..92e78f9 100644 --- a/tests/docker/docker-compose-github.yaml +++ b/tests/docker/docker-compose-github.yaml @@ -9,8 +9,9 @@ services: depends_on: - nginx-proxy environment: - - TEST_UUID_1=${TEST_UUID_1} - - TEST_UUID_2=${TEST_UUID_2} + - TOKEN_ACCEPTED_INVITATION=${TOKEN_ACCEPTED_INVITATION} + - TOKEN_OPEN_SENT_INVITATION=${TOKEN_OPEN_SENT_INVITATION} + - TOKEN_OPEN_RECEIVED_INVITATION=${TOKEN_OPEN_RECEIVED_INVITATION} - ADMIN_PASS=${ADMIN_PASS} extra_hosts: - 'nc-1.nl:10.1.0.160' # this will add this mapping to /etc/hosts @@ -30,8 +31,9 @@ services: depends_on: - mariadb-nc-1 environment: - - TEST_UUID_1=${TEST_UUID_1} - - TEST_UUID_2=${TEST_UUID_2} + - TOKEN_ACCEPTED_INVITATION=${TOKEN_ACCEPTED_INVITATION} + - TOKEN_OPEN_SENT_INVITATION=${TOKEN_OPEN_SENT_INVITATION} + - TOKEN_OPEN_RECEIVED_INVITATION=${TOKEN_OPEN_RECEIVED_INVITATION} - ADMIN_PASS=${ADMIN_PASS} extra_hosts: - 'nc-1.nl:10.1.0.160' # this will add this mapping to /etc/hosts diff --git a/tests/docker/docker-compose-local.yaml b/tests/docker/docker-compose-local.yaml index 242bf30..17b9938 100644 --- a/tests/docker/docker-compose-local.yaml +++ b/tests/docker/docker-compose-local.yaml @@ -9,8 +9,9 @@ services: depends_on: - nginx-proxy environment: - - TEST_UUID_1=${TEST_UUID_1} - - TEST_UUID_2=${TEST_UUID_2} + - TOKEN_ACCEPTED_INVITATION=${TOKEN_ACCEPTED_INVITATION} + - TOKEN_OPEN_SENT_INVITATION=${TOKEN_OPEN_SENT_INVITATION} + - TOKEN_OPEN_RECEIVED_INVITATION=${TOKEN_OPEN_RECEIVED_INVITATION} - ADMIN_PASS=${ADMIN_PASS} extra_hosts: - 'nc-1.nl:10.1.0.160' # this will add this mapping to /etc/hosts @@ -28,8 +29,9 @@ services: depends_on: - mariadb-nc-1 environment: - - TEST_UUID_1=${TEST_UUID_1} - - TEST_UUID_2=${TEST_UUID_2} + - TOKEN_ACCEPTED_INVITATION=${TOKEN_ACCEPTED_INVITATION} + - TOKEN_OPEN_SENT_INVITATION=${TOKEN_OPEN_SENT_INVITATION} + - TOKEN_OPEN_RECEIVED_INVITATION=${TOKEN_OPEN_RECEIVED_INVITATION} - ADMIN_PASS=${ADMIN_PASS} extra_hosts: - 'nc-1.nl:10.1.0.160' # this will add this mapping to /etc/hosts diff --git a/tests/docker/integration-tests/OcsController.php b/tests/docker/integration-tests/OcsController.php index ae7d9b8..270a656 100644 --- a/tests/docker/integration-tests/OcsController.php +++ b/tests/docker/integration-tests/OcsController.php @@ -1,34 +1,83 @@ invitationController = $invitationController; - $this->logger = $logger; + $this->meshRegistryController = $meshRegistryController; + } + + /** + * Delegates to InvitationController + * + * @NoAdminRequired + * @NoCSRFRequired + * @param string $token + * @return DataResponse + */ + public function invitationGetByToken(string $token = null): DataResponse + { + return $this->invitationController->getByToken($token); } /** + * Delegates to InvitationController + * * @NoAdminRequired * @NoCSRFRequired + * @param string $token + * @return DataResponse + */ + public function invitationUpdate(string $token = null, string $status): DataResponse + { + return $this->invitationController->update($token, $status); + } + + /** + * Delegates to InvitationController + * + * @NoAdminRequired + * @NoCSRFRequired + * @param string $status + * @return DataResponse + */ + public function invitationFind(string $status = "", string $remoteUserEmail = ""): DataResponse + { + return $this->invitationController->find($status, $remoteUserEmail); + } + + public function invitationGenerateInvite(string $email = "", string $recipientName = "", string $senderName = "", string $message = ""): DataResponse + { + return $this->invitationController->generateInvite($email, $recipientName, $senderName, $message); + } + + /** + * Set the name associated with this invitation service provider instance. + * + * @param string $name + * @return DataResponse + * @throws ServiceException */ - public function findByToken(string $token = null): DataResponse + public function registrySetName(string $name): DataResponse { - return $this->invitationController->findByToken($token); + return $this->meshRegistryController->setName($name); } } diff --git a/tests/docker/integration-tests/Version20240209130007.php b/tests/docker/integration-tests/Version20240209130007.php index cafb175..eb54c18 100644 --- a/tests/docker/integration-tests/Version20240209130007.php +++ b/tests/docker/integration-tests/Version20240209130007.php @@ -4,6 +4,7 @@ use OC\Accounts\AccountManager; use OCA\Invitation\Db\Schema; +use OCA\Invitation\Federation\Invitation; use OCP\Accounts\IAccountManager; use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\DB\ISchemaWrapper; @@ -49,8 +50,6 @@ public function __construct( */ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { - $prefix = $options['tablePrefix']; - /** * @var ISchemaWrapper $schema */ @@ -88,10 +87,10 @@ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $op ]); $qb->executeStatement(); - // add some invitations + // create an accepted invitation on nc-1 $qb->insert(Schema::TABLE_INVITATIONS)->values([ Schema::INVITATION_USER_CLOUD_ID => $qb->createNamedParameter('admin@nc-1.nl'), - Schema::INVITATION_TOKEN => $qb->createNamedParameter(getenv('TEST_UUID_1')), + Schema::INVITATION_TOKEN => $qb->createNamedParameter(getenv('TOKEN_ACCEPTED_INVITATION')), Schema::INVITATION_PROVIDER_ENDPOINT => $qb->createNamedParameter('https://nc-1.nl/apps/invitation'), Schema::INVITATION_RECIPIENT_ENDPOINT => $qb->createNamedParameter('https://nc-2.nl/apps/invitation'), Schema::INVITATION_SENDER_CLOUD_ID => $qb->createNamedParameter('admin@nc-1.nl'), @@ -100,23 +99,35 @@ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $op Schema::INVITATION_RECIPIENT_CLOUD_ID => $qb->createNamedParameter('lex@nc-2.nl'), Schema::INVITATION_RECIPIENT_EMAIL => $qb->createNamedParameter('lex@mail.nc-2-academy.nl'), Schema::INVITATION_RECIPIENT_NAME => $qb->createNamedParameter('Lex Lexington'), - Schema::INVITATION_TIMESTAMP => $qb->createNamedParameter(1713528254, IQueryBuilder::PARAM_INT), - Schema::INVITATION_STATUS => $qb->createNamedParameter('withdrawn'), + Schema::INVITATION_TIMESTAMP => $qb->createNamedParameter(time(), IQueryBuilder::PARAM_INT), + Schema::INVITATION_STATUS => $qb->createNamedParameter(Invitation::STATUS_ACCEPTED), + ]); + $qb->executeStatement(); + // create an open (sent) invitation on nc-1 + $qb->insert(Schema::TABLE_INVITATIONS)->values([ + Schema::INVITATION_USER_CLOUD_ID => $qb->createNamedParameter('admin@nc-1.nl'), + Schema::INVITATION_TOKEN => $qb->createNamedParameter(getenv('TOKEN_OPEN_SENT_INVITATION')), + Schema::INVITATION_PROVIDER_ENDPOINT => $qb->createNamedParameter('https://nc-1.nl/apps/invitation'), + Schema::INVITATION_SENDER_CLOUD_ID => $qb->createNamedParameter('admin@nc-1.nl'), + Schema::INVITATION_SENDER_EMAIL => $qb->createNamedParameter('admin@mail.nc-1-university.nl'), + Schema::INVITATION_SENDER_NAME => $qb->createNamedParameter('A. Dmin'), + Schema::INVITATION_RECIPIENT_EMAIL => $qb->createNamedParameter('ronnie@nc-2.nl'), + Schema::INVITATION_TIMESTAMP => $qb->createNamedParameter(time(), IQueryBuilder::PARAM_INT), + Schema::INVITATION_STATUS => $qb->createNamedParameter(Invitation::STATUS_OPEN), ]); $qb->executeStatement(); + // create an open (received) invitation on nc-1 $qb->insert(Schema::TABLE_INVITATIONS)->values([ Schema::INVITATION_USER_CLOUD_ID => $qb->createNamedParameter('admin@nc-1.nl'), - Schema::INVITATION_TOKEN => $qb->createNamedParameter(getenv('TEST_UUID_2')), + Schema::INVITATION_TOKEN => $qb->createNamedParameter(getenv('TOKEN_OPEN_RECEIVED_INVITATION')), Schema::INVITATION_PROVIDER_ENDPOINT => $qb->createNamedParameter('https://nc-2.nl/apps/invitation'), - Schema::INVITATION_RECIPIENT_ENDPOINT => $qb->createNamedParameter('https://nc-1.nl/apps/invitation'), - Schema::INVITATION_SENDER_CLOUD_ID => $qb->createNamedParameter('admin@nc-2.nl'), - Schema::INVITATION_SENDER_EMAIL => $qb->createNamedParameter('admin@mail.nc-2-university.nl'), Schema::INVITATION_SENDER_NAME => $qb->createNamedParameter('A. Dmin'), Schema::INVITATION_RECIPIENT_CLOUD_ID => $qb->createNamedParameter('admin@nc-1.nl'), - Schema::INVITATION_RECIPIENT_EMAIL => $qb->createNamedParameter('admin@nc-1.nl'), - Schema::INVITATION_RECIPIENT_NAME => $qb->createNamedParameter('Admin'), - Schema::INVITATION_TIMESTAMP => $qb->createNamedParameter(1713528678, IQueryBuilder::PARAM_INT), - Schema::INVITATION_STATUS => $qb->createNamedParameter('accepted'), + Schema::INVITATION_RECIPIENT_ENDPOINT => $qb->createNamedParameter('https://nc-1.nl/apps/invitation'), + Schema::INVITATION_RECIPIENT_NAME => $qb->createNamedParameter('Jimmie Bo Horn'), + Schema::INVITATION_RECIPIENT_EMAIL => $qb->createNamedParameter('jimmie@nc-1.nl'), + Schema::INVITATION_TIMESTAMP => $qb->createNamedParameter(time(), IQueryBuilder::PARAM_INT), + Schema::INVITATION_STATUS => $qb->createNamedParameter(Invitation::STATUS_OPEN), ]); $qb->executeStatement(); return $schema; diff --git a/tests/docker/integration-tests/build/artifacts/app/invitation_{version_number}.tar.gz b/tests/docker/integration-tests/build/artifacts/app/invitation_{version_number}.tar.gz new file mode 100644 index 0000000..3af2ce8 Binary files /dev/null and b/tests/docker/integration-tests/build/artifacts/app/invitation_{version_number}.tar.gz differ diff --git a/tests/docker/integration-tests/routes.php b/tests/docker/integration-tests/routes.php new file mode 100644 index 0000000..7b35f1c --- /dev/null +++ b/tests/docker/integration-tests/routes.php @@ -0,0 +1,27 @@ + +// SPDX-License-Identifier: AGPL-3.0-or-later + +/** + * Adds the routes required for testing to the app routes. + * + */ + +declare(strict_types=1); + +$appRoutes = include 'app-routes.php'; + +$ocsRoutes = [ + 'ocs' => [ + ['root' => '/invitation', 'name' => 'ocs#invitation_get_by_token', 'url' => '/invitations/{token}', 'verb' => 'GET'], + ['root' => '/invitation', 'name' => 'ocs#invitation_update', 'url' => '/invitations/{token}', 'verb' => 'PUT'], + ['root' => '/invitation', 'name' => 'ocs#invitation_find', 'url' => '/invitations', 'verb' => 'GET'], + ['root' => '/invitation', 'name' => 'ocs#invitation_generate_invite', 'url' => '/invitations', 'verb' => 'POST'], + + ['root' => '/invitation', 'name' => 'ocs#registry_set_name', 'url' => '/registry/name', 'verb' => 'PUT'], + + ], +]; + +return array_merge($appRoutes, $ocsRoutes); diff --git a/tests/docker/integration-tests/src/tests/integration/InvitationServiceProviderTest.php b/tests/docker/integration-tests/src/tests/integration/InvitationServiceProviderTest.php new file mode 100644 index 0000000..f497494 --- /dev/null +++ b/tests/docker/integration-tests/src/tests/integration/InvitationServiceProviderTest.php @@ -0,0 +1,83 @@ +authToken == "") { + $this->authToken = Util::getAuthToken(self::NC_1_HOST, 'admin', getenv('ADMIN_PASS')); + } + } + + public function testInvitationServiceProviderProperties() + { + try { + $endpoint = "/registry/invitation-service-provider"; + print_r("\ntesting unprotected endpoint GET $endpoint\n"); + $url = self::NC_1_APP_ROOT . $endpoint; + $httpClient = new HttpClient(); + $response = $httpClient->curlGet($url); + print_r("\n" . print_r($response, true) . "\n"); + + $this->assertEquals('nc-1.nl', $response['data']['domain'], "Domain is not what is expected."); + } catch (Exception $e) { + $this->fail($e->getTraceAsString()); + } + } + + public function testGetInvitationServiceProviderName() + { + try { + $invitationServiceProviderName = "NC 1 University"; + $endpoint = "/registry/name"; + print_r("\ntesting unprotected endpoint GET $endpoint\n"); + $url = self::NC_1_APP_ROOT . $endpoint; + $httpClient = new HttpClient(); + $response = $httpClient->curlGet($url); + print_r("\n" . print_r($response, true) . "\n"); + + $this->assertEquals($invitationServiceProviderName, $response['data'], "GET $url failed"); + + } catch (Exception $e) { + $this->fail($e->getTraceAsString()); + } + } + + public function testSetInvitationServiceProviderName() + { + try { + $invitationServiceProviderName = "NC 1 New Name"; + $endpoint = "/registry/name"; + print_r("\ntesting protected endpoint PUT $endpoint\n"); + $url = self::NC_1_OCS_ROOT . $endpoint; + $httpClient = new HttpClient(); + $basicAuthToken = base64_encode("admin:{$this->authToken}"); + $response = $httpClient->curlPut($url, ["name" => $invitationServiceProviderName], $basicAuthToken, "", ["OCS-APIRequest: true"]); + print_r("\n" . print_r($response, true) . "\n"); + + $this->assertEquals($invitationServiceProviderName, $response['data'], "GET $url failed"); + + } catch (Exception $e) { + $this->fail($e->getTraceAsString()); + } + } + + public function tearDown(): void + { + parent::tearDown(); + } +} diff --git a/tests/docker/integration-tests/src/tests/integration/InvitationServiceProviderTest.xxx b/tests/docker/integration-tests/src/tests/integration/InvitationServiceProviderTest.xxx deleted file mode 100644 index 56705c9..0000000 --- a/tests/docker/integration-tests/src/tests/integration/InvitationServiceProviderTest.xxx +++ /dev/null @@ -1,77 +0,0 @@ -curlGet($endpoint, true); - - $this->assertTrue(Util::isTrue($response['success']), "GET $endpoint failed"); - $this->assertEquals('oc-1.nl', $response['data']['domain'], "Domain is not what is expected."); - print_r("\nproperties: " . print_r($response, true) . "\n"); - - $endpoint = self::OC_2_UNPROTECTED_ENDPOINT . "/registry/invitation-service-provider"; - print_r("\ntesting unprotected endpoint $endpoint\n"); - $httpClient = new HttpClient(); - $response = $httpClient->curlGet($endpoint, true); - - $this->assertTrue(Util::isTrue($response['success']), "GET $endpoint failed"); - $this->assertEquals('oc-2.nl', $response['data']['domain'], "Domain is not what is expected."); - print_r("\nproperties: " . print_r($response, true) . "\n"); - } catch (Exception $e) { - $this->fail($e->getMessage()); - } - } - - public function testInvitationServiceProviderName() - { - // defined by the test data from Version20231130125301.php - try { - $invitationServiceProviderName = "OC 1 University"; - $endpoint = self::OC_1_UNPROTECTED_ENDPOINT . "/registry/name"; - print_r("\ntesting unprotected endpoint $endpoint\n"); - $httpClient = new HttpClient(); - $response = $httpClient->curlGet($endpoint, true); - - print_r("\n" . print_r($response, true)); - $this->assertTrue(Util::isTrue($response['success']), "GET $endpoint failed"); - $this->assertEquals($invitationServiceProviderName, $response['data'], "GET $endpoint failed"); - - $invitationServiceProviderName = "OC 2 University"; - $endpoint = self::OC_2_UNPROTECTED_ENDPOINT . "/registry/name"; - print_r("\ntesting unprotected endpoint $endpoint\n"); - $httpClient = new HttpClient(); - $response = $httpClient->curlGet($endpoint, true); - print_r("\n" . print_r($response, true)); - $this->assertTrue(Util::isTrue($response['success']), "GET $endpoint failed"); - $this->assertEquals($invitationServiceProviderName, $response['data'], "GET $endpoint failed"); - } catch (Exception $e) { - $this->fail($e->getMessage()); - } - } - - public function tearDown(): void - { - parent::tearDown(); - } -} diff --git a/tests/docker/integration-tests/src/tests/integration/InvitationTest.php b/tests/docker/integration-tests/src/tests/integration/InvitationTest.php index db8d06f..1624147 100644 --- a/tests/docker/integration-tests/src/tests/integration/InvitationTest.php +++ b/tests/docker/integration-tests/src/tests/integration/InvitationTest.php @@ -10,45 +10,49 @@ use tests\util\HttpClient; use tests\util\Util; +use function PHPUnit\Framework\assertEquals; + class InvitationTest extends TestCase { - private const NC_1_HOST = "http://nc-1.nl"; - private const NC_1_OCS_ROOT = "http://nc-1.nl/ocs/v2.php/invitation"; - // private const NC_1_ENDPOINT = "http://nc-1.nl/apps/invitation"; + private const NC_1_HOST = "https://nc-1.nl"; + private const NC_1_OCS_ROOT = "https://nc-1.nl/ocs/v2.php/invitation"; + private const NC_1_APP_ROOT = "https://nc-1.nl/apps/invitation"; + private const NC_2_INVITATION_SERVICE_PROVIDER_ENDPOINT = "https://nc-2.nl/apps/invitation"; + private const PARAM_NAME_EMAIL = "email"; + private const PARAM_NAME_RECIPIENT_NAME = "recipientName"; + private const PARAM_NAME_SENDER_NAME = "senderName"; + private const PARAM_NAME_MESSAGE = "message"; private string $authToken = ""; + private $tokenAcceptedInvitation = ""; + private $tokenOpenSentInvitation = ""; + private $tokenOpenReceivedInvitation = ""; + + public function setUp(): void { print_r("\nsetUp test\n"); parent::setUp(); - $this->authToken = $this->getAuthToken('admin', getenv('ADMIN_PASS')); - } - - private function getAuthToken(string $user, string $pass): string - { - - // curl -u admin:passw -H 'OCS-APIRequest: true' http://nc-1.nl/ocs/v2.php/core/getapppassword - $url = self::NC_1_HOST . "/ocs/v2.php/core/getapppassword"; - $httpClient = new HttpClient(); - // OCS spec: token should be base64 encoded [user]:[passwd] string - $basicAuthToken = base64_encode("{$user}:{$pass}"); - $headers = ["OCS-APIRequest: true"]; - $response = $httpClient->curlGet($url, $basicAuthToken, "", $headers); - print_r("\nReceived app authentication token: " . print_r($response, true) . "\n"); - return $response['apppassword']; - + if ($this->authToken == "") { + $this->authToken = Util::getAuthToken(self::NC_1_HOST, 'admin', getenv('ADMIN_PASS')); + } + $this->tokenAcceptedInvitation = getenv("TOKEN_ACCEPTED_INVITATION"); + $this->tokenOpenSentInvitation = getenv("TOKEN_OPEN_SENT_INVITATION"); + $this->tokenOpenReceivedInvitation = getenv("TOKEN_OPEN_RECEIVED_INVITATION"); } - public function testRouteFindInvitations() + public function testFindInvitations() { try { - $endpoint = self::NC_1_HOST . "/apps/invitation/invitations?status=accepted|withdrawn"; - print_r("\nTesting unprotected endpoint: {$endpoint}"); + $endpoint = "/invitations?status=accepted|open|withdrawn"; + print_r("\nTesting protected endpoint: {$endpoint}"); + $url = self::NC_1_OCS_ROOT . $endpoint; $httpClient = new HttpClient(); - $response = $httpClient->curlGet($endpoint); - print_r($response); - $this->assertTrue(Util::isTrue($response['success']), "GET {$endpoint} failed"); - print_r("\nFound invitations: " . print_r($response['data'], true) . "\n"); + $basicAuthToken = base64_encode("admin:{$this->authToken}"); + $response = $httpClient->curlGet($url, $basicAuthToken, "", ["OCS-APIRequest: true"]); + print_r("\n" . print_r($response, true) . "\n"); + + $this->assertEquals(3, count($response['data'][array_key_first($response['data'])]), "GET {$url} failed"); return $response['data']; } catch (Exception $e) { $this->fail($e->getTraceAsString()); @@ -56,30 +60,164 @@ public function testRouteFindInvitations() } /** - * Test - * - route GET /invitations/{token} - * - method InvitationController findByToken(token) + * Tests getting an invitation. * * @return string token */ - public function testRouteGetInvitations(): string + public function testGetInvitation(): string { try { - $testToken = getenv("TEST_UUID_1"); - $endpoint = "/invitations/{$testToken}"; + $token = $this->tokenOpenSentInvitation; + $endpoint = "/invitations/{$token}"; $url = self::NC_1_OCS_ROOT . "{$endpoint}"; print_r("\nTesting protected endpoint: {$endpoint}\n"); $httpClient = new HttpClient(); $basicAuthToken = base64_encode("admin:{$this->authToken}"); $response = $httpClient->curlGet($url, $basicAuthToken, "", ["OCS-APIRequest: true"]); - $this->assertTrue(Util::isTrue($response['success']), "GET {$url} failed"); - $this->assertEquals($testToken, $response['data']['token'], "GET {$endpoint} failed\n"); + print_r("\n" . print_r($response['data'], true) . "\n"); + + $this->assertEquals($token, $response['data']['token'], "GET {$url} failed\n"); return $response['data']['token']; } catch (Exception $e) { $this->fail($e->getTraceAsString()); } } + public function testGenerateInvite() + { + try { + $endpoint = "/invitations"; + print_r("\ntesting protected endpoint POST $endpoint\n"); + $url = self::NC_1_OCS_ROOT . $endpoint; + $httpClient = new HttpClient(); + + // test no email specified + print_r("\ntest POST $endpoint > no email specified\n"); + $basicAuthToken = base64_encode("admin:{$this->authToken}"); + $response = $httpClient->curlPost( + $url, + [ + self::PARAM_NAME_EMAIL => "", + self::PARAM_NAME_RECIPIENT_NAME => "You", + self::PARAM_NAME_SENDER_NAME => "Me" + + ], + $basicAuthToken, + "", + ["OCS-APIRequest: true"] + ); + print_r("\n" . print_r($response, true)); + + $this->assertEquals(AppError::CREATE_INVITATION_NO_RECIPIENT_EMAIL, $response['message'], 'No email address check failed.'); + + // test email invalid + print_r("\ntest POST $endpoint > email invalid\n"); + $response = $httpClient->curlPost( + $url, + [ + self::PARAM_NAME_EMAIL => "invalid-email-address", + self::PARAM_NAME_RECIPIENT_NAME => "You", + self::PARAM_NAME_SENDER_NAME => "Me" + ], + $basicAuthToken, + "", + ["OCS-APIRequest: true"] + ); + print_r("\n" . print_r($response, true)); + + $this->assertEquals(AppError::CREATE_INVITATION_EMAIL_INVALID, $response['message'], 'Invalid email address response failure.'); + + print_r("\ntest POST $endpoint\n"); + $message = urlencode('I want to invite you.'); + $response = $httpClient->curlPost( + $url, + [ + self::PARAM_NAME_EMAIL => "me@oc-1.nl", + self::PARAM_NAME_RECIPIENT_NAME => "You", + self::PARAM_NAME_SENDER_NAME => "Me", + self::PARAM_NAME_MESSAGE => $message + ], + $basicAuthToken, + "", + ["OCS-APIRequest: true"] + ); + print_r("\n" . print_r($response, true)); + $this->assertTrue(Uuid::isValid($response['data']['token']), 'POST $endpoint failed, invalid token returned.'); + return $response['data']['token']; + } catch (Exception $e) { + $this->fail($e->getMessage()); + } + } + + /** + * Tests route PUT /invitations/{token} + * Updates the status of sent invitation to revoked + * + * @return string $status the status that the invitation has been updated to + */ + public function testRevokeInvitation() + { + $token = $this->tokenAcceptedInvitation; + $endpoint = "/invitations/$token"; + print_r("\ntesting protected endpoint PUT $endpoint\n"); + $url = self::NC_1_OCS_ROOT . "$endpoint"; + $httpClient = new HttpClient(); + + $basicAuthToken = base64_encode("admin:{$this->authToken}"); + + $newStatus = "revoked"; + $response = $httpClient->curlPut( + $url, + ["status" => $newStatus], + $basicAuthToken, + "", + ["OCS-APIRequest: true"] + ); + print_r("\n" . print_r($response, true) . "\n"); + + $this->assertEquals($token, $response['data']['token'], "Updating the invitation status failed."); + $this->assertEquals($newStatus, $response['data']['status'], "Updating the invitation status failed."); + return $newStatus; + } + + /** + * Tests route PUT /invitations/{token} + * Accepts the invitation + * + * @return string $status the status that the invitation has been updated to + */ + public function xxxAcceptInvitation() + { + // Needs the instance from which the invitation came to respond to the /ocm/invite-accepted call. + // We therefor currently test POST /ocm/invite-accepted endpoint separately in testOcmInviteAccepted(). + } + + /** + * Test ocm POST /ocm/invite-accepted endpoint + * User at nc-2 accepts invitation from user at nc-1 + */ + public function testOcmInviteAccepted() + { + $endpoint = "/ocm/invite-accepted"; + print_r("\ntesting protected endpoint POST $endpoint\n"); + $url = self::NC_1_APP_ROOT . $endpoint; + $httpClient = new HttpClient(); + + print_r("\ntest unprotected POST $endpoint\n"); + $response = $httpClient->curlPost( + $url, + [ + "recipientProvider" => self::NC_2_INVITATION_SERVICE_PROVIDER_ENDPOINT, + "token" => $this->tokenOpenSentInvitation, // sent by nc-1 + "userID" => "me@nc-2.nl@mesh.org", + "email" => "me@nc-2.nl", + "name" => "M.E", + ] + ); + print_r("\n" . print_r($response, true)); + assertEquals(1, 1, "Strange"); + } + public function tearDown(): void { print_r("\ntearDown test\n"); diff --git a/tests/docker/integration-tests/src/tests/util/HttpClient.php b/tests/docker/integration-tests/src/tests/util/HttpClient.php index 5f57dc7..88017c5 100644 --- a/tests/docker/integration-tests/src/tests/util/HttpClient.php +++ b/tests/docker/integration-tests/src/tests/util/HttpClient.php @@ -5,8 +5,6 @@ use Exception; use SimpleXMLElement; -use function PHPUnit\Framework\isEmpty; - class HttpClient { public function __construct() @@ -21,16 +19,19 @@ public function __construct() * @param string $userName the user name to create a session user from * @return mixed returns an array in the standardized format: * [ - * 'success' => true | false, - * - * 'data' => if success is true + * 'data' => if successfull * or - * 'error_message' => if success is false + * 'message' => in case of error * ] * @throws HttpException */ - public function curlPost(string $url, array $params = [], bool $unprotected = false) - { + public function curlPost( + string $url, + array $params = [], + string $basicAuthToken = "", + string $simpleUserPass = "", + array $headers = [], + ) { try { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); @@ -38,22 +39,103 @@ public function curlPost(string $url, array $params = [], bool $unprotected = fa curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); - curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params)); + // ocm and non-ocm calls apparently need different encodings of the POST fields + if ($basicAuthToken == "" && $simpleUserPass == "") { + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params)); + } else { + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); + } + $httpHeaders = []; + if ($basicAuthToken != "") { + array_push($httpHeaders, "Authorization: Basic {$basicAuthToken}"); + } + if ($simpleUserPass != "") { + curl_setopt($ch, CURLOPT_USERPWD, $simpleUserPass); + } + if (!empty($headers)) { + foreach ($headers as $header) { + array_push($httpHeaders, $header); + } + } + if (!empty($httpHeaders)) { + curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders); + } $output = curl_exec($ch); $info = curl_getinfo($ch); curl_close($ch); if (!isset($output) || $output == false) { throw new Exception('curl_exec error > curl_getinfo: ' . print_r($info, true)); } - if ($unprotected) { + // assume unprotected route if no credentials are provided + if ($basicAuthToken == "" && $simpleUserPass == "") { return json_decode($output, true); } $ocs = new SimpleXMLElement($output); - if ($ocs->meta->status == 'ok') { - return Util::simplexmlToArray($ocs->data); - } else { - throw new Exception($ocs->meta->statuscode . '. ' . $ocs->meta->message); + return Util::simplexmlToArray($ocs->data); + } catch (Exception $e) { + print_r($output); + print_r($info); + throw new Exception($e->getTraceAsString()); + } + } + + /** + * Executes a PUT request. + * + * @param string $url + * @param array $params post fields + * @param string $userName the user name to create a session user from + * @return mixed returns an array in the standardized format: + * [ + * 'data' => if successfull + * or + * 'message' => in case of error + * ] + * @throws HttpException + */ + public function curlPut( + string $url, + array $params = [], + string $basicAuthToken = "", + string $simpleUserPass = "", + array $headers = [], + ) { + try { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]); + // curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params)); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); + $httpHeaders = []; + if ($basicAuthToken != "") { + array_push($httpHeaders, "Authorization: Basic {$basicAuthToken}"); } + if ($simpleUserPass != "") { + curl_setopt($ch, CURLOPT_USERPWD, $simpleUserPass); + } + if (!empty($headers)) { + foreach ($headers as $header) { + array_push($httpHeaders, $header); + } + } + if (!empty($httpHeaders)) { + curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders); + } + $output = curl_exec($ch); + $info = curl_getinfo($ch); + curl_close($ch); + if (!isset($output) || $output == false) { + throw new Exception('curl_exec error > curl_getinfo: ' . print_r($info, true)); + } + // assume unprotected route if no credentials are provided + if ($basicAuthToken == "" && $simpleUserPass == "") { + return json_decode($output, true); + } + $ocs = new SimpleXMLElement($output); + return Util::simplexmlToArray($ocs->data); } catch (Exception $e) { throw new Exception($e->getTraceAsString()); } @@ -66,11 +148,9 @@ public function curlPost(string $url, array $params = [], bool $unprotected = fa * @param string $userName the user name to create a session user from * @return mixed returns an array in the standardized format: * [ - * 'success' => true | false, - * - * 'data' => if success is true + * 'data' => if successfull * or - * 'error_message' => if success is false + * 'message' => in case of error * ] * @throws HttpException */ @@ -112,7 +192,7 @@ public function curlGet( print_r("\ncurl_getinfo: " . print_r($info, true)); throw new Exception('curl_exec output error, curl_getinfo: ' . print_r($info, true)); } - // unprotected route + // assume unprotected route if no credentials are provided if ($basicAuthToken == "" && $simpleUserPass == "") { return json_decode($output, true); } diff --git a/tests/docker/integration-tests/src/tests/util/Util.php b/tests/docker/integration-tests/src/tests/util/Util.php index 28970ac..91f6b64 100644 --- a/tests/docker/integration-tests/src/tests/util/Util.php +++ b/tests/docker/integration-tests/src/tests/util/Util.php @@ -42,4 +42,15 @@ public static function simplexmlToArray($xml) } return $ar; } + + public static function getAuthToken(string $host, string $user, string $pass): string + { + $url = "{$host}/ocs/v2.php/core/getapppassword"; + $httpClient = new HttpClient(); + // OCS spec: token should be base64 encoded [user]:[passwd] string + $basicAuthToken = base64_encode("{$user}:{$pass}"); + $headers = ["OCS-APIRequest: true"]; + $response = $httpClient->curlGet($url, $basicAuthToken, "", $headers); + return $response['apppassword']; + } } diff --git a/tests/docker/integration-tests/src/tests/util/fail-formatted.txt b/tests/docker/integration-tests/src/tests/util/fail-formatted.txt deleted file mode 100644 index 3734067..0000000 --- a/tests/docker/integration-tests/src/tests/util/fail-formatted.txt +++ /dev/null @@ -1,701 +0,0 @@ -"OC\\AppFramework\\Http\\Request Object -( - [inputStream:protected] => php://input - [content:protected] => - [items:protected] => Array - ( - [params] => Array - ( - ) - - [get] => Array - ( - ) - - [post] => Array - ( - ) - - [files] => Array - ( - ) - - [server] => Array - ( - [HTTP_AUTHORIZATION] => Basic YWRtaW46cGFzc3c= - [modHeadersAvailable] => true - [htaccessWorking] => true - [front_controller_active] => true - [HTTP_HOST] => nc-1 - [HTTP_X_FORWARDED_FOR] => 10.1.0.190 - [HTTP_X_FORWARDED_PROTO] => https - [HTTP_X_FORWARDED_HOST] => nc-1.nl - [HTTP_CONNECTION] => close - [HTTP_ACCEPT] => */* - [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - [SERVER_SIGNATURE] =>
Apache/2.4.59 (Debian) Server at nc-1 Port 80
- - [SERVER_SOFTWARE] => Apache/2.4.59 (Debian) - [SERVER_NAME] => nc-1 - [SERVER_ADDR] => 10.1.0.100 - [SERVER_PORT] => 80 - [REMOTE_ADDR] => 10.1.0.190 - [DOCUMENT_ROOT] => /var/www/html - [REQUEST_SCHEME] => http - [CONTEXT_PREFIX] => - [CONTEXT_DOCUMENT_ROOT] => /var/www/html - [SERVER_ADMIN] => webmaster@localhost - [SCRIPT_FILENAME] => /var/www/html/ocs/v2.php - [REMOTE_PORT] => 41302 - [GATEWAY_INTERFACE] => CGI/1.1 - [SERVER_PROTOCOL] => HTTP/1.0 - [REQUEST_METHOD] => GET - [QUERY_STRING] => - [REQUEST_URI] => /ocs/v2.php/core/getapppassword - [SCRIPT_NAME] => /ocs/v2.php - [PATH_INFO] => /core/getapppassword - [PATH_TRANSLATED] => redirect:/index.php - [PHP_SELF] => /ocs/v2.php/core/getapppassword - [PHP_AUTH_USER] => admin - [PHP_AUTH_PW] => passw - [REQUEST_TIME_FLOAT] => 1718637416.7316 - [REQUEST_TIME] => 1718637416 - [argv] => Array - ( - ) - - [argc] => 0 - ) - - [env] => Array - ( - [HOSTNAME] => da5fe9de4559 - [PHP_VERSION] => 8.2.20 - [APACHE_CONFDIR] => /etc/apache2 - [NEXTCLOUD_VERSION] => 29.0.1 - [PHP_INI_DIR] => /usr/local/etc/php - [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC - [PHP_LDFLAGS] => -Wl,-O1 -pie - [ADMIN_PASS] => passw - [PWD] => /var/www/html - [APACHE_LOG_DIR] => /var/log/apache2 - [PHP_MEMORY_LIMIT] => 512M - [LANG] => C - [APACHE_BODY_LIMIT] => 1073741824 - [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50 - [APACHE_PID_FILE] => /var/run/apache2/apache2.pid - [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c - [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31 - [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663 - [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz - [APACHE_RUN_GROUP] => www-data - [PHP_UPLOAD_LIMIT] => 512M - [APACHE_LOCK_DIR] => /var/lock/apache2 - [SHLVL] => 0 - [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - [APACHE_RUN_DIR] => /var/run/apache2 - [APACHE_ENVVARS] => /etc/apache2/envvars - [APACHE_RUN_USER] => www-data - [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - [DEBUG] => true - [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc - [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - ) - - [cookies] => Array - ( - ) - - [urlParams] => Array - ( - ) - - [parameters] => Array - ( - ) - - [method] => GET - [requesttoken] => Array - ( - ) - - ) - - [allowedKeys:protected] => Array - ( - [0] => get - [1] => post - [2] => files - [3] => server - [4] => env - [5] => cookies - [6] => urlParams - [7] => parameters - [8] => method - [9] => requesttoken - ) - - [requestId:protected] => OC\\AppFramework\\Http\\RequestId Object - ( - [secureRandom:protected] => OC\\Security\\SecureRandom Object - ( - ) - - [requestId:protected] => - ) - - [config:protected] => OC\\AllConfig Object - ( - [connection:OC\\AllConfig:private] => - [userCache:OC\\AllConfig:private] => OCP\\Cache\\CappedMemoryCache Object - ( - [capacity:OCP\\Cache\\CappedMemoryCache:private] => 512 - [cache:OCP\\Cache\\CappedMemoryCache:private] => Array - ( - ) - - ) - - [systemConfig:OC\\AllConfig:private] => OC\\SystemConfig Object - ( - [sensitiveValues:protected] => Array - ( - [instanceid] => 1 - [datadirectory] => 1 - [dbname] => 1 - [dbhost] => 1 - [dbpassword] => 1 - [dbuser] => 1 - [activity_dbname] => 1 - [activity_dbhost] => 1 - [activity_dbpassword] => 1 - [activity_dbuser] => 1 - [mail_from_address] => 1 - [mail_domain] => 1 - [mail_smtphost] => 1 - [mail_smtpname] => 1 - [mail_smtppassword] => 1 - [passwordsalt] => 1 - [secret] => 1 - [updater.secret] => 1 - [updater.server.url] => 1 - [trusted_proxies] => 1 - [preview_imaginary_url] => 1 - [proxyuserpwd] => 1 - [sentry.dsn] => 1 - [sentry.public-dsn] => 1 - [zammad.download.secret] => 1 - [zammad.portal.secret] => 1 - [zammad.secret] => 1 - [github.client_id] => 1 - [github.client_secret] => 1 - [log.condition] => Array - ( - [shared_secret] => 1 - ) - - [license-key] => 1 - [redis] => Array - ( - [host] => 1 - [password] => 1 - ) - - [redis.cluster] => Array - ( - [seeds] => 1 - [password] => 1 - ) - - [objectstore] => Array - ( - [arguments] => Array - ( - [options] => Array - ( - [credentials] => Array - ( - [key] => 1 - [secret] => 1 - ) - - ) - - [key] => 1 - [secret] => 1 - [username] => 1 - [password] => 1 - [user] => Array - ( - [name] => 1 - [password] => 1 - ) - - ) - - ) - - [objectstore_multibucket] => Array - ( - [arguments] => Array - ( - [options] => Array - ( - [credentials] => Array - ( - [key] => 1 - [secret] => 1 - ) - - ) - - [key] => 1 - [secret] => 1 - [username] => 1 - [password] => 1 - [user] => Array - ( - [name] => 1 - [password] => 1 - ) - - ) - - ) - - [onlyoffice] => Array - ( - [jwt_secret] => 1 - ) - - ) - - [config:OC\\SystemConfig:private] => OC\\Config Object - ( - [cache:protected] => Array - ( - [htaccess.RewriteBase] => / - [memcache.local] => \\OC\\Memcache\\APCu - [apps_paths] => Array - ( - [0] => Array - ( - [path] => /var/www/html/apps - [url] => /apps - [writable] => - ) - - [1] => Array - ( - [path] => /var/www/html/custom_apps - [url] => /custom_apps - [writable] => 1 - ) - - ) - - [upgrade.disable-web] => 1 - [passwordsalt] => vTtdPiLF5mxWWyNTVNbMrhBTE4rI3k - [secret] => MIOTZa6oerl0vEQFEEKeQ0fWwMGDN2lb7cW6Yb1l3blYwmC9 - [trusted_domains] => Array - ( - [0] => localhost - ) - - [datadirectory] => /var/www/html/data - [dbtype] => mysql - [version] => 29.0.1.1 - [overwrite.cli.url] => http://localhost - [dbname] => nextcloud - [dbhost] => mariadb-nc-1 - [dbport] => - [dbtableprefix] => oc_ - [loglevel] => 0 - [trusted_proxies] => Array - ( - [0] => 10.1.0.180 - ) - - [overwritehost] => nc-1.nl - [overwriteprotocol] => https - [mysql.utf8mb4] => 1 - [dbuser] => nextcloud - [dbpassword] => nextcloud - [installed] => 1 - [instanceid] => oc0cys0f28e0 - ) - - [envCache:protected] => Array - ( - [HOSTNAME] => da5fe9de4559 - [PHP_VERSION] => 8.2.20 - [APACHE_CONFDIR] => /etc/apache2 - [NEXTCLOUD_VERSION] => 29.0.1 - [PHP_INI_DIR] => /usr/local/etc/php - [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC - [PHP_LDFLAGS] => -Wl,-O1 -pie - [ADMIN_PASS] => passw - [PWD] => /var/www/html - [APACHE_LOG_DIR] => /var/log/apache2 - [PHP_MEMORY_LIMIT] => 512M - [LANG] => C - [APACHE_BODY_LIMIT] => 1073741824 - [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50 - [APACHE_PID_FILE] => /var/run/apache2/apache2.pid - [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c - [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31 - [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663 - [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz - [APACHE_RUN_GROUP] => www-data - [PHP_UPLOAD_LIMIT] => 512M - [APACHE_LOCK_DIR] => /var/lock/apache2 - [SHLVL] => 0 - [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - [APACHE_RUN_DIR] => /var/run/apache2 - [APACHE_ENVVARS] => /etc/apache2/envvars - [APACHE_RUN_USER] => www-data - [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - [DEBUG] => true - [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc - [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - ) - - [configDir:protected] => /var/www/html/config/ - [configFilePath:protected] => /var/www/html/config/config.php - [configFileName:protected] => config.php - [isReadOnly:protected] => - ) - - ) - - ) - - [csrfTokenManager:protected] => OC\\Security\\CSRF\\CsrfTokenManager Object - ( - [sessionStorage:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\TokenStorage\\SessionStorage Object - ( - [session:OC\\Security\\CSRF\\TokenStorage\\SessionStorage:private] => OC\\Session\\CryptoSessionData Object - ( - [session:protected] => OC\\Session\\Internal Object - ( - [sessionClosed:protected] => 1 - ) - - [crypto:protected] => OC\\Security\\Crypto Object - ( - [cipher:OC\\Security\\Crypto:private] => phpseclib\\Crypt\\AES Object - ( - [mode] => 2 - [block_size] => 16 - [key] => ??9?\u000f?\u0013??\u00180?\u0007\u001a\u001c - [iv] => ?H(?)\u001e??tD!h4R\u05c1 - [encryptIV] => ?H(?)\u001e??tD!h4R\u05c1 - [decryptIV] => ?H(?)\u001e??tD!h4R\u05c1 - [continuousBuffer] => - [enbuffer] => Array - ( - [ciphertext] => - [xor] => - [pos] => 0 - [enmcrypt_init] => 1 - ) - - [debuffer] => Array - ( - [ciphertext] => - [xor] => - [pos] => 0 - [enmcrypt_init] => 1 - ) - - [enmcrypt] => - [demcrypt] => - [enchanged] => 1 - [dechanged] => 1 - [ecb] => - [cfb_init_len] => 600 - [changed] => - [padding] => 1 - [paddable] => 1 - [engine] => 3 - [preferredEngine] => - [cipher_name_mcrypt] => rijndael-128 - [cipher_name_openssl] => aes-128-cbc - [cipher_name_openssl_ecb] => aes-128-ecb - [password_default_salt] => phpseclib - [inline_crypt] => - [use_inline_crypt] => 1 - [openssl_emulate_ctr] => - [openssl_options] => 3 - [explicit_key_length] => - [skip_key_adjustment] => - [w] => - [dw] => - [Nb] => 4 - [key_length] => 16 - [Nk] => 4 - [Nr] => - [c] => - [kl] => - ) - - [ivLength:OC\\Security\\Crypto:private] => 16 - [config:OC\\Security\\Crypto:private] => OC\\AllConfig Object - ( - [connection:OC\\AllConfig:private] => - [userCache:OC\\AllConfig:private] => OCP\\Cache\\CappedMemoryCache Object - ( - [capacity:OCP\\Cache\\CappedMemoryCache:private] => 512 - [cache:OCP\\Cache\\CappedMemoryCache:private] => Array - ( - ) - - ) - - [systemConfig:OC\\AllConfig:private] => OC\\SystemConfig Object - ( - [sensitiveValues:protected] => Array - ( - [instanceid] => 1 - [datadirectory] => 1 - [dbname] => 1 - [dbhost] => 1 - [dbpassword] => 1 - [dbuser] => 1 - [activity_dbname] => 1 - [activity_dbhost] => 1 - [activity_dbpassword] => 1 - [activity_dbuser] => 1 - [mail_from_address] => 1 - [mail_domain] => 1 - [mail_smtphost] => 1 - [mail_smtpname] => 1 - [mail_smtppassword] => 1 - [passwordsalt] => 1 - [secret] => 1 - [updater.secret] => 1 - [updater.server.url] => 1 - [trusted_proxies] => 1 - [preview_imaginary_url] => 1 - [proxyuserpwd] => 1 - [sentry.dsn] => 1 - [sentry.public-dsn] => 1 - [zammad.download.secret] => 1 - [zammad.portal.secret] => 1 - [zammad.secret] => 1 - [github.client_id] => 1 - [github.client_secret] => 1 - [log.condition] => Array - ( - [shared_secret] => 1 - ) - - [license-key] => 1 - [redis] => Array - ( - [host] => 1 - [password] => 1 - ) - - [redis.cluster] => Array - ( - [seeds] => 1 - [password] => 1 - ) - - [objectstore] => Array - ( - [arguments] => Array - ( - [options] => Array - ( - [credentials] => Array - ( - [key] => 1 - [secret] => 1 - ) - - ) - - [key] => 1 - [secret] => 1 - [username] => 1 - [password] => 1 - [user] => Array - ( - [name] => 1 - [password] => 1 - ) - - ) - - ) - - [objectstore_multibucket] => Array - ( - [arguments] => Array - ( - [options] => Array - ( - [credentials] => Array - ( - [key] => 1 - [secret] => 1 - ) - - ) - - [key] => 1 - [secret] => 1 - [username] => 1 - [password] => 1 - [user] => Array - ( - [name] => 1 - [password] => 1 - ) - - ) - - ) - - [onlyoffice] => Array - ( - [jwt_secret] => 1 - ) - - ) - - [config:OC\\SystemConfig:private] => OC\\Config Object - ( - [cache:protected] => Array - ( - [htaccess.RewriteBase] => / - [memcache.local] => \\OC\\Memcache\\APCu - [apps_paths] => Array - ( - [0] => Array - ( - [path] => /var/www/html/apps - [url] => /apps - [writable] => - ) - - [1] => Array - ( - [path] => /var/www/html/custom_apps - [url] => /custom_apps - [writable] => 1 - ) - - ) - - [upgrade.disable-web] => 1 - [passwordsalt] => vTtdPiLF5mxWWyNTVNbMrhBTE4rI3k - [secret] => MIOTZa6oerl0vEQFEEKeQ0fWwMGDN2lb7cW6Yb1l3blYwmC9 - [trusted_domains] => Array - ( - [0] => localhost - ) - - [datadirectory] => /var/www/html/data - [dbtype] => mysql - [version] => 29.0.1.1 - [overwrite.cli.url] => http://localhost - [dbname] => nextcloud - [dbhost] => mariadb-nc-1 - [dbport] => - [dbtableprefix] => oc_ - [loglevel] => 0 - [trusted_proxies] => Array - ( - [0] => 10.1.0.180 - ) - - [overwritehost] => nc-1.nl - [overwriteprotocol] => https - [mysql.utf8mb4] => 1 - [dbuser] => nextcloud - [dbpassword] => nextcloud - [installed] => 1 - [instanceid] => oc0cys0f28e0 - ) - - [envCache:protected] => Array - ( - [HOSTNAME] => da5fe9de4559 - [PHP_VERSION] => 8.2.20 - [APACHE_CONFDIR] => /etc/apache2 - [NEXTCLOUD_VERSION] => 29.0.1 - [PHP_INI_DIR] => /usr/local/etc/php - [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC - [PHP_LDFLAGS] => -Wl,-O1 -pie - [ADMIN_PASS] => passw - [PWD] => /var/www/html - [APACHE_LOG_DIR] => /var/log/apache2 - [PHP_MEMORY_LIMIT] => 512M - [LANG] => C - [APACHE_BODY_LIMIT] => 1073741824 - [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50 - [APACHE_PID_FILE] => /var/run/apache2/apache2.pid - [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c - [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31 - [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663 - [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz - [APACHE_RUN_GROUP] => www-data - [PHP_UPLOAD_LIMIT] => 512M - [APACHE_LOCK_DIR] => /var/lock/apache2 - [SHLVL] => 0 - [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - [APACHE_RUN_DIR] => /var/run/apache2 - [APACHE_ENVVARS] => /etc/apache2/envvars - [APACHE_RUN_USER] => www-data - [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - [DEBUG] => true - [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc - [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - ) - - [configDir:protected] => /var/www/html/config/ - [configFilePath:protected] => /var/www/html/config/config.php - [configFileName:protected] => config.php - [isReadOnly:protected] => - ) - - ) - - ) - - ) - - [passphrase:protected] => 971mOLK9z0nOfvBDof57cP0l6chS6ztvkeRDWxegxnuHhJauVctLggu3fthV5IgTdCnhVcuZ64itJTrlLR/iavkJrg/7cwws7lRpSk996Ny5u0zwAjgrXiP2f544zBAp - [sessionValues:protected] => Array - ( - [LAST_ACTIVITY] => 1718637416 - [requesttoken] => AOl4Y8Rlvho3bQUEv6UOYHc/UvUY5Css - [checkServer_succeeded] => 1 - ) - - [isModified:protected] => - ) - - ) - - [csrfToken:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\CsrfToken Object - ( - [encryptedValue:OC\\Security\\CSRF\\CsrfToken:private] => AP815NkCW5u/akQBkjXBwFAFxrsVhYeiLUo11+b8gpc=:QbBZ0IA6CffJAisy8GSUhSYzk/RMzeSNeDxgjtO/8eQ= - [value:OC\\Security\\CSRF\\CsrfToken:private] => AOl4Y8Rlvho3bQUEv6UOYHc/UvUY5Css - ) - - [tokenGenerator:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\CsrfTokenGenerator Object - ( - [random:OC\\Security\\CSRF\\CsrfTokenGenerator:private] => OC\\Security\\SecureRandom Object - ( - ) - - ) - - ) - - [contentDecoded:protected] => -) \ No newline at end of file diff --git a/tests/docker/integration-tests/src/tests/util/fail.txt b/tests/docker/integration-tests/src/tests/util/fail.txt deleted file mode 100644 index 496989a..0000000 --- a/tests/docker/integration-tests/src/tests/util/fail.txt +++ /dev/null @@ -1 +0,0 @@ -"OC\\AppFramework\\Http\\Request Object\n(\n [inputStream:protected] => php://input\n [content:protected] => \n [items:protected] => Array\n (\n [params] => Array\n (\n )\n\n [get] => Array\n (\n )\n\n [post] => Array\n (\n )\n\n [files] => Array\n (\n )\n\n [server] => Array\n (\n [HTTP_AUTHORIZATION] => Basic YWRtaW46cGFzc3c=\n [modHeadersAvailable] => true\n [htaccessWorking] => true\n [front_controller_active] => true\n [HTTP_HOST] => nc-1\n [HTTP_X_FORWARDED_FOR] => 10.1.0.190\n [HTTP_X_FORWARDED_PROTO] => https\n [HTTP_X_FORWARDED_HOST] => nc-1.nl\n [HTTP_CONNECTION] => close\n [HTTP_ACCEPT] => */*\n [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n [SERVER_SIGNATURE] =>
Apache/2.4.59 (Debian) Server at nc-1 Port 80
\n\n [SERVER_SOFTWARE] => Apache/2.4.59 (Debian)\n [SERVER_NAME] => nc-1\n [SERVER_ADDR] => 10.1.0.100\n [SERVER_PORT] => 80\n [REMOTE_ADDR] => 10.1.0.190\n [DOCUMENT_ROOT] => /var/www/html\n [REQUEST_SCHEME] => http\n [CONTEXT_PREFIX] => \n [CONTEXT_DOCUMENT_ROOT] => /var/www/html\n [SERVER_ADMIN] => webmaster@localhost\n [SCRIPT_FILENAME] => /var/www/html/ocs/v2.php\n [REMOTE_PORT] => 41302\n [GATEWAY_INTERFACE] => CGI/1.1\n [SERVER_PROTOCOL] => HTTP/1.0\n [REQUEST_METHOD] => GET\n [QUERY_STRING] => \n [REQUEST_URI] => /ocs/v2.php/core/getapppassword\n [SCRIPT_NAME] => /ocs/v2.php\n [PATH_INFO] => /core/getapppassword\n [PATH_TRANSLATED] => redirect:/index.php\n [PHP_SELF] => /ocs/v2.php/core/getapppassword\n [PHP_AUTH_USER] => admin\n [PHP_AUTH_PW] => passw\n [REQUEST_TIME_FLOAT] => 1718637416.7316\n [REQUEST_TIME] => 1718637416\n [argv] => Array\n (\n )\n\n [argc] => 0\n )\n\n [env] => Array\n (\n [HOSTNAME] => da5fe9de4559\n [PHP_VERSION] => 8.2.20\n [APACHE_CONFDIR] => /etc/apache2\n [NEXTCLOUD_VERSION] => 29.0.1\n [PHP_INI_DIR] => /usr/local/etc/php\n [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC\n [PHP_LDFLAGS] => -Wl,-O1 -pie\n [ADMIN_PASS] => passw\n [PWD] => /var/www/html\n [APACHE_LOG_DIR] => /var/log/apache2\n [PHP_MEMORY_LIMIT] => 512M\n [LANG] => C\n [APACHE_BODY_LIMIT] => 1073741824\n [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50\n [APACHE_PID_FILE] => /var/run/apache2/apache2.pid\n [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c\n [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31\n [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663\n [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz\n [APACHE_RUN_GROUP] => www-data\n [PHP_UPLOAD_LIMIT] => 512M\n [APACHE_LOCK_DIR] => /var/lock/apache2\n [SHLVL] => 0\n [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n [APACHE_RUN_DIR] => /var/run/apache2\n [APACHE_ENVVARS] => /etc/apache2/envvars\n [APACHE_RUN_USER] => www-data\n [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n [DEBUG] => true\n [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc\n [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n )\n\n [cookies] => Array\n (\n )\n\n [urlParams] => Array\n (\n )\n\n [parameters] => Array\n (\n )\n\n [method] => GET\n [requesttoken] => Array\n (\n )\n\n )\n\n [allowedKeys:protected] => Array\n (\n [0] => get\n [1] => post\n [2] => files\n [3] => server\n [4] => env\n [5] => cookies\n [6] => urlParams\n [7] => parameters\n [8] => method\n [9] => requesttoken\n )\n\n [requestId:protected] => OC\\AppFramework\\Http\\RequestId Object\n (\n [secureRandom:protected] => OC\\Security\\SecureRandom Object\n (\n )\n\n [requestId:protected] => \n )\n\n [config:protected] => OC\\AllConfig Object\n (\n [connection:OC\\AllConfig:private] => \n [userCache:OC\\AllConfig:private] => OCP\\Cache\\CappedMemoryCache Object\n (\n [capacity:OCP\\Cache\\CappedMemoryCache:private] => 512\n [cache:OCP\\Cache\\CappedMemoryCache:private] => Array\n (\n )\n\n )\n\n [systemConfig:OC\\AllConfig:private] => OC\\SystemConfig Object\n (\n [sensitiveValues:protected] => Array\n (\n [instanceid] => 1\n [datadirectory] => 1\n [dbname] => 1\n [dbhost] => 1\n [dbpassword] => 1\n [dbuser] => 1\n [activity_dbname] => 1\n [activity_dbhost] => 1\n [activity_dbpassword] => 1\n [activity_dbuser] => 1\n [mail_from_address] => 1\n [mail_domain] => 1\n [mail_smtphost] => 1\n [mail_smtpname] => 1\n [mail_smtppassword] => 1\n [passwordsalt] => 1\n [secret] => 1\n [updater.secret] => 1\n [updater.server.url] => 1\n [trusted_proxies] => 1\n [preview_imaginary_url] => 1\n [proxyuserpwd] => 1\n [sentry.dsn] => 1\n [sentry.public-dsn] => 1\n [zammad.download.secret] => 1\n [zammad.portal.secret] => 1\n [zammad.secret] => 1\n [github.client_id] => 1\n [github.client_secret] => 1\n [log.condition] => Array\n (\n [shared_secret] => 1\n )\n\n [license-key] => 1\n [redis] => Array\n (\n [host] => 1\n [password] => 1\n )\n\n [redis.cluster] => Array\n (\n [seeds] => 1\n [password] => 1\n )\n\n [objectstore] => Array\n (\n [arguments] => Array\n (\n [options] => Array\n (\n [credentials] => Array\n (\n [key] => 1\n [secret] => 1\n )\n\n )\n\n [key] => 1\n [secret] => 1\n [username] => 1\n [password] => 1\n [user] => Array\n (\n [name] => 1\n [password] => 1\n )\n\n )\n\n )\n\n [objectstore_multibucket] => Array\n (\n [arguments] => Array\n (\n [options] => Array\n (\n [credentials] => Array\n (\n [key] => 1\n [secret] => 1\n )\n\n )\n\n [key] => 1\n [secret] => 1\n [username] => 1\n [password] => 1\n [user] => Array\n (\n [name] => 1\n [password] => 1\n )\n\n )\n\n )\n\n [onlyoffice] => Array\n (\n [jwt_secret] => 1\n )\n\n )\n\n [config:OC\\SystemConfig:private] => OC\\Config Object\n (\n [cache:protected] => Array\n (\n [htaccess.RewriteBase] => /\n [memcache.local] => \\OC\\Memcache\\APCu\n [apps_paths] => Array\n (\n [0] => Array\n (\n [path] => /var/www/html/apps\n [url] => /apps\n [writable] => \n )\n\n [1] => Array\n (\n [path] => /var/www/html/custom_apps\n [url] => /custom_apps\n [writable] => 1\n )\n\n )\n\n [upgrade.disable-web] => 1\n [passwordsalt] => vTtdPiLF5mxWWyNTVNbMrhBTE4rI3k\n [secret] => MIOTZa6oerl0vEQFEEKeQ0fWwMGDN2lb7cW6Yb1l3blYwmC9\n [trusted_domains] => Array\n (\n [0] => localhost\n )\n\n [datadirectory] => /var/www/html/data\n [dbtype] => mysql\n [version] => 29.0.1.1\n [overwrite.cli.url] => http://localhost\n [dbname] => nextcloud\n [dbhost] => mariadb-nc-1\n [dbport] => \n [dbtableprefix] => oc_\n [loglevel] => 0\n [trusted_proxies] => Array\n (\n [0] => 10.1.0.180\n )\n\n [overwritehost] => nc-1.nl\n [overwriteprotocol] => https\n [mysql.utf8mb4] => 1\n [dbuser] => nextcloud\n [dbpassword] => nextcloud\n [installed] => 1\n [instanceid] => oc0cys0f28e0\n )\n\n [envCache:protected] => Array\n (\n [HOSTNAME] => da5fe9de4559\n [PHP_VERSION] => 8.2.20\n [APACHE_CONFDIR] => /etc/apache2\n [NEXTCLOUD_VERSION] => 29.0.1\n [PHP_INI_DIR] => /usr/local/etc/php\n [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC\n [PHP_LDFLAGS] => -Wl,-O1 -pie\n [ADMIN_PASS] => passw\n [PWD] => /var/www/html\n [APACHE_LOG_DIR] => /var/log/apache2\n [PHP_MEMORY_LIMIT] => 512M\n [LANG] => C\n [APACHE_BODY_LIMIT] => 1073741824\n [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50\n [APACHE_PID_FILE] => /var/run/apache2/apache2.pid\n [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c\n [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31\n [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663\n [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz\n [APACHE_RUN_GROUP] => www-data\n [PHP_UPLOAD_LIMIT] => 512M\n [APACHE_LOCK_DIR] => /var/lock/apache2\n [SHLVL] => 0\n [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n [APACHE_RUN_DIR] => /var/run/apache2\n [APACHE_ENVVARS] => /etc/apache2/envvars\n [APACHE_RUN_USER] => www-data\n [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n [DEBUG] => true\n [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc\n [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n )\n\n [configDir:protected] => /var/www/html/config/\n [configFilePath:protected] => /var/www/html/config/config.php\n [configFileName:protected] => config.php\n [isReadOnly:protected] => \n )\n\n )\n\n )\n\n [csrfTokenManager:protected] => OC\\Security\\CSRF\\CsrfTokenManager Object\n (\n [sessionStorage:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\TokenStorage\\SessionStorage Object\n (\n [session:OC\\Security\\CSRF\\TokenStorage\\SessionStorage:private] => OC\\Session\\CryptoSessionData Object\n (\n [session:protected] => OC\\Session\\Internal Object\n (\n [sessionClosed:protected] => 1\n )\n\n [crypto:protected] => OC\\Security\\Crypto Object\n (\n [cipher:OC\\Security\\Crypto:private] => phpseclib\\Crypt\\AES Object\n (\n [mode] => 2\n [block_size] => 16\n [key] => ??9?\u000f?\u0013??\u00180?\u0007\u001a\u001c\n [iv] => ?H(?)\u001e??tD!h4R\u05c1\n [encryptIV] => ?H(?)\u001e??tD!h4R\u05c1\n [decryptIV] => ?H(?)\u001e??tD!h4R\u05c1\n [continuousBuffer] => \n [enbuffer] => Array\n (\n [ciphertext] => \n [xor] => \n [pos] => 0\n [enmcrypt_init] => 1\n )\n\n [debuffer] => Array\n (\n [ciphertext] => \n [xor] => \n [pos] => 0\n [enmcrypt_init] => 1\n )\n\n [enmcrypt] => \n [demcrypt] => \n [enchanged] => 1\n [dechanged] => 1\n [ecb] => \n [cfb_init_len] => 600\n [changed] => \n [padding] => 1\n [paddable] => 1\n [engine] => 3\n [preferredEngine] => \n [cipher_name_mcrypt] => rijndael-128\n [cipher_name_openssl] => aes-128-cbc\n [cipher_name_openssl_ecb] => aes-128-ecb\n [password_default_salt] => phpseclib\n [inline_crypt] => \n [use_inline_crypt] => 1\n [openssl_emulate_ctr] => \n [openssl_options] => 3\n [explicit_key_length] => \n [skip_key_adjustment] => \n [w] => \n [dw] => \n [Nb] => 4\n [key_length] => 16\n [Nk] => 4\n [Nr] => \n [c] => \n [kl] => \n )\n\n [ivLength:OC\\Security\\Crypto:private] => 16\n [config:OC\\Security\\Crypto:private] => OC\\AllConfig Object\n (\n [connection:OC\\AllConfig:private] => \n [userCache:OC\\AllConfig:private] => OCP\\Cache\\CappedMemoryCache Object\n (\n [capacity:OCP\\Cache\\CappedMemoryCache:private] => 512\n [cache:OCP\\Cache\\CappedMemoryCache:private] => Array\n (\n )\n\n )\n\n [systemConfig:OC\\AllConfig:private] => OC\\SystemConfig Object\n (\n [sensitiveValues:protected] => Array\n (\n [instanceid] => 1\n [datadirectory] => 1\n [dbname] => 1\n [dbhost] => 1\n [dbpassword] => 1\n [dbuser] => 1\n [activity_dbname] => 1\n [activity_dbhost] => 1\n [activity_dbpassword] => 1\n [activity_dbuser] => 1\n [mail_from_address] => 1\n [mail_domain] => 1\n [mail_smtphost] => 1\n [mail_smtpname] => 1\n [mail_smtppassword] => 1\n [passwordsalt] => 1\n [secret] => 1\n [updater.secret] => 1\n [updater.server.url] => 1\n [trusted_proxies] => 1\n [preview_imaginary_url] => 1\n [proxyuserpwd] => 1\n [sentry.dsn] => 1\n [sentry.public-dsn] => 1\n [zammad.download.secret] => 1\n [zammad.portal.secret] => 1\n [zammad.secret] => 1\n [github.client_id] => 1\n [github.client_secret] => 1\n [log.condition] => Array\n (\n [shared_secret] => 1\n )\n\n [license-key] => 1\n [redis] => Array\n (\n [host] => 1\n [password] => 1\n )\n\n [redis.cluster] => Array\n (\n [seeds] => 1\n [password] => 1\n )\n\n [objectstore] => Array\n (\n [arguments] => Array\n (\n [options] => Array\n (\n [credentials] => Array\n (\n [key] => 1\n [secret] => 1\n )\n\n )\n\n [key] => 1\n [secret] => 1\n [username] => 1\n [password] => 1\n [user] => Array\n (\n [name] => 1\n [password] => 1\n )\n\n )\n\n )\n\n [objectstore_multibucket] => Array\n (\n [arguments] => Array\n (\n [options] => Array\n (\n [credentials] => Array\n (\n [key] => 1\n [secret] => 1\n )\n\n )\n\n [key] => 1\n [secret] => 1\n [username] => 1\n [password] => 1\n [user] => Array\n (\n [name] => 1\n [password] => 1\n )\n\n )\n\n )\n\n [onlyoffice] => Array\n (\n [jwt_secret] => 1\n )\n\n )\n\n [config:OC\\SystemConfig:private] => OC\\Config Object\n (\n [cache:protected] => Array\n (\n [htaccess.RewriteBase] => /\n [memcache.local] => \\OC\\Memcache\\APCu\n [apps_paths] => Array\n (\n [0] => Array\n (\n [path] => /var/www/html/apps\n [url] => /apps\n [writable] => \n )\n\n [1] => Array\n (\n [path] => /var/www/html/custom_apps\n [url] => /custom_apps\n [writable] => 1\n )\n\n )\n\n [upgrade.disable-web] => 1\n [passwordsalt] => vTtdPiLF5mxWWyNTVNbMrhBTE4rI3k\n [secret] => MIOTZa6oerl0vEQFEEKeQ0fWwMGDN2lb7cW6Yb1l3blYwmC9\n [trusted_domains] => Array\n (\n [0] => localhost\n )\n\n [datadirectory] => /var/www/html/data\n [dbtype] => mysql\n [version] => 29.0.1.1\n [overwrite.cli.url] => http://localhost\n [dbname] => nextcloud\n [dbhost] => mariadb-nc-1\n [dbport] => \n [dbtableprefix] => oc_\n [loglevel] => 0\n [trusted_proxies] => Array\n (\n [0] => 10.1.0.180\n )\n\n [overwritehost] => nc-1.nl\n [overwriteprotocol] => https\n [mysql.utf8mb4] => 1\n [dbuser] => nextcloud\n [dbpassword] => nextcloud\n [installed] => 1\n [instanceid] => oc0cys0f28e0\n )\n\n [envCache:protected] => Array\n (\n [HOSTNAME] => da5fe9de4559\n [PHP_VERSION] => 8.2.20\n [APACHE_CONFDIR] => /etc/apache2\n [NEXTCLOUD_VERSION] => 29.0.1\n [PHP_INI_DIR] => /usr/local/etc/php\n [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC\n [PHP_LDFLAGS] => -Wl,-O1 -pie\n [ADMIN_PASS] => passw\n [PWD] => /var/www/html\n [APACHE_LOG_DIR] => /var/log/apache2\n [PHP_MEMORY_LIMIT] => 512M\n [LANG] => C\n [APACHE_BODY_LIMIT] => 1073741824\n [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50\n [APACHE_PID_FILE] => /var/run/apache2/apache2.pid\n [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c\n [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31\n [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663\n [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz\n [APACHE_RUN_GROUP] => www-data\n [PHP_UPLOAD_LIMIT] => 512M\n [APACHE_LOCK_DIR] => /var/lock/apache2\n [SHLVL] => 0\n [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n [APACHE_RUN_DIR] => /var/run/apache2\n [APACHE_ENVVARS] => /etc/apache2/envvars\n [APACHE_RUN_USER] => www-data\n [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n [DEBUG] => true\n [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc\n [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n )\n\n [configDir:protected] => /var/www/html/config/\n [configFilePath:protected] => /var/www/html/config/config.php\n [configFileName:protected] => config.php\n [isReadOnly:protected] => \n )\n\n )\n\n )\n\n )\n\n [passphrase:protected] => 971mOLK9z0nOfvBDof57cP0l6chS6ztvkeRDWxegxnuHhJauVctLggu3fthV5IgTdCnhVcuZ64itJTrlLR/iavkJrg/7cwws7lRpSk996Ny5u0zwAjgrXiP2f544zBAp\n [sessionValues:protected] => Array\n (\n [LAST_ACTIVITY] => 1718637416\n [requesttoken] => AOl4Y8Rlvho3bQUEv6UOYHc/UvUY5Css\n [checkServer_succeeded] => 1\n )\n\n [isModified:protected] => \n )\n\n )\n\n [csrfToken:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\CsrfToken Object\n (\n [encryptedValue:OC\\Security\\CSRF\\CsrfToken:private] => AP815NkCW5u/akQBkjXBwFAFxrsVhYeiLUo11+b8gpc=:QbBZ0IA6CffJAisy8GSUhSYzk/RMzeSNeDxgjtO/8eQ=\n [value:OC\\Security\\CSRF\\CsrfToken:private] => AOl4Y8Rlvho3bQUEv6UOYHc/UvUY5Css\n )\n\n [tokenGenerator:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\CsrfTokenGenerator Object\n (\n [random:OC\\Security\\CSRF\\CsrfTokenGenerator:private] => OC\\Security\\SecureRandom Object\n (\n )\n\n )\n\n )\n\n [contentDecoded:protected] => \n)\n \ No newline at end of file diff --git a/tests/docker/integration-tests/src/tests/util/success-formatted.txt b/tests/docker/integration-tests/src/tests/util/success-formatted.txt deleted file mode 100644 index 07bb5c5..0000000 --- a/tests/docker/integration-tests/src/tests/util/success-formatted.txt +++ /dev/null @@ -1,703 +0,0 @@ -"OC\\AppFramework\\Http\\Request Object -( - [inputStream:protected] => php://input - [content:protected] => - [items:protected] => Array - ( - [params] => Array - ( - ) - - [get] => Array - ( - ) - - [post] => Array - ( - ) - - [files] => Array - ( - ) - - [server] => Array - ( - [HTTP_AUTHORIZATION] => Basic YWRtaW46cGFzc3c= - [modHeadersAvailable] => true - [htaccessWorking] => true - [front_controller_active] => true - [HTTP_HOST] => nc-1 - [HTTP_X_FORWARDED_FOR] => 10.1.0.1 - [HTTP_X_FORWARDED_PROTO] => http - [HTTP_X_FORWARDED_HOST] => nc-1.nl - [HTTP_CONNECTION] => close - [HTTP_USER_AGENT] => curl/7.81.0 - [HTTP_ACCEPT] => */* - [HTTP_OCS_APIREQUEST] => true - [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - [SERVER_SIGNATURE] =>
Apache/2.4.59 (Debian) Server at nc-1 Port 80
- - [SERVER_SOFTWARE] => Apache/2.4.59 (Debian) - [SERVER_NAME] => nc-1 - [SERVER_ADDR] => 10.1.0.100 - [SERVER_PORT] => 80 - [REMOTE_ADDR] => 10.1.0.1 - [DOCUMENT_ROOT] => /var/www/html - [REQUEST_SCHEME] => http - [CONTEXT_PREFIX] => - [CONTEXT_DOCUMENT_ROOT] => /var/www/html - [SERVER_ADMIN] => webmaster@localhost - [SCRIPT_FILENAME] => /var/www/html/ocs/v2.php - [REMOTE_PORT] => 38516 - [GATEWAY_INTERFACE] => CGI/1.1 - [SERVER_PROTOCOL] => HTTP/1.0 - [REQUEST_METHOD] => GET - [QUERY_STRING] => - [REQUEST_URI] => /ocs/v2.php/core/getapppassword - [SCRIPT_NAME] => /ocs/v2.php - [PATH_INFO] => /core/getapppassword - [PATH_TRANSLATED] => redirect:/index.php - [PHP_SELF] => /ocs/v2.php/core/getapppassword - [PHP_AUTH_USER] => admin - [PHP_AUTH_PW] => passw - [REQUEST_TIME_FLOAT] => 1718637660.2152 - [REQUEST_TIME] => 1718637660 - [argv] => Array - ( - ) - - [argc] => 0 - ) - - [env] => Array - ( - [HOSTNAME] => da5fe9de4559 - [PHP_VERSION] => 8.2.20 - [APACHE_CONFDIR] => /etc/apache2 - [NEXTCLOUD_VERSION] => 29.0.1 - [PHP_INI_DIR] => /usr/local/etc/php - [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC - [PHP_LDFLAGS] => -Wl,-O1 -pie - [ADMIN_PASS] => passw - [PWD] => /var/www/html - [APACHE_LOG_DIR] => /var/log/apache2 - [PHP_MEMORY_LIMIT] => 512M - [LANG] => C - [APACHE_BODY_LIMIT] => 1073741824 - [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50 - [APACHE_PID_FILE] => /var/run/apache2/apache2.pid - [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c - [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31 - [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663 - [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz - [APACHE_RUN_GROUP] => www-data - [PHP_UPLOAD_LIMIT] => 512M - [APACHE_LOCK_DIR] => /var/lock/apache2 - [SHLVL] => 0 - [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - [APACHE_RUN_DIR] => /var/run/apache2 - [APACHE_ENVVARS] => /etc/apache2/envvars - [APACHE_RUN_USER] => www-data - [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - [DEBUG] => true - [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc - [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - ) - - [cookies] => Array - ( - ) - - [urlParams] => Array - ( - ) - - [parameters] => Array - ( - ) - - [method] => GET - [requesttoken] => Array - ( - ) - - ) - - [allowedKeys:protected] => Array - ( - [0] => get - [1] => post - [2] => files - [3] => server - [4] => env - [5] => cookies - [6] => urlParams - [7] => parameters - [8] => method - [9] => requesttoken - ) - - [requestId:protected] => OC\\AppFramework\\Http\\RequestId Object - ( - [secureRandom:protected] => OC\\Security\\SecureRandom Object - ( - ) - - [requestId:protected] => - ) - - [config:protected] => OC\\AllConfig Object - ( - [connection:OC\\AllConfig:private] => - [userCache:OC\\AllConfig:private] => OCP\\Cache\\CappedMemoryCache Object - ( - [capacity:OCP\\Cache\\CappedMemoryCache:private] => 512 - [cache:OCP\\Cache\\CappedMemoryCache:private] => Array - ( - ) - - ) - - [systemConfig:OC\\AllConfig:private] => OC\\SystemConfig Object - ( - [sensitiveValues:protected] => Array - ( - [instanceid] => 1 - [datadirectory] => 1 - [dbname] => 1 - [dbhost] => 1 - [dbpassword] => 1 - [dbuser] => 1 - [activity_dbname] => 1 - [activity_dbhost] => 1 - [activity_dbpassword] => 1 - [activity_dbuser] => 1 - [mail_from_address] => 1 - [mail_domain] => 1 - [mail_smtphost] => 1 - [mail_smtpname] => 1 - [mail_smtppassword] => 1 - [passwordsalt] => 1 - [secret] => 1 - [updater.secret] => 1 - [updater.server.url] => 1 - [trusted_proxies] => 1 - [preview_imaginary_url] => 1 - [proxyuserpwd] => 1 - [sentry.dsn] => 1 - [sentry.public-dsn] => 1 - [zammad.download.secret] => 1 - [zammad.portal.secret] => 1 - [zammad.secret] => 1 - [github.client_id] => 1 - [github.client_secret] => 1 - [log.condition] => Array - ( - [shared_secret] => 1 - ) - - [license-key] => 1 - [redis] => Array - ( - [host] => 1 - [password] => 1 - ) - - [redis.cluster] => Array - ( - [seeds] => 1 - [password] => 1 - ) - - [objectstore] => Array - ( - [arguments] => Array - ( - [options] => Array - ( - [credentials] => Array - ( - [key] => 1 - [secret] => 1 - ) - - ) - - [key] => 1 - [secret] => 1 - [username] => 1 - [password] => 1 - [user] => Array - ( - [name] => 1 - [password] => 1 - ) - - ) - - ) - - [objectstore_multibucket] => Array - ( - [arguments] => Array - ( - [options] => Array - ( - [credentials] => Array - ( - [key] => 1 - [secret] => 1 - ) - - ) - - [key] => 1 - [secret] => 1 - [username] => 1 - [password] => 1 - [user] => Array - ( - [name] => 1 - [password] => 1 - ) - - ) - - ) - - [onlyoffice] => Array - ( - [jwt_secret] => 1 - ) - - ) - - [config:OC\\SystemConfig:private] => OC\\Config Object - ( - [cache:protected] => Array - ( - [htaccess.RewriteBase] => / - [memcache.local] => \\OC\\Memcache\\APCu - [apps_paths] => Array - ( - [0] => Array - ( - [path] => /var/www/html/apps - [url] => /apps - [writable] => - ) - - [1] => Array - ( - [path] => /var/www/html/custom_apps - [url] => /custom_apps - [writable] => 1 - ) - - ) - - [upgrade.disable-web] => 1 - [passwordsalt] => vTtdPiLF5mxWWyNTVNbMrhBTE4rI3k - [secret] => MIOTZa6oerl0vEQFEEKeQ0fWwMGDN2lb7cW6Yb1l3blYwmC9 - [trusted_domains] => Array - ( - [0] => localhost - ) - - [datadirectory] => /var/www/html/data - [dbtype] => mysql - [version] => 29.0.1.1 - [overwrite.cli.url] => http://localhost - [dbname] => nextcloud - [dbhost] => mariadb-nc-1 - [dbport] => - [dbtableprefix] => oc_ - [loglevel] => 0 - [trusted_proxies] => Array - ( - [0] => 10.1.0.180 - ) - - [overwritehost] => nc-1.nl - [overwriteprotocol] => https - [mysql.utf8mb4] => 1 - [dbuser] => nextcloud - [dbpassword] => nextcloud - [installed] => 1 - [instanceid] => oc0cys0f28e0 - ) - - [envCache:protected] => Array - ( - [HOSTNAME] => da5fe9de4559 - [PHP_VERSION] => 8.2.20 - [APACHE_CONFDIR] => /etc/apache2 - [NEXTCLOUD_VERSION] => 29.0.1 - [PHP_INI_DIR] => /usr/local/etc/php - [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC - [PHP_LDFLAGS] => -Wl,-O1 -pie - [ADMIN_PASS] => passw - [PWD] => /var/www/html - [APACHE_LOG_DIR] => /var/log/apache2 - [PHP_MEMORY_LIMIT] => 512M - [LANG] => C - [APACHE_BODY_LIMIT] => 1073741824 - [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50 - [APACHE_PID_FILE] => /var/run/apache2/apache2.pid - [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c - [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31 - [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663 - [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz - [APACHE_RUN_GROUP] => www-data - [PHP_UPLOAD_LIMIT] => 512M - [APACHE_LOCK_DIR] => /var/lock/apache2 - [SHLVL] => 0 - [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - [APACHE_RUN_DIR] => /var/run/apache2 - [APACHE_ENVVARS] => /etc/apache2/envvars - [APACHE_RUN_USER] => www-data - [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - [DEBUG] => true - [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc - [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - ) - - [configDir:protected] => /var/www/html/config/ - [configFilePath:protected] => /var/www/html/config/config.php - [configFileName:protected] => config.php - [isReadOnly:protected] => - ) - - ) - - ) - - [csrfTokenManager:protected] => OC\\Security\\CSRF\\CsrfTokenManager Object - ( - [sessionStorage:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\TokenStorage\\SessionStorage Object - ( - [session:OC\\Security\\CSRF\\TokenStorage\\SessionStorage:private] => OC\\Session\\CryptoSessionData Object - ( - [session:protected] => OC\\Session\\Internal Object - ( - [sessionClosed:protected] => 1 - ) - - [crypto:protected] => OC\\Security\\Crypto Object - ( - [cipher:OC\\Security\\Crypto:private] => phpseclib\\Crypt\\AES Object - ( - [mode] => 2 - [block_size] => 16 - [key] => ??\u0010?t\tL?\u001c?2.???\u001c - [iv] => \u0013\u000f???[3}?\u001e????r - [encryptIV] => \u0013\u000f???[3}?\u001e????r - [decryptIV] => \u0013\u000f???[3}?\u001e????r - [continuousBuffer] => - [enbuffer] => Array - ( - [ciphertext] => - [xor] => - [pos] => 0 - [enmcrypt_init] => 1 - ) - - [debuffer] => Array - ( - [ciphertext] => - [xor] => - [pos] => 0 - [enmcrypt_init] => 1 - ) - - [enmcrypt] => - [demcrypt] => - [enchanged] => 1 - [dechanged] => 1 - [ecb] => - [cfb_init_len] => 600 - [changed] => - [padding] => 1 - [paddable] => 1 - [engine] => 3 - [preferredEngine] => - [cipher_name_mcrypt] => rijndael-128 - [cipher_name_openssl] => aes-128-cbc - [cipher_name_openssl_ecb] => aes-128-ecb - [password_default_salt] => phpseclib - [inline_crypt] => - [use_inline_crypt] => 1 - [openssl_emulate_ctr] => - [openssl_options] => 3 - [explicit_key_length] => - [skip_key_adjustment] => - [w] => - [dw] => - [Nb] => 4 - [key_length] => 16 - [Nk] => 4 - [Nr] => - [c] => - [kl] => - ) - - [ivLength:OC\\Security\\Crypto:private] => 16 - [config:OC\\Security\\Crypto:private] => OC\\AllConfig Object - ( - [connection:OC\\AllConfig:private] => - [userCache:OC\\AllConfig:private] => OCP\\Cache\\CappedMemoryCache Object - ( - [capacity:OCP\\Cache\\CappedMemoryCache:private] => 512 - [cache:OCP\\Cache\\CappedMemoryCache:private] => Array - ( - ) - - ) - - [systemConfig:OC\\AllConfig:private] => OC\\SystemConfig Object - ( - [sensitiveValues:protected] => Array - ( - [instanceid] => 1 - [datadirectory] => 1 - [dbname] => 1 - [dbhost] => 1 - [dbpassword] => 1 - [dbuser] => 1 - [activity_dbname] => 1 - [activity_dbhost] => 1 - [activity_dbpassword] => 1 - [activity_dbuser] => 1 - [mail_from_address] => 1 - [mail_domain] => 1 - [mail_smtphost] => 1 - [mail_smtpname] => 1 - [mail_smtppassword] => 1 - [passwordsalt] => 1 - [secret] => 1 - [updater.secret] => 1 - [updater.server.url] => 1 - [trusted_proxies] => 1 - [preview_imaginary_url] => 1 - [proxyuserpwd] => 1 - [sentry.dsn] => 1 - [sentry.public-dsn] => 1 - [zammad.download.secret] => 1 - [zammad.portal.secret] => 1 - [zammad.secret] => 1 - [github.client_id] => 1 - [github.client_secret] => 1 - [log.condition] => Array - ( - [shared_secret] => 1 - ) - - [license-key] => 1 - [redis] => Array - ( - [host] => 1 - [password] => 1 - ) - - [redis.cluster] => Array - ( - [seeds] => 1 - [password] => 1 - ) - - [objectstore] => Array - ( - [arguments] => Array - ( - [options] => Array - ( - [credentials] => Array - ( - [key] => 1 - [secret] => 1 - ) - - ) - - [key] => 1 - [secret] => 1 - [username] => 1 - [password] => 1 - [user] => Array - ( - [name] => 1 - [password] => 1 - ) - - ) - - ) - - [objectstore_multibucket] => Array - ( - [arguments] => Array - ( - [options] => Array - ( - [credentials] => Array - ( - [key] => 1 - [secret] => 1 - ) - - ) - - [key] => 1 - [secret] => 1 - [username] => 1 - [password] => 1 - [user] => Array - ( - [name] => 1 - [password] => 1 - ) - - ) - - ) - - [onlyoffice] => Array - ( - [jwt_secret] => 1 - ) - - ) - - [config:OC\\SystemConfig:private] => OC\\Config Object - ( - [cache:protected] => Array - ( - [htaccess.RewriteBase] => / - [memcache.local] => \\OC\\Memcache\\APCu - [apps_paths] => Array - ( - [0] => Array - ( - [path] => /var/www/html/apps - [url] => /apps - [writable] => - ) - - [1] => Array - ( - [path] => /var/www/html/custom_apps - [url] => /custom_apps - [writable] => 1 - ) - - ) - - [upgrade.disable-web] => 1 - [passwordsalt] => vTtdPiLF5mxWWyNTVNbMrhBTE4rI3k - [secret] => MIOTZa6oerl0vEQFEEKeQ0fWwMGDN2lb7cW6Yb1l3blYwmC9 - [trusted_domains] => Array - ( - [0] => localhost - ) - - [datadirectory] => /var/www/html/data - [dbtype] => mysql - [version] => 29.0.1.1 - [overwrite.cli.url] => http://localhost - [dbname] => nextcloud - [dbhost] => mariadb-nc-1 - [dbport] => - [dbtableprefix] => oc_ - [loglevel] => 0 - [trusted_proxies] => Array - ( - [0] => 10.1.0.180 - ) - - [overwritehost] => nc-1.nl - [overwriteprotocol] => https - [mysql.utf8mb4] => 1 - [dbuser] => nextcloud - [dbpassword] => nextcloud - [installed] => 1 - [instanceid] => oc0cys0f28e0 - ) - - [envCache:protected] => Array - ( - [HOSTNAME] => da5fe9de4559 - [PHP_VERSION] => 8.2.20 - [APACHE_CONFDIR] => /etc/apache2 - [NEXTCLOUD_VERSION] => 29.0.1 - [PHP_INI_DIR] => /usr/local/etc/php - [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC - [PHP_LDFLAGS] => -Wl,-O1 -pie - [ADMIN_PASS] => passw - [PWD] => /var/www/html - [APACHE_LOG_DIR] => /var/log/apache2 - [PHP_MEMORY_LIMIT] => 512M - [LANG] => C - [APACHE_BODY_LIMIT] => 1073741824 - [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50 - [APACHE_PID_FILE] => /var/run/apache2/apache2.pid - [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c - [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31 - [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663 - [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz - [APACHE_RUN_GROUP] => www-data - [PHP_UPLOAD_LIMIT] => 512M - [APACHE_LOCK_DIR] => /var/lock/apache2 - [SHLVL] => 0 - [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - [APACHE_RUN_DIR] => /var/run/apache2 - [APACHE_ENVVARS] => /etc/apache2/envvars - [APACHE_RUN_USER] => www-data - [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - [DEBUG] => true - [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc - [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 - ) - - [configDir:protected] => /var/www/html/config/ - [configFilePath:protected] => /var/www/html/config/config.php - [configFileName:protected] => config.php - [isReadOnly:protected] => - ) - - ) - - ) - - ) - - [passphrase:protected] => 7Lalvsix5wllH+C7lDO0mKdJdb95ZSGDlV1r4msAD6h1r1ULWTaUT3l0cl0jsIjj80MYVlbDIz8K59vNDYvgkMeSi0+nwrGDgA1C926gsF6L4QcF2PC1aMBzoXmdir9v - [sessionValues:protected] => Array - ( - [LAST_ACTIVITY] => 1718637660 - [requesttoken] => SqFb8pQbZpHstA0N82m9OES/DcIqknKp - [checkServer_succeeded] => 1 - ) - - [isModified:protected] => - ) - - ) - - [csrfToken:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\CsrfToken Object - ( - [encryptedValue:OC\\Security\\CSRF\\CsrfToken:private] => Iq5Wua3TezVXBiWoVR5lkvpMEsvmpDJhOSWA1FDBSEE=:cd8Q25WjKlcNdm3bIV9V3MJ+f/Kp4WFOfUbJpTuvAzE= - [value:OC\\Security\\CSRF\\CsrfToken:private] => SqFb8pQbZpHstA0N82m9OES/DcIqknKp - ) - - [tokenGenerator:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\CsrfTokenGenerator Object - ( - [random:OC\\Security\\CSRF\\CsrfTokenGenerator:private] => OC\\Security\\SecureRandom Object - ( - ) - - ) - - ) - - [contentDecoded:protected] => -) \ No newline at end of file diff --git a/tests/docker/integration-tests/src/tests/util/success.txt b/tests/docker/integration-tests/src/tests/util/success.txt deleted file mode 100644 index ae5f6e1..0000000 --- a/tests/docker/integration-tests/src/tests/util/success.txt +++ /dev/null @@ -1 +0,0 @@ -"OC\\AppFramework\\Http\\Request Object\n(\n [inputStream:protected] => php://input\n [content:protected] => \n [items:protected] => Array\n (\n [params] => Array\n (\n )\n\n [get] => Array\n (\n )\n\n [post] => Array\n (\n )\n\n [files] => Array\n (\n )\n\n [server] => Array\n (\n [HTTP_AUTHORIZATION] => Basic YWRtaW46cGFzc3c=\n [modHeadersAvailable] => true\n [htaccessWorking] => true\n [front_controller_active] => true\n [HTTP_HOST] => nc-1\n [HTTP_X_FORWARDED_FOR] => 10.1.0.1\n [HTTP_X_FORWARDED_PROTO] => http\n [HTTP_X_FORWARDED_HOST] => nc-1.nl\n [HTTP_CONNECTION] => close\n [HTTP_USER_AGENT] => curl/7.81.0\n [HTTP_ACCEPT] => */*\n [HTTP_OCS_APIREQUEST] => true\n [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n [SERVER_SIGNATURE] =>
Apache/2.4.59 (Debian) Server at nc-1 Port 80
\n\n [SERVER_SOFTWARE] => Apache/2.4.59 (Debian)\n [SERVER_NAME] => nc-1\n [SERVER_ADDR] => 10.1.0.100\n [SERVER_PORT] => 80\n [REMOTE_ADDR] => 10.1.0.1\n [DOCUMENT_ROOT] => /var/www/html\n [REQUEST_SCHEME] => http\n [CONTEXT_PREFIX] => \n [CONTEXT_DOCUMENT_ROOT] => /var/www/html\n [SERVER_ADMIN] => webmaster@localhost\n [SCRIPT_FILENAME] => /var/www/html/ocs/v2.php\n [REMOTE_PORT] => 38516\n [GATEWAY_INTERFACE] => CGI/1.1\n [SERVER_PROTOCOL] => HTTP/1.0\n [REQUEST_METHOD] => GET\n [QUERY_STRING] => \n [REQUEST_URI] => /ocs/v2.php/core/getapppassword\n [SCRIPT_NAME] => /ocs/v2.php\n [PATH_INFO] => /core/getapppassword\n [PATH_TRANSLATED] => redirect:/index.php\n [PHP_SELF] => /ocs/v2.php/core/getapppassword\n [PHP_AUTH_USER] => admin\n [PHP_AUTH_PW] => passw\n [REQUEST_TIME_FLOAT] => 1718637660.2152\n [REQUEST_TIME] => 1718637660\n [argv] => Array\n (\n )\n\n [argc] => 0\n )\n\n [env] => Array\n (\n [HOSTNAME] => da5fe9de4559\n [PHP_VERSION] => 8.2.20\n [APACHE_CONFDIR] => /etc/apache2\n [NEXTCLOUD_VERSION] => 29.0.1\n [PHP_INI_DIR] => /usr/local/etc/php\n [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC\n [PHP_LDFLAGS] => -Wl,-O1 -pie\n [ADMIN_PASS] => passw\n [PWD] => /var/www/html\n [APACHE_LOG_DIR] => /var/log/apache2\n [PHP_MEMORY_LIMIT] => 512M\n [LANG] => C\n [APACHE_BODY_LIMIT] => 1073741824\n [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50\n [APACHE_PID_FILE] => /var/run/apache2/apache2.pid\n [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c\n [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31\n [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663\n [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz\n [APACHE_RUN_GROUP] => www-data\n [PHP_UPLOAD_LIMIT] => 512M\n [APACHE_LOCK_DIR] => /var/lock/apache2\n [SHLVL] => 0\n [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n [APACHE_RUN_DIR] => /var/run/apache2\n [APACHE_ENVVARS] => /etc/apache2/envvars\n [APACHE_RUN_USER] => www-data\n [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n [DEBUG] => true\n [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc\n [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n )\n\n [cookies] => Array\n (\n )\n\n [urlParams] => Array\n (\n )\n\n [parameters] => Array\n (\n )\n\n [method] => GET\n [requesttoken] => Array\n (\n )\n\n )\n\n [allowedKeys:protected] => Array\n (\n [0] => get\n [1] => post\n [2] => files\n [3] => server\n [4] => env\n [5] => cookies\n [6] => urlParams\n [7] => parameters\n [8] => method\n [9] => requesttoken\n )\n\n [requestId:protected] => OC\\AppFramework\\Http\\RequestId Object\n (\n [secureRandom:protected] => OC\\Security\\SecureRandom Object\n (\n )\n\n [requestId:protected] => \n )\n\n [config:protected] => OC\\AllConfig Object\n (\n [connection:OC\\AllConfig:private] => \n [userCache:OC\\AllConfig:private] => OCP\\Cache\\CappedMemoryCache Object\n (\n [capacity:OCP\\Cache\\CappedMemoryCache:private] => 512\n [cache:OCP\\Cache\\CappedMemoryCache:private] => Array\n (\n )\n\n )\n\n [systemConfig:OC\\AllConfig:private] => OC\\SystemConfig Object\n (\n [sensitiveValues:protected] => Array\n (\n [instanceid] => 1\n [datadirectory] => 1\n [dbname] => 1\n [dbhost] => 1\n [dbpassword] => 1\n [dbuser] => 1\n [activity_dbname] => 1\n [activity_dbhost] => 1\n [activity_dbpassword] => 1\n [activity_dbuser] => 1\n [mail_from_address] => 1\n [mail_domain] => 1\n [mail_smtphost] => 1\n [mail_smtpname] => 1\n [mail_smtppassword] => 1\n [passwordsalt] => 1\n [secret] => 1\n [updater.secret] => 1\n [updater.server.url] => 1\n [trusted_proxies] => 1\n [preview_imaginary_url] => 1\n [proxyuserpwd] => 1\n [sentry.dsn] => 1\n [sentry.public-dsn] => 1\n [zammad.download.secret] => 1\n [zammad.portal.secret] => 1\n [zammad.secret] => 1\n [github.client_id] => 1\n [github.client_secret] => 1\n [log.condition] => Array\n (\n [shared_secret] => 1\n )\n\n [license-key] => 1\n [redis] => Array\n (\n [host] => 1\n [password] => 1\n )\n\n [redis.cluster] => Array\n (\n [seeds] => 1\n [password] => 1\n )\n\n [objectstore] => Array\n (\n [arguments] => Array\n (\n [options] => Array\n (\n [credentials] => Array\n (\n [key] => 1\n [secret] => 1\n )\n\n )\n\n [key] => 1\n [secret] => 1\n [username] => 1\n [password] => 1\n [user] => Array\n (\n [name] => 1\n [password] => 1\n )\n\n )\n\n )\n\n [objectstore_multibucket] => Array\n (\n [arguments] => Array\n (\n [options] => Array\n (\n [credentials] => Array\n (\n [key] => 1\n [secret] => 1\n )\n\n )\n\n [key] => 1\n [secret] => 1\n [username] => 1\n [password] => 1\n [user] => Array\n (\n [name] => 1\n [password] => 1\n )\n\n )\n\n )\n\n [onlyoffice] => Array\n (\n [jwt_secret] => 1\n )\n\n )\n\n [config:OC\\SystemConfig:private] => OC\\Config Object\n (\n [cache:protected] => Array\n (\n [htaccess.RewriteBase] => /\n [memcache.local] => \\OC\\Memcache\\APCu\n [apps_paths] => Array\n (\n [0] => Array\n (\n [path] => /var/www/html/apps\n [url] => /apps\n [writable] => \n )\n\n [1] => Array\n (\n [path] => /var/www/html/custom_apps\n [url] => /custom_apps\n [writable] => 1\n )\n\n )\n\n [upgrade.disable-web] => 1\n [passwordsalt] => vTtdPiLF5mxWWyNTVNbMrhBTE4rI3k\n [secret] => MIOTZa6oerl0vEQFEEKeQ0fWwMGDN2lb7cW6Yb1l3blYwmC9\n [trusted_domains] => Array\n (\n [0] => localhost\n )\n\n [datadirectory] => /var/www/html/data\n [dbtype] => mysql\n [version] => 29.0.1.1\n [overwrite.cli.url] => http://localhost\n [dbname] => nextcloud\n [dbhost] => mariadb-nc-1\n [dbport] => \n [dbtableprefix] => oc_\n [loglevel] => 0\n [trusted_proxies] => Array\n (\n [0] => 10.1.0.180\n )\n\n [overwritehost] => nc-1.nl\n [overwriteprotocol] => https\n [mysql.utf8mb4] => 1\n [dbuser] => nextcloud\n [dbpassword] => nextcloud\n [installed] => 1\n [instanceid] => oc0cys0f28e0\n )\n\n [envCache:protected] => Array\n (\n [HOSTNAME] => da5fe9de4559\n [PHP_VERSION] => 8.2.20\n [APACHE_CONFDIR] => /etc/apache2\n [NEXTCLOUD_VERSION] => 29.0.1\n [PHP_INI_DIR] => /usr/local/etc/php\n [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC\n [PHP_LDFLAGS] => -Wl,-O1 -pie\n [ADMIN_PASS] => passw\n [PWD] => /var/www/html\n [APACHE_LOG_DIR] => /var/log/apache2\n [PHP_MEMORY_LIMIT] => 512M\n [LANG] => C\n [APACHE_BODY_LIMIT] => 1073741824\n [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50\n [APACHE_PID_FILE] => /var/run/apache2/apache2.pid\n [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c\n [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31\n [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663\n [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz\n [APACHE_RUN_GROUP] => www-data\n [PHP_UPLOAD_LIMIT] => 512M\n [APACHE_LOCK_DIR] => /var/lock/apache2\n [SHLVL] => 0\n [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n [APACHE_RUN_DIR] => /var/run/apache2\n [APACHE_ENVVARS] => /etc/apache2/envvars\n [APACHE_RUN_USER] => www-data\n [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n [DEBUG] => true\n [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc\n [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n )\n\n [configDir:protected] => /var/www/html/config/\n [configFilePath:protected] => /var/www/html/config/config.php\n [configFileName:protected] => config.php\n [isReadOnly:protected] => \n )\n\n )\n\n )\n\n [csrfTokenManager:protected] => OC\\Security\\CSRF\\CsrfTokenManager Object\n (\n [sessionStorage:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\TokenStorage\\SessionStorage Object\n (\n [session:OC\\Security\\CSRF\\TokenStorage\\SessionStorage:private] => OC\\Session\\CryptoSessionData Object\n (\n [session:protected] => OC\\Session\\Internal Object\n (\n [sessionClosed:protected] => 1\n )\n\n [crypto:protected] => OC\\Security\\Crypto Object\n (\n [cipher:OC\\Security\\Crypto:private] => phpseclib\\Crypt\\AES Object\n (\n [mode] => 2\n [block_size] => 16\n [key] => ??\u0010?t\tL?\u001c?2.???\u001c\n [iv] => \u0013\u000f???[3}?\u001e????r\n [encryptIV] => \u0013\u000f???[3}?\u001e????r\n [decryptIV] => \u0013\u000f???[3}?\u001e????r\n [continuousBuffer] => \n [enbuffer] => Array\n (\n [ciphertext] => \n [xor] => \n [pos] => 0\n [enmcrypt_init] => 1\n )\n\n [debuffer] => Array\n (\n [ciphertext] => \n [xor] => \n [pos] => 0\n [enmcrypt_init] => 1\n )\n\n [enmcrypt] => \n [demcrypt] => \n [enchanged] => 1\n [dechanged] => 1\n [ecb] => \n [cfb_init_len] => 600\n [changed] => \n [padding] => 1\n [paddable] => 1\n [engine] => 3\n [preferredEngine] => \n [cipher_name_mcrypt] => rijndael-128\n [cipher_name_openssl] => aes-128-cbc\n [cipher_name_openssl_ecb] => aes-128-ecb\n [password_default_salt] => phpseclib\n [inline_crypt] => \n [use_inline_crypt] => 1\n [openssl_emulate_ctr] => \n [openssl_options] => 3\n [explicit_key_length] => \n [skip_key_adjustment] => \n [w] => \n [dw] => \n [Nb] => 4\n [key_length] => 16\n [Nk] => 4\n [Nr] => \n [c] => \n [kl] => \n )\n\n [ivLength:OC\\Security\\Crypto:private] => 16\n [config:OC\\Security\\Crypto:private] => OC\\AllConfig Object\n (\n [connection:OC\\AllConfig:private] => \n [userCache:OC\\AllConfig:private] => OCP\\Cache\\CappedMemoryCache Object\n (\n [capacity:OCP\\Cache\\CappedMemoryCache:private] => 512\n [cache:OCP\\Cache\\CappedMemoryCache:private] => Array\n (\n )\n\n )\n\n [systemConfig:OC\\AllConfig:private] => OC\\SystemConfig Object\n (\n [sensitiveValues:protected] => Array\n (\n [instanceid] => 1\n [datadirectory] => 1\n [dbname] => 1\n [dbhost] => 1\n [dbpassword] => 1\n [dbuser] => 1\n [activity_dbname] => 1\n [activity_dbhost] => 1\n [activity_dbpassword] => 1\n [activity_dbuser] => 1\n [mail_from_address] => 1\n [mail_domain] => 1\n [mail_smtphost] => 1\n [mail_smtpname] => 1\n [mail_smtppassword] => 1\n [passwordsalt] => 1\n [secret] => 1\n [updater.secret] => 1\n [updater.server.url] => 1\n [trusted_proxies] => 1\n [preview_imaginary_url] => 1\n [proxyuserpwd] => 1\n [sentry.dsn] => 1\n [sentry.public-dsn] => 1\n [zammad.download.secret] => 1\n [zammad.portal.secret] => 1\n [zammad.secret] => 1\n [github.client_id] => 1\n [github.client_secret] => 1\n [log.condition] => Array\n (\n [shared_secret] => 1\n )\n\n [license-key] => 1\n [redis] => Array\n (\n [host] => 1\n [password] => 1\n )\n\n [redis.cluster] => Array\n (\n [seeds] => 1\n [password] => 1\n )\n\n [objectstore] => Array\n (\n [arguments] => Array\n (\n [options] => Array\n (\n [credentials] => Array\n (\n [key] => 1\n [secret] => 1\n )\n\n )\n\n [key] => 1\n [secret] => 1\n [username] => 1\n [password] => 1\n [user] => Array\n (\n [name] => 1\n [password] => 1\n )\n\n )\n\n )\n\n [objectstore_multibucket] => Array\n (\n [arguments] => Array\n (\n [options] => Array\n (\n [credentials] => Array\n (\n [key] => 1\n [secret] => 1\n )\n\n )\n\n [key] => 1\n [secret] => 1\n [username] => 1\n [password] => 1\n [user] => Array\n (\n [name] => 1\n [password] => 1\n )\n\n )\n\n )\n\n [onlyoffice] => Array\n (\n [jwt_secret] => 1\n )\n\n )\n\n [config:OC\\SystemConfig:private] => OC\\Config Object\n (\n [cache:protected] => Array\n (\n [htaccess.RewriteBase] => /\n [memcache.local] => \\OC\\Memcache\\APCu\n [apps_paths] => Array\n (\n [0] => Array\n (\n [path] => /var/www/html/apps\n [url] => /apps\n [writable] => \n )\n\n [1] => Array\n (\n [path] => /var/www/html/custom_apps\n [url] => /custom_apps\n [writable] => 1\n )\n\n )\n\n [upgrade.disable-web] => 1\n [passwordsalt] => vTtdPiLF5mxWWyNTVNbMrhBTE4rI3k\n [secret] => MIOTZa6oerl0vEQFEEKeQ0fWwMGDN2lb7cW6Yb1l3blYwmC9\n [trusted_domains] => Array\n (\n [0] => localhost\n )\n\n [datadirectory] => /var/www/html/data\n [dbtype] => mysql\n [version] => 29.0.1.1\n [overwrite.cli.url] => http://localhost\n [dbname] => nextcloud\n [dbhost] => mariadb-nc-1\n [dbport] => \n [dbtableprefix] => oc_\n [loglevel] => 0\n [trusted_proxies] => Array\n (\n [0] => 10.1.0.180\n )\n\n [overwritehost] => nc-1.nl\n [overwriteprotocol] => https\n [mysql.utf8mb4] => 1\n [dbuser] => nextcloud\n [dbpassword] => nextcloud\n [installed] => 1\n [instanceid] => oc0cys0f28e0\n )\n\n [envCache:protected] => Array\n (\n [HOSTNAME] => da5fe9de4559\n [PHP_VERSION] => 8.2.20\n [APACHE_CONFDIR] => /etc/apache2\n [NEXTCLOUD_VERSION] => 29.0.1\n [PHP_INI_DIR] => /usr/local/etc/php\n [GPG_KEYS] => 39B641343D8C104B2B146DC3F9C39DC0B9698544 E60913E4DF209907D8E30D96659A97C9CF2A795A 1198C0117593497A5EC5C199286AF1F9897469DC\n [PHP_LDFLAGS] => -Wl,-O1 -pie\n [ADMIN_PASS] => passw\n [PWD] => /var/www/html\n [APACHE_LOG_DIR] => /var/log/apache2\n [PHP_MEMORY_LIMIT] => 512M\n [LANG] => C\n [APACHE_BODY_LIMIT] => 1073741824\n [PHP_SHA256] => 4474cc430febef6de7be958f2c37253e5524d5c5331a7e1765cd2d2234881e50\n [APACHE_PID_FILE] => /var/run/apache2/apache2.pid\n [PHPIZE_DEPS] => autoconf \t\tdpkg-dev \t\tfile \t\tg++ \t\tgcc \t\tlibc-dev \t\tmake \t\tpkg-config \t\tre2c\n [TEST_UUID_1] => c33056f9-2abf-4a1c-98d3-b579b1db8e31\n [TEST_UUID_2] => 5f23338a-b767-41e3-9233-1c1249444663\n [PHP_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz\n [APACHE_RUN_GROUP] => www-data\n [PHP_UPLOAD_LIMIT] => 512M\n [APACHE_LOCK_DIR] => /var/lock/apache2\n [SHLVL] => 0\n [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n [APACHE_RUN_DIR] => /var/run/apache2\n [APACHE_ENVVARS] => /etc/apache2/envvars\n [APACHE_RUN_USER] => www-data\n [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n [DEBUG] => true\n [PHP_ASC_URL] => https://www.php.net/distributions/php-8.2.20.tar.xz.asc\n [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64\n )\n\n [configDir:protected] => /var/www/html/config/\n [configFilePath:protected] => /var/www/html/config/config.php\n [configFileName:protected] => config.php\n [isReadOnly:protected] => \n )\n\n )\n\n )\n\n )\n\n [passphrase:protected] => 7Lalvsix5wllH+C7lDO0mKdJdb95ZSGDlV1r4msAD6h1r1ULWTaUT3l0cl0jsIjj80MYVlbDIz8K59vNDYvgkMeSi0+nwrGDgA1C926gsF6L4QcF2PC1aMBzoXmdir9v\n [sessionValues:protected] => Array\n (\n [LAST_ACTIVITY] => 1718637660\n [requesttoken] => SqFb8pQbZpHstA0N82m9OES/DcIqknKp\n [checkServer_succeeded] => 1\n )\n\n [isModified:protected] => \n )\n\n )\n\n [csrfToken:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\CsrfToken Object\n (\n [encryptedValue:OC\\Security\\CSRF\\CsrfToken:private] => Iq5Wua3TezVXBiWoVR5lkvpMEsvmpDJhOSWA1FDBSEE=:cd8Q25WjKlcNdm3bIV9V3MJ+f/Kp4WFOfUbJpTuvAzE=\n [value:OC\\Security\\CSRF\\CsrfToken:private] => SqFb8pQbZpHstA0N82m9OES/DcIqknKp\n )\n\n [tokenGenerator:OC\\Security\\CSRF\\CsrfTokenManager:private] => OC\\Security\\CSRF\\CsrfTokenGenerator Object\n (\n [random:OC\\Security\\CSRF\\CsrfTokenGenerator:private] => OC\\Security\\SecureRandom Object\n (\n )\n\n )\n\n )\n\n [contentDecoded:protected] => \n)\n \ No newline at end of file diff --git a/tests/docker/integration-tests/tests.sh b/tests/docker/integration-tests/tests.sh index 07c1d2c..e2fbb3a 100644 --- a/tests/docker/integration-tests/tests.sh +++ b/tests/docker/integration-tests/tests.sh @@ -4,7 +4,7 @@ echo Start Invitation app integration tests echo sleeping 60s ... giving owncloud time to startup && sleep 15 && -curl -u admin:passw -H 'OCS-APIRequest: true' http://nc-1.nl/ocs/v2.php/core/getapppassword +curl -u admin:${ADMIN_PASS} -H 'OCS-APIRequest: true' http://nc-1.nl/ocs/v2.php/core/getapppassword echo echo diff --git a/tests/docker/nc-1/Dockerfile-github b/tests/docker/nc-1/Dockerfile-github index 341049e..174c816 100644 --- a/tests/docker/nc-1/Dockerfile-github +++ b/tests/docker/nc-1/Dockerfile-github @@ -8,21 +8,24 @@ RUN apt update \ # it needs the certs from all mesh hosts COPY nc-1/nc-1.nl/certs/cert.pem /usr/share/ca-certificates/rd-mesh/nc-1.pem RUN echo 'rd-mesh/nc-1.pem' >> /etc/ca-certificates.conf \ - # && echo 'rd-mesh/oc-1.pem' >> /etc/ca-certificates.conf \ - && update-ca-certificates \ + && update-ca-certificates \ && export CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt # Add the Invitation app from repository RUN mkdir -p /tmp/invitation \ && git clone -b ${BRANCH} https://github.com/sara-nl/nc-invitation.git /tmp/invitation +# Add test run requirements: test data, test controller, test routes +RUN cp /tmp/invitation/tests/docker/integration-tests/Version20240209130007.php /tmp/invitation/lib/Migration \ + && cp /tmp/invitation/tests/docker/integration-tests/OcsController.php /tmp/invitation/lib/Controller \ + && mv /tmp/invitation/appinfo/routes.php /tmp/invitation/appinfo/app-routes.php \ + && cp /tmp/invitation/tests/docker/integration-tests/routes.php /tmp/invitation/appinfo/routes.php -RUN cp /tmp/invitation/tests/docker/integration-tests/Version20240209130007.php /tmp/invitation/lib/Migration -RUN cp /tmp/invitation/tests/docker/integration-tests/OcsController.php /tmp/invitation/lib/Controller - -# add pre install script +# add pre install script and make invitation app RUN cp -R /tmp/invitation/tests/docker/nc-1/before-starting.sh /docker-entrypoint-hooks.d/before-starting RUN chown -R www-data /docker-entrypoint-hooks.d/before-starting \ && chmod u+x /docker-entrypoint-hooks.d/before-starting/before-starting.sh \ + && cd /tmp/invitation \ + && make -e version=test buildapp-tests \ && chown -R www-data /tmp/invitation USER www-data diff --git a/tests/docker/nc-1/Dockerfile-local b/tests/docker/nc-1/Dockerfile-local index 26a8d6b..d068494 100644 --- a/tests/docker/nc-1/Dockerfile-local +++ b/tests/docker/nc-1/Dockerfile-local @@ -13,13 +13,18 @@ RUN echo 'rd-mesh/nc-1.pem' >> /etc/ca-certificates.conf \ RUN mkdir -p /tmp/invitation COPY . /tmp/invitation -RUN cp /tmp/invitation/tests/docker/integration-tests/Version20240209130007.php /tmp/invitation/lib/Migration -RUN cp /tmp/invitation/tests/docker/integration-tests/OcsController.php /tmp/invitation/lib/Controller +# Add test run requirements: test data, test controller, test routes +RUN cp /tmp/invitation/tests/docker/integration-tests/Version20240209130007.php /tmp/invitation/lib/Migration \ + && cp /tmp/invitation/tests/docker/integration-tests/OcsController.php /tmp/invitation/lib/Controller \ + && mv /tmp/invitation/appinfo/routes.php /tmp/invitation/appinfo/app-routes.php \ + && cp /tmp/invitation/tests/docker/integration-tests/routes.php /tmp/invitation/appinfo/routes.php -# add pre install script +# add pre install script and make invitation app RUN cp -R /tmp/invitation/tests/docker/nc-1/before-starting.sh /docker-entrypoint-hooks.d/before-starting RUN chown -R www-data /docker-entrypoint-hooks.d/before-starting \ && chmod u+x /docker-entrypoint-hooks.d/before-starting/before-starting.sh \ + && cd /tmp/invitation \ + && make -e version=test buildapp-tests \ && chown -R www-data /tmp/invitation USER www-data diff --git a/tests/docker/nc-1/before-starting.sh b/tests/docker/nc-1/before-starting.sh index d876d35..a32f539 100644 --- a/tests/docker/nc-1/before-starting.sh +++ b/tests/docker/nc-1/before-starting.sh @@ -8,15 +8,13 @@ status=$?; if [ $status -eq 1 ] then echo 'Setup nextcloud database'; - php /var/www/html/occ maintenance:install --database mysql --database-name nextcloud --database-host mariadb-nc-1 --database-user nextcloud --database-pass nextcloud --admin-user admin --admin-pass passw --admin-email admin@nc-1.nl; + php /var/www/html/occ maintenance:install --database mysql --database-name nextcloud --database-host mariadb-nc-1 --database-user nextcloud --database-pass nextcloud --admin-user admin --admin-pass ${ADMIN_PASS} --admin-email admin@nc-1.nl; # add necessary config.php settings sed -i "/^);/i 'loglevel' => 0, 'trusted_proxies' => [0 => '10.1.0.100'], 'overwritehost' => 'nc-1.nl', 'overwriteprotocol' => 'https'" /var/www/html/config/config.php; + + # Install the Invitation app echo 'Install Invitation app'; - cd /tmp/invitation; - make -e version=test buildapp-tests; tar xvf /tmp/invitation/build/artifacts/app/invitation_test.tar.gz -C /var/www/html/apps; - # mkdir /var/www/html/log; - # mv /var/www/html/apps/invitation/appinfo/routes.php /var/www/html/apps/invitation/appinfo/routes-main.php; php /var/www/html/occ app:enable invitation; else echo 'Nextcloud already installed' diff --git a/tests/phpunit.integration.xml b/tests/phpunit.integration.xml new file mode 100644 index 0000000..f261ba7 --- /dev/null +++ b/tests/phpunit.integration.xml @@ -0,0 +1,11 @@ + + + + + ./Integration + + + diff --git a/tests/phpunit.xml b/tests/phpunit.xml new file mode 100644 index 0000000..24c9444 --- /dev/null +++ b/tests/phpunit.xml @@ -0,0 +1,11 @@ + + + + + ./Unit + + +