mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-08-29 01:10:42 +08:00
Add legacy api re-direction
- Listen to legacy api calls on the LegacyRedirectListener - Add LegacyApiRedirectHandler to re-direct to legacy endpoint -- Using 307 re-direction response to support post re-direction -- Using api_paths.yaml with the configuration with paths to check - Setup API tests using codeception -- Add helper methods to login in v4 and v8 API - Add Api test to create account using v4 api - Add Api test to create account using v8 api - Add unit test for LegacyApiRedirectHandler
This commit is contained in:
parent
2a489cbc7e
commit
6c3e266b5d
18 changed files with 797 additions and 112 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -32,6 +32,8 @@ public/
|
|||
|
||||
# Tests
|
||||
tests/coverage
|
||||
tests/api.suite.yml
|
||||
tests/acceptance.suite.yml
|
||||
|
||||
# Composer
|
||||
vendor/
|
||||
|
@ -159,3 +161,4 @@ testem.log
|
|||
/.php_cs
|
||||
/.php_cs.cache
|
||||
###< friendsofphp/php-cs-fixer ###
|
||||
|
||||
|
|
|
@ -33,11 +33,12 @@
|
|||
},
|
||||
"require-dev": {
|
||||
"api-platform/schema-generator": "^2.2",
|
||||
"codeception/aspect-mock": "^3.1",
|
||||
"codeception/codeception": "^4.0",
|
||||
"codeception/module-asserts": "^1.1",
|
||||
"codeception/module-phpbrowser": "^1.0",
|
||||
"codeception/module-rest": "^1.2",
|
||||
"codeception/module-symfony": "^1.0",
|
||||
"codeception/aspect-mock": "^3.1",
|
||||
"dama/doctrine-test-bundle": "^5.0",
|
||||
"doctrine/doctrine-fixtures-bundle": "~3.2",
|
||||
"doctrine/doctrine-migrations-bundle": "^2.1",
|
||||
|
|
302
composer.lock
generated
302
composer.lock
generated
|
@ -1,20 +1,20 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "00f1adf41ad3121e7cfed51b3cc9cb8e",
|
||||
"packages": [
|
||||
{
|
||||
"name": "api-platform/api-pack",
|
||||
"version": "v1.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/api-platform/api-pack.git",
|
||||
"reference": "ca7ca22f30bcfcdb2493ec9e8b7b5dba1271608a"
|
||||
},
|
||||
"dist": {
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "756a56bc803aed095e3d1bc05b893eaa",
|
||||
"packages": [
|
||||
{
|
||||
"name": "api-platform/api-pack",
|
||||
"version": "v1.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/api-platform/api-pack.git",
|
||||
"reference": "ca7ca22f30bcfcdb2493ec9e8b7b5dba1271608a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/api-platform/api-pack/zipball/ca7ca22f30bcfcdb2493ec9e8b7b5dba1271608a",
|
||||
"reference": "ca7ca22f30bcfcdb2493ec9e8b7b5dba1271608a",
|
||||
|
@ -6141,26 +6141,77 @@
|
|||
"name": "Gintautas Miselis"
|
||||
}
|
||||
],
|
||||
"description": "Codeception module for testing web application over HTTP",
|
||||
"homepage": "http://codeception.com/",
|
||||
"keywords": [
|
||||
"codeception",
|
||||
"functional-testing",
|
||||
"http"
|
||||
],
|
||||
"time": "2019-10-10T14:25:59+00:00"
|
||||
"description": "Codeception module for testing web application over HTTP",
|
||||
"homepage": "http://codeception.com/",
|
||||
"keywords": [
|
||||
"codeception",
|
||||
"functional-testing",
|
||||
"http"
|
||||
],
|
||||
"time": "2019-10-10T14:25:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "codeception/module-symfony",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Codeception/module-symfony.git",
|
||||
"reference": "db1a281f183afbc63ba70fb16dee8730cc8875ba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Codeception/module-symfony/zipball/db1a281f183afbc63ba70fb16dee8730cc8875ba",
|
||||
{
|
||||
"name": "codeception/module-rest",
|
||||
"version": "1.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Codeception/module-rest.git",
|
||||
"reference": "c86417af517bb1fb5b88550455d823a7c9fc167e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Codeception/module-rest/zipball/c86417af517bb1fb5b88550455d823a7c9fc167e",
|
||||
"reference": "c86417af517bb1fb5b88550455d823a7c9fc167e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"codeception/codeception": "^4.0",
|
||||
"flow/jsonpath": "^0.5",
|
||||
"justinrainbow/json-schema": "^5.2.9",
|
||||
"php": ">=5.6.0 <8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/lib-innerbrowser": "^1.0",
|
||||
"codeception/util-robohelpers": "dev-master",
|
||||
"codeception/util-universalframework": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"aws/aws-sdk-php": "For using AWS Auth"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gintautas Miselis"
|
||||
}
|
||||
],
|
||||
"description": "REST module for Codeception",
|
||||
"homepage": "http://codeception.com/",
|
||||
"keywords": [
|
||||
"codeception",
|
||||
"rest"
|
||||
],
|
||||
"time": "2020-02-01T19:23:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "codeception/module-symfony",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Codeception/module-symfony.git",
|
||||
"reference": "db1a281f183afbc63ba70fb16dee8730cc8875ba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Codeception/module-symfony/zipball/db1a281f183afbc63ba70fb16dee8730cc8875ba",
|
||||
"reference": "db1a281f183afbc63ba70fb16dee8730cc8875ba",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -6624,26 +6675,67 @@
|
|||
"description": "EasyRdf is a PHP library designed to make it easy to consume and produce RDF.",
|
||||
"homepage": "http://www.easyrdf.org/",
|
||||
"keywords": [
|
||||
"Linked Data",
|
||||
"RDF",
|
||||
"Semantic Web",
|
||||
"Turtle",
|
||||
"rdfa",
|
||||
"sparql"
|
||||
"Linked Data",
|
||||
"RDF",
|
||||
"Semantic Web",
|
||||
"Turtle",
|
||||
"rdfa",
|
||||
"sparql"
|
||||
],
|
||||
"time": "2015-02-27T09:45:49+00:00"
|
||||
"time": "2015-02-27T09:45:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v2.16.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
|
||||
"reference": "c460a3cbaa58f983fe026cd52c45950bf61e9239"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/c460a3cbaa58f983fe026cd52c45950bf61e9239",
|
||||
{
|
||||
"name": "flow/jsonpath",
|
||||
"version": "0.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/FlowCommunications/JSONPath.git",
|
||||
"reference": "b9738858c75d008c1211612b973e9510f8b7f8ea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/FlowCommunications/JSONPath/zipball/b9738858c75d008c1211612b973e9510f8b7f8ea",
|
||||
"reference": "b9738858c75d008c1211612b973e9510f8b7f8ea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"peekmo/jsonpath": "dev-master",
|
||||
"phpunit/phpunit": "^7.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Flow\\JSONPath": "src/",
|
||||
"Flow\\JSONPath\\Test": "tests/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Stephen Frank",
|
||||
"email": "stephen@flowsa.com"
|
||||
}
|
||||
],
|
||||
"description": "JSONPath implementation for parsing, searching and flattening arrays",
|
||||
"time": "2019-07-15T17:23:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v2.16.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
|
||||
"reference": "c460a3cbaa58f983fe026cd52c45950bf61e9239"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/c460a3cbaa58f983fe026cd52c45950bf61e9239",
|
||||
"reference": "c460a3cbaa58f983fe026cd52c45950bf61e9239",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -7078,26 +7170,92 @@
|
|||
}
|
||||
],
|
||||
"description": "Lexing and parsing in pure PHP",
|
||||
"homepage": "https://github.com/jakubledl/dissect",
|
||||
"keywords": [
|
||||
"ast",
|
||||
"lexing",
|
||||
"parser",
|
||||
"parsing"
|
||||
],
|
||||
"time": "2013-01-29T21:29:14+00:00"
|
||||
"homepage": "https://github.com/jakubledl/dissect",
|
||||
"keywords": [
|
||||
"ast",
|
||||
"lexing",
|
||||
"parser",
|
||||
"parsing"
|
||||
],
|
||||
"time": "2013-01-29T21:29:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/html-to-markdown",
|
||||
"version": "4.9.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/html-to-markdown.git",
|
||||
"reference": "1dcd0f85de786f46a7f224a27cc3d709ddd2a68c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/1dcd0f85de786f46a7f224a27cc3d709ddd2a68c",
|
||||
{
|
||||
"name": "justinrainbow/json-schema",
|
||||
"version": "5.2.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/justinrainbow/json-schema.git",
|
||||
"reference": "44c6787311242a979fa15c704327c20e7221a0e4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/44c6787311242a979fa15c704327c20e7221a0e4",
|
||||
"reference": "44c6787311242a979fa15c704327c20e7221a0e4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1",
|
||||
"json-schema/json-schema-test-suite": "1.2.0",
|
||||
"phpunit/phpunit": "^4.8.35"
|
||||
},
|
||||
"bin": [
|
||||
"bin/validate-json"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"JsonSchema\\": "src/JsonSchema/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Bruno Prieto Reis",
|
||||
"email": "bruno.p.reis@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Justin Rainbow",
|
||||
"email": "justin.rainbow@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Igor Wiedler",
|
||||
"email": "igor@wiedler.ch"
|
||||
},
|
||||
{
|
||||
"name": "Robert Schönthal",
|
||||
"email": "seroscho@googlemail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library to validate a json schema.",
|
||||
"homepage": "https://github.com/justinrainbow/json-schema",
|
||||
"keywords": [
|
||||
"json",
|
||||
"schema"
|
||||
],
|
||||
"time": "2019-09-25T14:49:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/html-to-markdown",
|
||||
"version": "4.9.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/html-to-markdown.git",
|
||||
"reference": "1dcd0f85de786f46a7f224a27cc3d709ddd2a68c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/1dcd0f85de786f46a7f224a27cc3d709ddd2a68c",
|
||||
"reference": "1dcd0f85de786f46a7f224a27cc3d709ddd2a68c",
|
||||
"shasum": ""
|
||||
},
|
||||
|
|
|
@ -27,6 +27,7 @@ services:
|
|||
$legacyActionNameMap: '%legacy.action_name_map%'
|
||||
$menuItemMap: '%legacy.menu_item_map%'
|
||||
$legacyAssetPaths: '%legacy.asset_paths%'
|
||||
$legacyApiPaths: '%legacy.api_paths%'
|
||||
$exposedUserPreferences: '%legacy.exposed_user_preferences%'
|
||||
$themeImagePaths: '%themes.image_paths%'
|
||||
$themeImageSupportedTypes: '%themes.image_supported_types%'
|
||||
|
|
6
config/services/legacy/api_paths.yaml
Normal file
6
config/services/legacy/api_paths.yaml
Normal file
|
@ -0,0 +1,6 @@
|
|||
parameters:
|
||||
legacy.api_paths:
|
||||
Api/access_token: Api/index.php/access_token
|
||||
Api/V8: Api/index.php/V8
|
||||
Api: Api/index.php
|
||||
service/v4_1: service/v4_1
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
namespace App\EventListener;
|
||||
|
||||
use App\Service\LegacyAssetHandler;
|
||||
use App\Service\LegacyApiRedirectHandler;
|
||||
use App\Service\LegacyAssetRedirectHandler;
|
||||
use App\Service\RouteConverter;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
|
@ -19,19 +20,29 @@ class LegacyRedirectListener
|
|||
private $routeConverter;
|
||||
|
||||
/**
|
||||
* @var LegacyAssetHandler
|
||||
* @var LegacyAssetRedirectHandler
|
||||
*/
|
||||
private $legacyAssetHandler;
|
||||
|
||||
/**
|
||||
* @var LegacyApiRedirectHandler
|
||||
*/
|
||||
private $legacyApiRedirectHandler;
|
||||
|
||||
/**
|
||||
* LegacyRedirectListener constructor.
|
||||
* @param RouteConverter $routeConverter
|
||||
* @param LegacyAssetHandler $legacyAssetHandler
|
||||
* @param LegacyAssetRedirectHandler $legacyAssetHandler
|
||||
* @param LegacyApiRedirectHandler $legacyApiRedirectHandler
|
||||
*/
|
||||
public function __construct(RouteConverter $routeConverter, LegacyAssetHandler $legacyAssetHandler)
|
||||
{
|
||||
public function __construct(
|
||||
RouteConverter $routeConverter,
|
||||
LegacyAssetRedirectHandler $legacyAssetHandler,
|
||||
LegacyApiRedirectHandler $legacyApiRedirectHandler
|
||||
) {
|
||||
$this->routeConverter = $routeConverter;
|
||||
$this->legacyAssetHandler = $legacyAssetHandler;
|
||||
$this->legacyApiRedirectHandler = $legacyApiRedirectHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,6 +59,14 @@ class LegacyRedirectListener
|
|||
return;
|
||||
}
|
||||
|
||||
if ($this->isLegacyApi($event)) {
|
||||
$url = $this->legacyApiRedirectHandler->convert($event->getRequest());
|
||||
$response = new RedirectResponse($url, 307);
|
||||
$event->setResponse($response);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->isConvertible($event)) {
|
||||
$url = $this->routeConverter->convert($event->getRequest());
|
||||
$response = new RedirectResponse($url);
|
||||
|
@ -72,6 +91,16 @@ class LegacyRedirectListener
|
|||
*/
|
||||
protected function isLegacyAsset(RequestEvent $event): bool
|
||||
{
|
||||
return $this->legacyAssetHandler->isLegacyAssetRequest($event->getRequest());
|
||||
return $this->legacyAssetHandler->isAssetRequest($event->getRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it is legacy api requests
|
||||
* @param RequestEvent $event
|
||||
* @return bool
|
||||
*/
|
||||
protected function isLegacyApi(RequestEvent $event): bool
|
||||
{
|
||||
return $this->legacyApiRedirectHandler->isApiRequest($event->getRequest());
|
||||
}
|
||||
}
|
54
core/src/Service/LegacyApiRedirectHandler.php
Normal file
54
core/src/Service/LegacyApiRedirectHandler.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class LegacyApiRedirectHandler extends LegacyRedirectHandler
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $legacyApiPaths;
|
||||
|
||||
/**
|
||||
* LegacyApiRedirectHandler constructor.
|
||||
* @param array $legacyApiPaths
|
||||
* @param String $legacyPath
|
||||
*/
|
||||
public function __construct(array $legacyApiPaths, String $legacyPath)
|
||||
{
|
||||
parent::__construct($legacyPath);
|
||||
$this->legacyApiPaths = $legacyApiPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given $request is a legacy api request
|
||||
*
|
||||
* @param Request $request
|
||||
* @return bool
|
||||
*/
|
||||
public function isApiRequest(Request $request): bool
|
||||
{
|
||||
return $this->inPathList($request, array_keys($this->legacyApiPaths));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert given $request route
|
||||
*
|
||||
* @param Request $request
|
||||
* @return string
|
||||
*/
|
||||
public function convert(Request $request): string
|
||||
{
|
||||
$legacyPath = parent::convert($request);
|
||||
|
||||
foreach ($this->legacyApiPaths as $path => $replace) {
|
||||
if ($this->inPath($request, $path)) {
|
||||
return str_replace($path, $replace, $legacyPath);
|
||||
}
|
||||
}
|
||||
|
||||
return $legacyPath;
|
||||
}
|
||||
}
|
35
core/src/Service/LegacyAssetRedirectHandler.php
Normal file
35
core/src/Service/LegacyAssetRedirectHandler.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class LegacyAssetRedirectHandler extends LegacyRedirectHandler
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $legacyAssetPaths;
|
||||
|
||||
/**
|
||||
* LegacyAssetRedirectHandler constructor.
|
||||
* @param array $legacyAssetPaths
|
||||
* @param String $legacyPath
|
||||
*/
|
||||
public function __construct(array $legacyAssetPaths, String $legacyPath)
|
||||
{
|
||||
parent::__construct($legacyPath);
|
||||
$this->legacyAssetPaths = $legacyAssetPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given $request is a legacy asset request
|
||||
*
|
||||
* @param Request $request
|
||||
* @return bool
|
||||
*/
|
||||
public function isAssetRequest(Request $request): bool
|
||||
{
|
||||
return $this->inPathList($request, $this->legacyAssetPaths);
|
||||
}
|
||||
}
|
|
@ -1,58 +1,59 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class LegacyAssetHandler
|
||||
class LegacyRedirectHandler
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $legacyAssetPaths;
|
||||
/**
|
||||
* @var String
|
||||
*/
|
||||
private $legacyPath;
|
||||
protected $legacyPath;
|
||||
|
||||
/**
|
||||
* LegacyAssetHandler constructor.
|
||||
* @param array $legacyAssetPaths
|
||||
* LegacyRedirectHandler constructor.
|
||||
* @param String $legacyPath
|
||||
*/
|
||||
public function __construct(array $legacyAssetPaths, String $legacyPath)
|
||||
public function __construct(String $legacyPath)
|
||||
{
|
||||
$this->legacyAssetPaths = $legacyAssetPaths;
|
||||
$this->legacyPath = $legacyPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given $request is a legacy asset request
|
||||
* Check if given request falls into one of the given $paths
|
||||
*
|
||||
* @param Request $request
|
||||
* @param array $paths
|
||||
* @return bool
|
||||
*/
|
||||
public function isLegacyAssetRequest(Request $request): bool
|
||||
protected function inPathList(Request $request, array $paths): bool
|
||||
{
|
||||
if (empty($request->getPathInfo()) || $request->getPathInfo() === '/') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pathParts = explode('/', $request->getPathInfo());
|
||||
|
||||
if (empty($pathParts) || empty($pathParts[1])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (in_array($pathParts[1], $this->legacyAssetPaths)) {
|
||||
return true;
|
||||
foreach ($paths as $path) {
|
||||
if ($this->inPath($request, $path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if request falls into given path
|
||||
*
|
||||
* @param Request $request
|
||||
* @param $path
|
||||
* @return bool
|
||||
*/
|
||||
protected function inPath(Request $request, $path): bool
|
||||
{
|
||||
return strpos($request->getPathInfo(), '/' . $path) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert given $request route
|
||||
*
|
||||
|
@ -68,4 +69,4 @@ class LegacyAssetHandler
|
|||
|
||||
return $request->getBaseUrl() . $this->legacyPath . $request->getPathInfo() . $queryString;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -63,6 +63,9 @@
|
|||
"codeception/module-phpbrowser": {
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"codeception/module-rest": {
|
||||
"version": "1.2.0"
|
||||
},
|
||||
"codeception/module-symfony": {
|
||||
"version": "1.0.0"
|
||||
},
|
||||
|
@ -188,6 +191,9 @@
|
|||
"fig/link-util": {
|
||||
"version": "1.1.0"
|
||||
},
|
||||
"flow/jsonpath": {
|
||||
"version": "0.5.0"
|
||||
},
|
||||
"friendsofphp/php-cs-fixer": {
|
||||
"version": "2.2",
|
||||
"recipe": {
|
||||
|
@ -221,6 +227,9 @@
|
|||
"jdorn/sql-formatter": {
|
||||
"version": "v1.2.17"
|
||||
},
|
||||
"justinrainbow/json-schema": {
|
||||
"version": "5.2.9"
|
||||
},
|
||||
"league/html-to-markdown": {
|
||||
"version": "4.9.1"
|
||||
},
|
||||
|
|
130
tests/_support/ApiTester.php
Normal file
130
tests/_support/ApiTester.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
namespace App\Tests;
|
||||
|
||||
use Codeception\Actor;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Inherited Methods
|
||||
* @method void wantToTest($text)
|
||||
* @method void wantTo($text)
|
||||
* @method void execute($callable)
|
||||
* @method void expectTo($prediction)
|
||||
* @method void expect($prediction)
|
||||
* @method void amGoingTo($argumentation)
|
||||
* @method void am($role)
|
||||
* @method void lookForwardTo($achieveValue)
|
||||
* @method void comment($description)
|
||||
* @method void pause()
|
||||
*
|
||||
* @SuppressWarnings(PHPMD)
|
||||
*/
|
||||
class ApiTester extends Actor
|
||||
{
|
||||
use _generated\ApiTesterActions;
|
||||
|
||||
/**
|
||||
* Define custom actions here
|
||||
*/
|
||||
|
||||
/**
|
||||
* Login on V8 API
|
||||
* @param string $clientId
|
||||
* @param string $clientSecret
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function v8Login(string $clientId, string $clientSecret): string
|
||||
{
|
||||
$this->sendPOST($this->getV8Path('/access_token'), [
|
||||
'grant_type' => 'client_credentials',
|
||||
'scope' => '',
|
||||
'client_id' => $clientId,
|
||||
'client_secret' => $clientSecret
|
||||
]);
|
||||
|
||||
$token = $this->grabDataFromResponseByJsonPath('$.access_token');
|
||||
|
||||
return $token[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Login on v4 API
|
||||
* @param string $user
|
||||
* @param string $password
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function v4Login(string $user, string $password): string
|
||||
{
|
||||
$userAuth = [
|
||||
'user_name' => $user,
|
||||
'password' => md5($password),
|
||||
];
|
||||
$appName = 'test';
|
||||
$nameValueList = [];
|
||||
|
||||
$args = [
|
||||
'user_auth' => $userAuth,
|
||||
'application_name' => $appName,
|
||||
'name_value_list' => $nameValueList
|
||||
];
|
||||
|
||||
$result = $this->v4Request('login', $args);
|
||||
|
||||
return $result['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Do v4 rest api request
|
||||
* @param string $method
|
||||
* @param array $arguments
|
||||
* @return mixed
|
||||
*/
|
||||
public function v4Request(string $method, array $arguments)
|
||||
{
|
||||
$postData = array(
|
||||
'method' => $method,
|
||||
'input_type' => 'JSON',
|
||||
'response_type' => 'JSON',
|
||||
'rest_data' => json_encode($arguments),
|
||||
);
|
||||
|
||||
$this->sendPOST($this->getV4Path(), $postData);
|
||||
|
||||
$response = $this->grabResponse();
|
||||
|
||||
return json_decode($response, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get v4 path
|
||||
* @return string
|
||||
*/
|
||||
public function getV4Path(): string
|
||||
{
|
||||
return '/service/v4_1/rest.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get v8 path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public function getV8Path(string $path): string
|
||||
{
|
||||
return "/Api$path";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get uuid type check string
|
||||
* @return string
|
||||
*/
|
||||
public function getUuidJsonType(): string
|
||||
{
|
||||
$uuidRegex = '[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}';
|
||||
|
||||
return "string:regex(~$uuidRegex~)";
|
||||
}
|
||||
}
|
11
tests/_support/Helper/Api.php
Normal file
11
tests/_support/Helper/Api.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App\Tests\Helper;
|
||||
|
||||
// here you can define custom actions
|
||||
// all public methods declared in helper class will be available in $I
|
||||
|
||||
class Api extends \Codeception\Module
|
||||
{
|
||||
|
||||
}
|
12
tests/api.suite.dist.yml
Normal file
12
tests/api.suite.dist.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
actor: ApiTester
|
||||
modules:
|
||||
enabled:
|
||||
- \App\Tests\Helper\Api
|
||||
- REST:
|
||||
url: http://<suite-endpoint>
|
||||
depends: PhpBrowser
|
||||
- \App\Tests\Helper\ConfigHelper:
|
||||
client_id: <legacy-suite-client-id>
|
||||
client_secret: <legacy-suite-client-secret>
|
||||
user_name: <user-name>
|
||||
password: <password>
|
58
tests/api/v4/V4ApiAccountsCest.php
Normal file
58
tests/api/v4/V4ApiAccountsCest.php
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php namespace App\Tests;
|
||||
|
||||
use Codeception\Util\HttpCode;
|
||||
use Exception;
|
||||
|
||||
class V4ApiAccountsCest
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $session;
|
||||
|
||||
/**
|
||||
* @param ApiTester $I
|
||||
* @throws Exception
|
||||
*/
|
||||
public function _before(ApiTester $I): void
|
||||
{
|
||||
$this->session = $I->v4Login($I->getConfig('user_name'), $I->getConfig('password'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test account record creation
|
||||
* @param ApiTester $I
|
||||
*/
|
||||
public function create(ApiTester $I): void
|
||||
{
|
||||
|
||||
$entryArgs = array(
|
||||
'session' => $this->session,
|
||||
'module_name' => 'Accounts',
|
||||
'name_value_list' => [
|
||||
'name' => 'V4 Api test Account'
|
||||
],
|
||||
'track_view' => false
|
||||
);
|
||||
|
||||
$I->v4Request('set_entry', $entryArgs);
|
||||
|
||||
$I->seeResponseCodeIs(HttpCode::OK); // 200
|
||||
$I->seeResponseIsJson();
|
||||
|
||||
$uuidTypeCheck = $I->getUuidJsonType();
|
||||
|
||||
$I->seeResponseMatchesJsonType([
|
||||
'id' => $uuidTypeCheck,
|
||||
]);
|
||||
|
||||
$I->seeResponseContainsJson([
|
||||
'entry_list' => [
|
||||
'name' => [
|
||||
'name' => 'name',
|
||||
'value' => 'V4 Api test Account'
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
57
tests/api/v8/V8ApiAccountsCest.php
Normal file
57
tests/api/v8/V8ApiAccountsCest.php
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php namespace App\Tests;
|
||||
|
||||
use Codeception\Util\HttpCode;
|
||||
use Exception;
|
||||
|
||||
class V8ApiAccountsCest
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $token;
|
||||
|
||||
/**
|
||||
* @param ApiTester $I
|
||||
* @throws Exception
|
||||
*/
|
||||
public function _before(ApiTester $I): void
|
||||
{
|
||||
$this->token = $I->v8Login($I->getConfig('client_id'), $I->getConfig('client_secret'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test account record creation
|
||||
* @param ApiTester $I
|
||||
*/
|
||||
public function create(ApiTester $I): void
|
||||
{
|
||||
|
||||
$I->amBearerAuthenticated($this->token);
|
||||
$I->sendPOST($I->getV8Path('/V8/module'), [
|
||||
'data' => [
|
||||
'type' => 'Accounts',
|
||||
'attributes' => [
|
||||
'name' => 'V8 Api test Account'
|
||||
]
|
||||
]
|
||||
]);
|
||||
$I->seeResponseCodeIs(HttpCode::CREATED); // 200
|
||||
$I->seeResponseIsJson();
|
||||
|
||||
$uuidTypeCheck = $I->getUuidJsonType();
|
||||
|
||||
$I->seeResponseContainsJson([
|
||||
'type' => 'Account',
|
||||
]);
|
||||
|
||||
$I->seeResponseMatchesJsonType([
|
||||
'data' => [
|
||||
'id' => $uuidTypeCheck,
|
||||
]
|
||||
]);
|
||||
|
||||
$I->seeResponseContainsJson([
|
||||
'name' => 'V8 Api test Account'
|
||||
]);
|
||||
}
|
||||
}
|
120
tests/unit/core/src/Service/LegacyApiRedirectHandlerTest.php
Normal file
120
tests/unit/core/src/Service/LegacyApiRedirectHandlerTest.php
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?php namespace App\Tests;
|
||||
|
||||
use App\Service\LegacyApiRedirectHandler;
|
||||
use Codeception\Test\Unit;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class LegacyApiRedirectHandlerTest extends Unit
|
||||
{
|
||||
/**
|
||||
* @var UnitTester
|
||||
*/
|
||||
protected $tester;
|
||||
|
||||
|
||||
/**
|
||||
* @var LegacyApiRedirectHandler
|
||||
*/
|
||||
private $legacyApiHandler;
|
||||
|
||||
protected function _before(): void
|
||||
{
|
||||
$legacyAssetPaths = [
|
||||
'Api/access_token' => 'Api/index.php/access_token',
|
||||
'Api/V8' => 'Api/index.php/V8',
|
||||
'Api' => 'Api/index.php',
|
||||
'service/v4_1' => 'service/v4_1'
|
||||
];
|
||||
|
||||
$this->legacyApiHandler = new LegacyApiRedirectHandler($legacyAssetPaths, '/legacy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test api request check with suite 8 api call
|
||||
*/
|
||||
public function testAPIRequestCheckWithSuite8Call(): void
|
||||
{
|
||||
$queryParams = [
|
||||
];
|
||||
|
||||
$serverParams = [
|
||||
'REDIRECT_BASE' => '/suiteinstance',
|
||||
'BASE' => '/suiteinstance',
|
||||
'HTTP_HOST' => 'localhost',
|
||||
'HTTP_ORIGIN' => 'http://localhost',
|
||||
'HTTP_REFERER' => 'http://localhost/suiteinstance/public/docs/graphql-playground/index.html',
|
||||
'SERVER_NAME' => 'localhost',
|
||||
'REDIRECT_URL' => '/suiteinstance/api/graphql',
|
||||
'REQUEST_METHOD' => 'POST',
|
||||
'REQUEST_URI' => '/suiteinstance/api/graphql',
|
||||
'SCRIPT_FILENAME' => '/var/www/html/suiteinstance/index.php',
|
||||
'SCRIPT_NAME' => '/suiteinstance/index.php',
|
||||
'PHP_SELF' => '/suiteinstance/index.php',
|
||||
];
|
||||
|
||||
$request = new Request($queryParams, [], [], [], [], $serverParams);
|
||||
|
||||
$valid = $this->legacyApiHandler->isApiRequest($request);
|
||||
|
||||
static::assertFalse($valid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test valid legacy api call check
|
||||
*/
|
||||
public function testValidLegacyApiPathRequestCheck(): void
|
||||
{
|
||||
$queryParams = [
|
||||
];
|
||||
|
||||
$serverParams = [
|
||||
'BASE' => '/suiteinstance',
|
||||
'HTTP_HOST' => 'localhost',
|
||||
'SERVER_NAME' => 'localhost',
|
||||
'REDIRECT_URL' => '/suiteinstance/',
|
||||
'REDIRECT_QUERY_STRING' => '',
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'QUERY_STRING' => '',
|
||||
'SCRIPT_FILENAME' => '/var/www/html/suiteinstance/index.php',
|
||||
'REQUEST_URI' => '/suiteinstance/Api/access_token',
|
||||
'SCRIPT_NAME' => '/suiteinstance/index.php',
|
||||
'PHP_SELF' => '/suiteinstance/index.php'
|
||||
];
|
||||
|
||||
$request = new Request($queryParams, [], [], [], [], $serverParams);
|
||||
|
||||
$valid = $this->legacyApiHandler->isApiRequest($request);
|
||||
|
||||
static::assertTrue($valid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test valid legacy api call path conversion
|
||||
*/
|
||||
public function testValidLegacyApiPathConversion(): void
|
||||
{
|
||||
$resultingRoute = '/suiteinstance/legacy/Api/index.php/access_token';
|
||||
$queryParams = [
|
||||
];
|
||||
|
||||
$serverParams = [
|
||||
'BASE' => '/suiteinstance',
|
||||
'HTTP_HOST' => 'localhost',
|
||||
'SERVER_NAME' => 'localhost',
|
||||
'REDIRECT_URL' => '/suiteinstance/',
|
||||
'REDIRECT_QUERY_STRING' => '',
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'QUERY_STRING' => '',
|
||||
'SCRIPT_FILENAME' => '/var/www/html/suiteinstance/index.php',
|
||||
'REQUEST_URI' => '/suiteinstance/Api/access_token',
|
||||
'SCRIPT_NAME' => '/suiteinstance/index.php',
|
||||
'PHP_SELF' => '/suiteinstance/index.php'
|
||||
];
|
||||
|
||||
$request = new Request($queryParams, [], [], [], [], $serverParams);
|
||||
|
||||
$route = $this->legacyApiHandler->convert($request);
|
||||
|
||||
static::assertEquals($resultingRoute, $route);
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
<?php namespace App\Tests;
|
||||
|
||||
use App\Service\LegacyAssetHandler;
|
||||
use App\Service\LegacyAssetRedirectHandler;
|
||||
use \Codeception\Test\Unit;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class LegacyAssetHandlerTest extends Unit
|
||||
class LegacyAssetRedirectHandlerTest extends Unit
|
||||
{
|
||||
/**
|
||||
* @var UnitTester
|
||||
|
@ -13,11 +13,11 @@ class LegacyAssetHandlerTest extends Unit
|
|||
|
||||
|
||||
/**
|
||||
* @var LegacyAssetHandler
|
||||
* @var LegacyAssetRedirectHandler
|
||||
*/
|
||||
private $legacyAssetHandler;
|
||||
|
||||
protected function _before()
|
||||
protected function _before(): void
|
||||
{
|
||||
$legacyAssetPaths = [
|
||||
'cache',
|
||||
|
@ -25,10 +25,10 @@ class LegacyAssetHandlerTest extends Unit
|
|||
'themes'
|
||||
];
|
||||
|
||||
$this->legacyAssetHandler = new LegacyAssetHandler($legacyAssetPaths, '/legacy');
|
||||
$this->legacyAssetHandler = new LegacyAssetRedirectHandler($legacyAssetPaths, '/legacy');
|
||||
}
|
||||
|
||||
public function testAPIRequestCheck()
|
||||
public function testAPIRequestCheck(): void
|
||||
{
|
||||
$queryParams = [
|
||||
];
|
||||
|
@ -50,12 +50,12 @@ class LegacyAssetHandlerTest extends Unit
|
|||
|
||||
$request = new Request($queryParams, [], [], [], [], $serverParams);
|
||||
|
||||
$valid = $this->legacyAssetHandler->isLegacyAssetRequest($request);
|
||||
$valid = $this->legacyAssetHandler->isAssetRequest($request);
|
||||
|
||||
static::assertFalse($valid);
|
||||
}
|
||||
|
||||
public function testLegacyValidAssetPathRequestCheck()
|
||||
public function testLegacyValidAssetPathRequestCheck(): void
|
||||
{
|
||||
$queryParams = [
|
||||
'v' => 'Y0_lwfeIA-XvM4ey09-htw',
|
||||
|
@ -77,12 +77,12 @@ class LegacyAssetHandlerTest extends Unit
|
|||
|
||||
$request = new Request($queryParams, [], [], [], [], $serverParams);
|
||||
|
||||
$valid = $this->legacyAssetHandler->isLegacyAssetRequest($request);
|
||||
$valid = $this->legacyAssetHandler->isAssetRequest($request);
|
||||
|
||||
static::assertTrue($valid);
|
||||
}
|
||||
|
||||
public function testValidLegacyAssetPathConvertion()
|
||||
public function testValidLegacyAssetPathConversion(): void
|
||||
{
|
||||
$resultingRoute = '/suiteinstance/legacy/themes/default/images/company_logo.png?v=Y0_lwfeIA-XvM4ey09-htw';
|
||||
$queryParams = [
|
Loading…
Add table
Add a link
Reference in a new issue