diff --git a/.gitattributes b/.gitattributes
index 80102b6f..53b0a935 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -5,8 +5,6 @@
/module/CLI/test-resources export-ignore
/module/Core/test export-ignore
/module/Core/test-db export-ignore
-/module/PreviewGenerator/test export-ignore
-/module/PreviewGenerator/test-db export-ignore
/module/Rest/test export-ignore
/module/Rest/test-api export-ignore
.gitattributes export-ignore
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e89d44c6..23fc1f61 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this
* [#429](https://github.com/shlinkio/shlink/issues/429) Dropped support for PHP 7.2 and 7.3
+* [#229](https://github.com/shlinkio/shlink/issues/229) Remove everything which was deprecated, including:
+
+ * Preview generation feature completely removed.
+ * Authentication against REST API using JWT is no longer supported.
+
+ See [UPGRADING doc](UPGRADING.md) in order to get details on how to migrate to this version.
+
#### Fixed
* *Nothing*
diff --git a/README.md b/README.md
index 9d0911c6..d5201276 100644
--- a/README.md
+++ b/README.md
@@ -215,12 +215,6 @@ Those tasks can be performed using shlink's CLI tool, so it should be easy to sc
> You don't need this if you use Shlink v1.17.0 or newer, since now it downloads/updates the geolocation database automatically just before trying to use it.
-* Generate website previews: `/path/to/shlink/bin/cli short-url:process-previews`
-
- Running this will improve the performance of the `doma.in/abc123/preview` URLs, which return a preview of the site.
-
- > **Important!** Generating previews is considered deprecated and the feature will be removed in Shlink v2.
-
*Any of these commands accept the `-q` flag, which makes it not display any output. This is recommended when configuring the commands as cron jobs.*
## Update to new version
@@ -274,33 +268,28 @@ Options:
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
Available commands:
- help Displays help for a command
- list Lists commands
+ help Displays help for a command
+ list Lists commands
api-key
- api-key:disable Disables an API key.
- api-key:generate Generates a new valid API key.
- api-key:list Lists all the available API keys.
- config
- config:generate-charset [DEPRECATED] Generates a character set sample just by shuffling the default one, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ". Then it can be set in the SHORTCODE_CHARS environment variable
- config:generate-secret [DEPRECATED] Generates a random secret string that can be used for JWT token encryption
+ api-key:disable Disables an API key.
+ api-key:generate Generates a new valid API key.
+ api-key:list Lists all the available API keys.
db
- db:create Creates the database needed for shlink to work. It will do nothing if the database already exists
- db:migrate Runs database migrations, which will ensure the shlink database is up to date.
+ db:create Creates the database needed for shlink to work. It will do nothing if the database already exists
+ db:migrate Runs database migrations, which will ensure the shlink database is up to date.
short-url
- short-url:delete [short-code:delete] Deletes a short URL
- short-url:generate [shortcode:generate|short-code:generate] Generates a short URL for provided long URL and returns it
- short-url:list [shortcode:list|short-code:list] List all short URLs
- short-url:parse [shortcode:parse|short-code:parse] Returns the long URL behind a short code
- short-url:process-previews [shortcode:process-previews|short-code:process-previews] [DEPRECATED] Processes and generates the previews for every URL, improving performance for later web requests.
- short-url:visits [shortcode:visits|short-code:visits] Returns the detailed visits information for provided short code
+ short-url:delete Deletes a short URL
+ short-url:generate Generates a short URL for provided long URL and returns it
+ short-url:list List all short URLs
+ short-url:parse Returns the long URL behind a short code
+ short-url:visits Returns the detailed visits information for provided short code
tag
- tag:create Creates one or more tags.
- tag:delete Deletes one or more tags.
- tag:list Lists existing tags.
- tag:rename Renames one existing tag.
+ tag:create Creates one or more tags.
+ tag:delete Deletes one or more tags.
+ tag:list Lists existing tags.
+ tag:rename Renames one existing tag.
visit
- visit:locate [visit:process] Resolves visits origin locations.
- visit:update-db [DEPRECATED] Updates the GeoLite2 database file used to geolocate IP addresses
+ visit:locate Resolves visits origin locations.
```
> This product includes GeoLite2 data created by MaxMind, available from [https://www.maxmind.com](https://www.maxmind.com)
diff --git a/bin/wkhtmltoimage b/bin/wkhtmltoimage
deleted file mode 100755
index 1459957b..00000000
Binary files a/bin/wkhtmltoimage and /dev/null differ
diff --git a/composer.json b/composer.json
index 2f33ce98..0b2c1d93 100644
--- a/composer.json
+++ b/composer.json
@@ -71,8 +71,7 @@
"psr-4": {
"Shlinkio\\Shlink\\CLI\\": "module/CLI/src",
"Shlinkio\\Shlink\\Rest\\": "module/Rest/src",
- "Shlinkio\\Shlink\\Core\\": "module/Core/src",
- "Shlinkio\\Shlink\\PreviewGenerator\\": "module/PreviewGenerator/src/"
+ "Shlinkio\\Shlink\\Core\\": "module/Core/src"
},
"files": [
"module/Core/functions/functions.php"
@@ -86,8 +85,7 @@
"ShlinkioTest\\Shlink\\Core\\": [
"module/Core/test",
"module/Core/test-db"
- ],
- "ShlinkioTest\\Shlink\\PreviewGenerator\\": "module/PreviewGenerator/test"
+ ]
}
},
"scripts": {
diff --git a/config/autoload/app_options.global.php b/config/autoload/app_options.global.php
index e10f1b20..f64f9cff 100644
--- a/config/autoload/app_options.global.php
+++ b/config/autoload/app_options.global.php
@@ -2,14 +2,11 @@
declare(strict_types=1);
-use function Shlinkio\Shlink\Common\env;
-
return [
'app_options' => [
'name' => 'Shlink',
'version' => '%SHLINK_VERSION%',
- 'secret_key' => env('SECRET_KEY', ''),
'disable_track_param' => null,
],
diff --git a/config/autoload/error-handler.global.php b/config/autoload/error-handler.global.php
index 7f5c91c9..69a54f03 100644
--- a/config/autoload/error-handler.global.php
+++ b/config/autoload/error-handler.global.php
@@ -15,10 +15,6 @@ return [
],
],
- 'backwards_compatible_problem_details' => [
- 'json_flags' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION,
- ],
-
'error_handler' => [
'listeners' => [Logger\ErrorLogger::class],
],
diff --git a/config/autoload/middleware-pipeline.global.php b/config/autoload/middleware-pipeline.global.php
index 35a9a16b..0f24a7c9 100644
--- a/config/autoload/middleware-pipeline.global.php
+++ b/config/autoload/middleware-pipeline.global.php
@@ -21,7 +21,6 @@ return [
'path' => '/rest',
'middleware' => [
Rest\Middleware\CrossDomainMiddleware::class,
- Rest\Middleware\BackwardsCompatibleProblemDetailsMiddleware::class,
ProblemDetails\ProblemDetailsMiddleware::class,
],
],
@@ -31,13 +30,6 @@ return [
Common\Middleware\CloseDbConnectionMiddleware::class,
],
],
- 'pre-routing-rest' => [
- 'path' => '/rest',
- 'middleware' => [
- Rest\Middleware\PathVersionMiddleware::class,
- Rest\Middleware\ShortUrl\ShortCodePathMiddleware::class,
- ],
- ],
'routing' => [
'middleware' => [
diff --git a/config/autoload/preview-generation.global.php b/config/autoload/preview-generation.global.php
deleted file mode 100644
index 93696000..00000000
--- a/config/autoload/preview-generation.global.php
+++ /dev/null
@@ -1,12 +0,0 @@
- [
- 'files_location' => 'data/cache',
- ],
-
-];
diff --git a/config/autoload/url-shortener.global.php b/config/autoload/url-shortener.global.php
index 58bc3faa..5cf4f86f 100644
--- a/config/autoload/url-shortener.global.php
+++ b/config/autoload/url-shortener.global.php
@@ -9,7 +9,7 @@ return [
'schema' => 'https',
'hostname' => '',
],
- 'validate_url' => true,
+ 'validate_url' => false,
'visits_webhooks' => [],
],
diff --git a/config/config.php b/config/config.php
index ad18fd20..855f5d41 100644
--- a/config/config.php
+++ b/config/config.php
@@ -23,7 +23,6 @@ return (new ConfigAggregator\ConfigAggregator([
CLI\ConfigProvider::class,
Rest\ConfigProvider::class,
EventDispatcher\ConfigProvider::class,
- PreviewGenerator\ConfigProvider::class,
new ConfigAggregator\PhpFileProvider('config/autoload/{{,*.}global,{,*.}local}.php'),
env('APP_ENV') === 'test'
? new ConfigAggregator\PhpFileProvider('config/test/*.global.php')
diff --git a/config/test/test_config.global.php b/config/test/test_config.global.php
index 0aeaea6d..a3b297b7 100644
--- a/config/test/test_config.global.php
+++ b/config/test/test_config.global.php
@@ -61,6 +61,7 @@ return [
'schema' => 'http',
'hostname' => 'doma.in',
],
+ 'validate_url' => true,
],
'zend-expressive-swoole' => [
diff --git a/docker/README.md b/docker/README.md
index b600c268..423ba8f8 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -103,7 +103,7 @@ This is the complete list of supported env vars:
* **postgres** -> `5432`
* `DISABLE_TRACK_PARAM`: The name of a query param that can be used to visit short URLs avoiding the visit to be tracked. This feature won't be available if not value is provided.
* `DELETE_SHORT_URL_THRESHOLD`: The amount of visits on short URLs which will not allow them to be deleted. Defaults to `15`.
-* `VALIDATE_URLS`: Boolean which tells if shlink should validate a status 20x (after following redirects) is returned when trying to shorten a URL. Defaults to `true`.
+* `VALIDATE_URLS`: Boolean which tells if shlink should validate a status 20x is returned (after following redirects) when trying to shorten a URL. Defaults to `false`.
* `INVALID_SHORT_URL_REDIRECT_TO`: If a URL is provided here, when a user tries to access an invalid short URL, he/she will be redirected to this value. If this env var is not provided, the user will see a generic `404 - not found` page.
* `REGULAR_404_REDIRECT_TO`: If a URL is provided here, when a user tries to access a URL not matching any one supported by the router, he/she will be redirected to this value. If this env var is not provided, the user will see a generic `404 - not found` page.
* `BASE_URL_REDIRECT_TO`: If a URL is provided here, when a user tries to access Shlink's base URL, he/she will be redirected to this value. If this env var is not provided, the user will see a generic `404 - not found` page.
@@ -119,7 +119,6 @@ This is the complete list of supported env vars:
In the future, these redis servers could be used for other caching operations performed by shlink.
-* `NOT_FOUND_REDIRECT_TO`: **Deprecated since v1.20 in favor of `INVALID_SHORT_URL_REDIRECT_TO`** If a URL is provided here, when a user tries to access an invalid short URL, he/she will be redirected to this value. If this env var is not provided, the user will see a generic `404 - not found` page.
* `SHORTCODE_CHARS`: **Ignored when using Shlink 1.20 or newer**. A charset to use when building short codes. Only needed when using more than one shlink instance ([Multi instance considerations](#multi-instance-considerations)).
An example using all env vars could look like this:
@@ -138,7 +137,7 @@ docker run \
-e DB_PORT=3306 \
-e DISABLE_TRACK_PARAM="no-track" \
-e DELETE_SHORT_URL_THRESHOLD=30 \
- -e VALIDATE_URLS=false \
+ -e VALIDATE_URLS=true \
-e "INVALID_SHORT_URL_REDIRECT_TO=https://my-landing-page.com" \
-e "REGULAR_404_REDIRECT_TO=https://my-landing-page.com" \
-e "BASE_URL_REDIRECT_TO=https://my-landing-page.com" \
@@ -164,7 +163,7 @@ The whole configuration should have this format, but it can be split into multip
"delete_short_url_threshold": 30,
"short_domain_schema": "https",
"short_domain_host": "doma.in",
- "validate_url": false,
+ "validate_url": true,
"invalid_short_url_redirect_to": "https://my-landing-page.com",
"regular_404_redirect_to": "https://my-landing-page.com",
"base_url_redirect_to": "https://my-landing-page.com",
@@ -186,15 +185,12 @@ The whole configuration should have this format, but it can be split into multip
"password": "123abc",
"host": "something.rds.amazonaws.com",
"port": "3306"
- },
- "not_found_redirect_to": "https://my-landing-page.com"
+ }
}
```
> This is internally parsed to how shlink expects the config. If you are using a version previous to 1.17.0, this parser is not present and you need to provide a config structure like the one [documented previously](https://github.com/shlinkio/shlink-docker-image/tree/v1.16.3#provide-config-via-volumes).
-> The `not_found_redirect_to` option has been deprecated in v1.20. Use `invalid_short_url_redirect_to` instead (however, it will still work for backwards compatibility).
-
Once created just run shlink with the volume:
```bash
diff --git a/docker/config/shlink_in_docker.local.php b/docker/config/shlink_in_docker.local.php
index 6d3367ac..5b9d5547 100644
--- a/docker/config/shlink_in_docker.local.php
+++ b/docker/config/shlink_in_docker.local.php
@@ -8,19 +8,10 @@ use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use function explode;
-use function file_exists;
-use function file_get_contents;
-use function file_put_contents;
use function Functional\contains;
-use function implode;
use function Shlinkio\Shlink\Common\env;
-use function sprintf;
-use function str_shuffle;
-use function substr;
-use function sys_get_temp_dir;
$helper = new class {
- private const BASE62 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
private const DB_DRIVERS_MAP = [
'mysql' => 'pdo_mysql',
'maria' => 'pdo_mysql',
@@ -32,40 +23,6 @@ $helper = new class {
'postgres' => '5432',
];
- /** @var string */
- private $secretKey;
-
- public function __construct()
- {
- [, $this->secretKey] = $this->initShlinkSecretKey();
- }
-
- private function initShlinkSecretKey(): array
- {
- $keysFile = sprintf('%s/shlink.keys', sys_get_temp_dir());
- if (file_exists($keysFile)) {
- return explode(',', file_get_contents($keysFile));
- }
-
- $keys = [
- '', // This was the SHORTCODE_CHARS. Kept as empty string for BC
- env('SECRET_KEY', $this->generateSecretKey()), // Deprecated
- ];
-
- file_put_contents($keysFile, implode(',', $keys));
- return $keys;
- }
-
- private function generateSecretKey(): string
- {
- return substr(str_shuffle(self::BASE62), 0, 32);
- }
-
- public function getSecretKey(): string
- {
- return $this->secretKey;
- }
-
public function getDbConfig(): array
{
$driver = env('DB_DRIVER');
@@ -94,7 +51,7 @@ $helper = new class {
public function getNotFoundRedirectsConfig(): array
{
return [
- 'invalid_short_url' => env('INVALID_SHORT_URL_REDIRECT_TO', env('NOT_FOUND_REDIRECT_TO')),
+ 'invalid_short_url' => env('INVALID_SHORT_URL_REDIRECT_TO'),
'regular_404' => env('REGULAR_404_REDIRECT_TO'),
'base_url' => env('BASE_URL_REDIRECT_TO'),
];
@@ -112,7 +69,6 @@ return [
'config_cache_enabled' => false,
'app_options' => [
- 'secret_key' => $helper->getSecretKey(),
'disable_track_param' => env('DISABLE_TRACK_PARAM'),
],
@@ -130,7 +86,7 @@ return [
'schema' => env('SHORT_DOMAIN_SCHEMA', 'http'),
'hostname' => env('SHORT_DOMAIN_HOST', ''),
],
- 'validate_url' => (bool) env('VALIDATE_URLS', true),
+ 'validate_url' => (bool) env('VALIDATE_URLS', false),
'visits_webhooks' => $helper->getVisitsWebhooks(),
],
diff --git a/docs/swagger/definitions/Error.json b/docs/swagger/definitions/Error.json
index 006fa47a..217f32c5 100644
--- a/docs/swagger/definitions/Error.json
+++ b/docs/swagger/definitions/Error.json
@@ -17,16 +17,6 @@
"status": {
"type": "number",
"description": "HTTP response status code"
- },
- "code": {
- "type": "string",
- "description": "**[Deprecated] Use type instead. Not returned for v2 of the REST API** A machine unique code",
- "deprecated": true
- },
- "message": {
- "type": "string",
- "description": "**[Deprecated] Use detail instead. Not returned for v2 of the REST API** A human-friendly error message",
- "deprecated": true
}
}
}
diff --git a/docs/swagger/definitions/ShortUrl.json b/docs/swagger/definitions/ShortUrl.json
index 9b259249..8111bd6e 100644
--- a/docs/swagger/definitions/ShortUrl.json
+++ b/docs/swagger/definitions/ShortUrl.json
@@ -31,11 +31,6 @@
},
"meta": {
"$ref": "./ShortUrlMeta.json"
- },
- "originalUrl": {
- "deprecated": true,
- "type": "string",
- "description": "The original long URL. [DEPRECATED. Use longUrl instead]"
}
}
}
diff --git a/docs/swagger/definitions/Visit.json b/docs/swagger/definitions/Visit.json
index 131bc84e..9e1eb5b5 100644
--- a/docs/swagger/definitions/Visit.json
+++ b/docs/swagger/definitions/Visit.json
@@ -16,11 +16,6 @@
},
"visitLocation": {
"$ref": "./VisitLocation.json"
- },
- "remoteAddr": {
- "type": "string",
- "description": "This value is deprecated and will always be null",
- "deprecated": true
}
}
}
diff --git a/docs/swagger/definitions/VisitLocation.json b/docs/swagger/definitions/VisitLocation.json
index e4c9fc90..7e2fa18c 100644
--- a/docs/swagger/definitions/VisitLocation.json
+++ b/docs/swagger/definitions/VisitLocation.json
@@ -11,10 +11,10 @@
"type": "string"
},
"latitude": {
- "type": "string"
+ "type": "number"
},
"longitude": {
- "type": "string"
+ "type": "number"
},
"regionName": {
"type": "string"
diff --git a/docs/swagger/paths/v1_authenticate.json b/docs/swagger/paths/v1_authenticate.json
deleted file mode 100644
index cffa9e05..00000000
--- a/docs/swagger/paths/v1_authenticate.json
+++ /dev/null
@@ -1,84 +0,0 @@
-{
- "post": {
- "deprecated": true,
- "operationId": "authenticate",
- "tags": [
- "Authentication"
- ],
- "summary": "[Deprecated] Perform authentication",
- "description": "**This endpoint is deprecated, since the authentication can be performed via API key now**. Performs an authentication.",
- "requestBody": {
- "description": "Request body.",
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "required": [
- "apiKey"
- ],
- "properties": {
- "apiKey": {
- "description": "The API key to authenticate with",
- "type": "string"
- }
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "The authentication worked.",
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "properties": {
- "token": {
- "type": "string",
- "description": "The authentication token that needs to be sent in the Authorization header"
- }
- }
- }
- }
- },
- "examples": {
- "application/json": {
- "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"
- }
- }
- },
- "400": {
- "description": "An API key was not provided.",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "../definitions/Error.json"
- }
- }
- }
- },
- "401": {
- "description": "The API key is incorrect, is disabled or has expired.",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "../definitions/Error.json"
- }
- }
- }
- },
- "500": {
- "description": "Unexpected error.",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "../definitions/Error.json"
- }
- }
- }
- }
- }
- }
-}
diff --git a/docs/swagger/paths/v1_short-urls.json b/docs/swagger/paths/v1_short-urls.json
index 46708e22..0c6d0484 100644
--- a/docs/swagger/paths/v1_short-urls.json
+++ b/docs/swagger/paths/v1_short-urls.json
@@ -5,7 +5,7 @@
"Short URLs"
],
"summary": "List short URLs",
- "description": "Returns the list of short URLs.
**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
+ "description": "Returns the list of short URLs.",
"parameters": [
{
"$ref": "../parameters/version.json"
@@ -77,9 +77,6 @@
"security": [
{
"ApiKey": []
- },
- {
- "Bearer": []
}
],
"responses": {
@@ -187,13 +184,10 @@
"Short URLs"
],
"summary": "Create short URL",
- "description": "Creates a new short URL.
**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.
**Param findIfExists:**: Starting with v1.16, this new param allows to force shlink to return existing short URLs when found based on provided params, instead of creating a new one. However, it might add complexity and have unexpected outputs.\n\nThese are the use cases:\n* Only the long URL is provided: It will return the newest match or create a new short URL if none is found.\n* Long url and custom slug are provided: It will return the short URL when both params match, return an error when the slug is in use for another long URL, or create a new short URL otherwise.\n* Any of the above but including other params (tags, validSince, validUntil, maxVisits): It will behave the same as the previous two cases, but it will try to exactly match existing results using all the params. If any of them does not match, it will try to create a new short URL.",
+ "description": "Creates a new short URL.
**Param findIfExists:**: Starting with v1.16, this new param allows to force shlink to return existing short URLs when found based on provided params, instead of creating a new one. However, it might add complexity and have unexpected outputs.\n\nThese are the use cases:\n* Only the long URL is provided: It will return the newest match or create a new short URL if none is found.\n* Long url and custom slug are provided: It will return the short URL when both params match, return an error when the slug is in use for another long URL, or create a new short URL otherwise.\n* Any of the above but including other params (tags, validSince, validUntil, maxVisits): It will behave the same as the previous two cases, but it will try to exactly match existing results using all the params. If any of them does not match, it will try to create a new short URL.",
"security": [
{
"ApiKey": []
- },
- {
- "Bearer": []
}
],
"parameters": [
diff --git a/docs/swagger/paths/v1_short-urls_shorten.json b/docs/swagger/paths/v1_short-urls_shorten.json
index 49233c49..c5ad9352 100644
--- a/docs/swagger/paths/v1_short-urls_shorten.json
+++ b/docs/swagger/paths/v1_short-urls_shorten.json
@@ -5,7 +5,7 @@
"Short URLs"
],
"summary": "Create a short URL",
- "description": "Creates a short URL in a single API call. Useful for third party integrations.
**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
+ "description": "Creates a short URL in a single API call. Useful for third party integrations.",
"parameters": [
{
"$ref": "../parameters/version.json"
diff --git a/docs/swagger/paths/v1_short-urls_{shortCode}.json b/docs/swagger/paths/v1_short-urls_{shortCode}.json
index 95532868..d4537a83 100644
--- a/docs/swagger/paths/v1_short-urls_{shortCode}.json
+++ b/docs/swagger/paths/v1_short-urls_{shortCode}.json
@@ -5,7 +5,7 @@
"Short URLs"
],
"summary": "Parse short code",
- "description": "Get the long URL behind a short URL's short code.
**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
+ "description": "Get the long URL behind a short URL's short code.",
"parameters": [
{
"$ref": "../parameters/version.json"
@@ -32,9 +32,6 @@
"security": [
{
"ApiKey": []
- },
- {
- "Bearer": []
}
],
"responses": {
@@ -94,7 +91,7 @@
"Short URLs"
],
"summary": "Edit short URL",
- "description": "Update certain meta arguments from an existing short URL.
**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
+ "description": "Update certain meta arguments from an existing short URL.",
"parameters": [
{
"$ref": "../parameters/version.json"
@@ -137,9 +134,6 @@
"security": [
{
"ApiKey": []
- },
- {
- "Bearer": []
}
],
"responses": {
@@ -201,105 +195,13 @@
}
},
- "put": {
- "deprecated": true,
- "operationId": "editShortUrlPut",
- "tags": [
- "Short URLs"
- ],
- "summary": "[DEPRECATED] Edit short URL",
- "description": "**[DEPRECATED]** Use [editShortUrl](#/Short_URLs/getShortUrl) instead",
- "parameters": [
- {
- "$ref": "../parameters/version.json"
- },
- {
- "name": "shortCode",
- "in": "path",
- "description": "The short code to edit.",
- "required": true,
- "schema": {
- "type": "string"
- }
- }
- ],
- "requestBody": {
- "description": "Request body.",
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "type": "object",
- "properties": {
- "validSince": {
- "description": "The date (in ISO-8601 format) from which this short code will be valid",
- "type": "string"
- },
- "validUntil": {
- "description": "The date (in ISO-8601 format) until which this short code will be valid",
- "type": "string"
- },
- "maxVisits": {
- "description": "The maximum number of allowed visits for this short code",
- "type": "number"
- }
- }
- }
- }
- }
- },
- "security": [
- {
- "ApiKey": []
- },
- {
- "Bearer": []
- }
- ],
- "responses": {
- "204": {
- "description": "The short code has been properly updated."
- },
- "400": {
- "description": "Provided meta arguments are invalid.",
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "../definitions/Error.json"
- }
- }
- }
- },
- "404": {
- "description": "No short URL was found for provided short code.",
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "../definitions/Error.json"
- }
- }
- }
- },
- "500": {
- "description": "Unexpected error.",
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "../definitions/Error.json"
- }
- }
- }
- }
- }
- },
-
"delete": {
"operationId": "deleteShortUrl",
"tags": [
"Short URLs"
],
"summary": "Delete short URL",
- "description": "Deletes the short URL for provided short code.
**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
+ "description": "Deletes the short URL for provided short code.",
"parameters": [
{
"$ref": "../parameters/version.json"
@@ -317,9 +219,6 @@
"security": [
{
"ApiKey": []
- },
- {
- "Bearer": []
}
],
"responses": {
diff --git a/docs/swagger/paths/v1_short-urls_{shortCode}_tags.json b/docs/swagger/paths/v1_short-urls_{shortCode}_tags.json
index 45142e62..4065f718 100644
--- a/docs/swagger/paths/v1_short-urls_{shortCode}_tags.json
+++ b/docs/swagger/paths/v1_short-urls_{shortCode}_tags.json
@@ -5,7 +5,7 @@
"Short URLs"
],
"summary": "Edit tags on short URL",
- "description": "Edit the tags on URL identified by provided short code.
**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
+ "description": "Edit the tags on URL identified by provided short code.",
"parameters": [
{
"$ref": "../parameters/version.json"
@@ -46,9 +46,6 @@
"security": [
{
"ApiKey": []
- },
- {
- "Bearer": []
}
],
"responses": {
diff --git a/docs/swagger/paths/v1_short-urls_{shortCode}_visits.json b/docs/swagger/paths/v1_short-urls_{shortCode}_visits.json
index 508449de..2369ba13 100644
--- a/docs/swagger/paths/v1_short-urls_{shortCode}_visits.json
+++ b/docs/swagger/paths/v1_short-urls_{shortCode}_visits.json
@@ -5,7 +5,7 @@
"Visits"
],
"summary": "List visits for short URL",
- "description": "Get the list of visits on the short URL behind provided short code.
**Important note**: Before shlink v1.13, this endpoint used to use the `/short-codes` path instead of `/short-urls`. Both of them will keep working, while the first one is considered deprecated.",
+ "description": "Get the list of visits on the short URL behind provided short code.",
"parameters": [
{
"$ref": "../parameters/version.json"
@@ -59,9 +59,6 @@
"security": [
{
"ApiKey": []
- },
- {
- "Bearer": []
}
],
"responses": {
@@ -108,8 +105,8 @@
"cityName": "Cupertino",
"countryCode": "US",
"countryName": "United States",
- "latitude": "37.3042",
- "longitude": "-122.0946",
+ "latitude": 37.3042,
+ "longitude": -122.0946,
"regionName": "California",
"timezone": "America/Los_Angeles"
}
diff --git a/docs/swagger/paths/v1_tags.json b/docs/swagger/paths/v1_tags.json
index a0fcc512..5e7fd71c 100644
--- a/docs/swagger/paths/v1_tags.json
+++ b/docs/swagger/paths/v1_tags.json
@@ -9,9 +9,6 @@
"security": [
{
"ApiKey": []
- },
- {
- "Bearer": []
}
],
"parameters": [
@@ -78,9 +75,6 @@
"security": [
{
"ApiKey": []
- },
- {
- "Bearer": []
}
],
"parameters": [
@@ -170,9 +164,6 @@
"security": [
{
"ApiKey": []
- },
- {
- "Bearer": []
}
],
"parameters": [
@@ -279,9 +270,6 @@
"security": [
{
"ApiKey": []
- },
- {
- "Bearer": []
}
],
"responses": {
diff --git a/docs/swagger/paths/{shortCode}_preview.json b/docs/swagger/paths/{shortCode}_preview.json
deleted file mode 100644
index 98df559c..00000000
--- a/docs/swagger/paths/{shortCode}_preview.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "get": {
- "deprecated": true,
- "operationId": "shortUrlPreview",
- "tags": [
- "URL Shortener"
- ],
- "summary": "Short URL preview image",
- "description": "Returns the preview of the page behind a short URL",
- "parameters": [
- {
- "name": "shortCode",
- "in": "path",
- "description": "The short code to resolve.",
- "required": true,
- "schema": {
- "type": "string"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Image in PNG format",
- "content": {
- "image/png": {
- "schema": {
- "type": "string",
- "format": "binary"
- }
- }
- }
- }
- }
- }
-}
diff --git a/docs/swagger/swagger.json b/docs/swagger/swagger.json
index d924b8a0..ddf2b3ad 100644
--- a/docs/swagger/swagger.json
+++ b/docs/swagger/swagger.json
@@ -33,12 +33,6 @@
"type": "apiKey",
"in": "header",
"name": "X-Api-Key"
- },
- "Bearer": {
- "description": "**[DEPRECATED]** The JWT identifying a previously authenticated API key",
- "type": "http",
- "scheme": "bearer",
- "bearerFormat": "JWT"
}
}
},
@@ -63,10 +57,6 @@
{
"name": "URL Shortener",
"description": "Non-rest endpoints, used to be publicly exposed"
- },
- {
- "name": "Authentication",
- "description": "**[DEPRECATED]** Authentication-related endpoints"
}
],
@@ -104,13 +94,6 @@
},
"/{shortCode}/qr-code": {
"$ref": "paths/{shortCode}_qr-code.json"
- },
- "/{shortCode}/preview": {
- "$ref": "paths/{shortCode}_preview.json"
- },
-
- "/rest/v1/authenticate": {
- "$ref": "paths/v1_authenticate.json"
}
}
}
diff --git a/module/CLI/config/cli.config.php b/module/CLI/config/cli.config.php
index 0d5d5d5b..fa9efc69 100644
--- a/module/CLI/config/cli.config.php
+++ b/module/CLI/config/cli.config.php
@@ -12,14 +12,9 @@ return [
Command\ShortUrl\ResolveUrlCommand::NAME => Command\ShortUrl\ResolveUrlCommand::class,
Command\ShortUrl\ListShortUrlsCommand::NAME => Command\ShortUrl\ListShortUrlsCommand::class,
Command\ShortUrl\GetVisitsCommand::NAME => Command\ShortUrl\GetVisitsCommand::class,
- Command\ShortUrl\GeneratePreviewCommand::NAME => Command\ShortUrl\GeneratePreviewCommand::class,
Command\ShortUrl\DeleteShortUrlCommand::NAME => Command\ShortUrl\DeleteShortUrlCommand::class,
Command\Visit\LocateVisitsCommand::NAME => Command\Visit\LocateVisitsCommand::class,
- Command\Visit\UpdateDbCommand::NAME => Command\Visit\UpdateDbCommand::class,
-
- Command\Config\GenerateCharsetCommand::NAME => Command\Config\GenerateCharsetCommand::class,
- Command\Config\GenerateSecretCommand::NAME => Command\Config\GenerateSecretCommand::class,
Command\Api\GenerateKeyCommand::NAME => Command\Api\GenerateKeyCommand::class,
Command\Api\DisableKeyCommand::NAME => Command\Api\DisableKeyCommand::class,
diff --git a/module/CLI/config/dependencies.config.php b/module/CLI/config/dependencies.config.php
index c89a0ad7..c7eea7b2 100644
--- a/module/CLI/config/dependencies.config.php
+++ b/module/CLI/config/dependencies.config.php
@@ -12,7 +12,6 @@ use Shlinkio\Shlink\Core\Service;
use Shlinkio\Shlink\Installer\Factory\ProcessHelperFactory;
use Shlinkio\Shlink\IpGeolocation\GeoLite2\DbUpdater;
use Shlinkio\Shlink\IpGeolocation\Resolver\IpLocationResolverInterface;
-use Shlinkio\Shlink\PreviewGenerator\Service\PreviewGenerator;
use Shlinkio\Shlink\Rest\Service\ApiKeyService;
use Symfony\Component\Console as SymfonyCli;
use Symfony\Component\Lock\LockFactory;
@@ -34,14 +33,9 @@ return [
Command\ShortUrl\ResolveUrlCommand::class => ConfigAbstractFactory::class,
Command\ShortUrl\ListShortUrlsCommand::class => ConfigAbstractFactory::class,
Command\ShortUrl\GetVisitsCommand::class => ConfigAbstractFactory::class,
- Command\ShortUrl\GeneratePreviewCommand::class => ConfigAbstractFactory::class,
Command\ShortUrl\DeleteShortUrlCommand::class => ConfigAbstractFactory::class,
Command\Visit\LocateVisitsCommand::class => ConfigAbstractFactory::class,
- Command\Visit\UpdateDbCommand::class => ConfigAbstractFactory::class,
-
- Command\Config\GenerateCharsetCommand::class => InvokableFactory::class,
- Command\Config\GenerateSecretCommand::class => InvokableFactory::class,
Command\Api\GenerateKeyCommand::class => ConfigAbstractFactory::class,
Command\Api\DisableKeyCommand::class => ConfigAbstractFactory::class,
@@ -64,7 +58,6 @@ return [
Command\ShortUrl\ResolveUrlCommand::class => [Service\UrlShortener::class],
Command\ShortUrl\ListShortUrlsCommand::class => [Service\ShortUrlService::class, 'config.url_shortener.domain'],
Command\ShortUrl\GetVisitsCommand::class => [Service\VisitsTracker::class],
- Command\ShortUrl\GeneratePreviewCommand::class => [Service\ShortUrlService::class, PreviewGenerator::class],
Command\ShortUrl\DeleteShortUrlCommand::class => [Service\ShortUrl\DeleteShortUrlService::class],
Command\Visit\LocateVisitsCommand::class => [
@@ -73,7 +66,6 @@ return [
LockFactory::class,
GeolocationDbUpdater::class,
],
- Command\Visit\UpdateDbCommand::class => [DbUpdater::class],
Command\Api\GenerateKeyCommand::class => [ApiKeyService::class],
Command\Api\DisableKeyCommand::class => [ApiKeyService::class],
diff --git a/module/CLI/src/Command/Config/GenerateCharsetCommand.php b/module/CLI/src/Command/Config/GenerateCharsetCommand.php
deleted file mode 100644
index a285c7f0..00000000
--- a/module/CLI/src/Command/Config/GenerateCharsetCommand.php
+++ /dev/null
@@ -1,40 +0,0 @@
-setName(self::NAME)
- ->setDescription(sprintf(
- '[DEPRECATED] Generates a character set sample just by shuffling the default one, "%s". '
- . 'Then it can be set in the SHORTCODE_CHARS environment variable',
- self::DEFAULT_CHARS
- ))
- ->setHelp('This command is deprecated. Better leave shlink generate the charset.>');
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): ?int
- {
- $charSet = str_shuffle(self::DEFAULT_CHARS);
- (new SymfonyStyle($input, $output))->success(sprintf('Character set: "%s"', $charSet));
- return ExitCodes::EXIT_SUCCESS;
- }
-}
diff --git a/module/CLI/src/Command/Config/GenerateSecretCommand.php b/module/CLI/src/Command/Config/GenerateSecretCommand.php
deleted file mode 100644
index c0d60eea..00000000
--- a/module/CLI/src/Command/Config/GenerateSecretCommand.php
+++ /dev/null
@@ -1,39 +0,0 @@
-setName(self::NAME)
- ->setDescription('[DEPRECATED] Generates a random secret string that can be used for JWT token encryption')
- ->setHelp(
- 'This command is deprecated. Better leave shlink generate the secret key.>'
- );
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): ?int
- {
- $secret = $this->generateRandomString(32);
- (new SymfonyStyle($input, $output))->success(sprintf('Secret key: "%s"', $secret));
- return ExitCodes::EXIT_SUCCESS;
- }
-}
diff --git a/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php b/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php
index 6626791b..91c37663 100644
--- a/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php
+++ b/module/CLI/src/Command/ShortUrl/DeleteShortUrlCommand.php
@@ -19,7 +19,6 @@ use function sprintf;
class DeleteShortUrlCommand extends Command
{
public const NAME = 'short-url:delete';
- private const ALIASES = ['short-code:delete'];
private DeleteShortUrlServiceInterface $deleteShortUrlService;
@@ -33,7 +32,6 @@ class DeleteShortUrlCommand extends Command
{
$this
->setName(self::NAME)
- ->setAliases(self::ALIASES)
->setDescription('Deletes a short URL')
->addArgument('shortCode', InputArgument::REQUIRED, 'The short code for the short URL to be deleted')
->addOption(
diff --git a/module/CLI/src/Command/ShortUrl/GeneratePreviewCommand.php b/module/CLI/src/Command/ShortUrl/GeneratePreviewCommand.php
deleted file mode 100644
index 081fa94f..00000000
--- a/module/CLI/src/Command/ShortUrl/GeneratePreviewCommand.php
+++ /dev/null
@@ -1,76 +0,0 @@
-shortUrlService = $shortUrlService;
- $this->previewGenerator = $previewGenerator;
- }
-
- protected function configure(): void
- {
- $this
- ->setName(self::NAME)
- ->setAliases(self::ALIASES)
- ->setDescription(
- '[DEPRECATED] Processes and generates the previews for every URL, improving performance for later web '
- . 'requests.'
- );
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): ?int
- {
- $page = 1;
- do {
- $shortUrls = $this->shortUrlService->listShortUrls($page);
- $page += 1;
-
- foreach ($shortUrls as $shortUrl) {
- $this->processUrl($shortUrl->getLongUrl(), $output);
- }
- } while ($page <= $shortUrls->count());
-
- (new SymfonyStyle($input, $output))->success('Finished processing all URLs');
- return ExitCodes::EXIT_SUCCESS;
- }
-
- private function processUrl($url, OutputInterface $output): void
- {
- try {
- $output->write(sprintf('Processing URL %s...', $url));
- $this->previewGenerator->generatePreview($url);
- $output->writeln(' Success!');
- } catch (PreviewGenerationException $e) {
- $output->writeln(' Error');
- if ($output->isVerbose()) {
- $this->getApplication()->renderThrowable($e, $output);
- }
- }
- }
-}
diff --git a/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php b/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php
index 94748795..3e66658d 100644
--- a/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php
+++ b/module/CLI/src/Command/ShortUrl/GenerateShortUrlCommand.php
@@ -26,7 +26,6 @@ use function sprintf;
class GenerateShortUrlCommand extends Command
{
public const NAME = 'short-url:generate';
- private const ALIASES = ['shortcode:generate', 'short-code:generate'];
private UrlShortenerInterface $urlShortener;
private array $domainConfig;
@@ -42,7 +41,6 @@ class GenerateShortUrlCommand extends Command
{
$this
->setName(self::NAME)
- ->setAliases(self::ALIASES)
->setDescription('Generates a short URL for provided long URL and returns it')
->addArgument('longUrl', InputArgument::REQUIRED, 'The long URL to parse')
->addOption(
diff --git a/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php b/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php
index 94462a57..363ff3aa 100644
--- a/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php
+++ b/module/CLI/src/Command/ShortUrl/GetVisitsCommand.php
@@ -22,7 +22,6 @@ use function Functional\select_keys;
class GetVisitsCommand extends AbstractWithDateRangeCommand
{
public const NAME = 'short-url:visits';
- private const ALIASES = ['shortcode:visits', 'short-code:visits'];
private VisitsTrackerInterface $visitsTracker;
@@ -36,7 +35,6 @@ class GetVisitsCommand extends AbstractWithDateRangeCommand
{
$this
->setName(self::NAME)
- ->setAliases(self::ALIASES)
->setDescription('Returns the detailed visits information for provided short code')
->addArgument('shortCode', InputArgument::REQUIRED, 'The short code which visits we want to get');
}
diff --git a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php
index 9eb0cc13..62d44445 100644
--- a/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php
+++ b/module/CLI/src/Command/ShortUrl/ListShortUrlsCommand.php
@@ -32,7 +32,6 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
use PaginatorUtilsTrait;
public const NAME = 'short-url:list';
- private const ALIASES = ['shortcode:list', 'short-code:list'];
private const COLUMNS_WHITELIST = [
'shortCode',
'shortUrl',
@@ -56,7 +55,6 @@ class ListShortUrlsCommand extends AbstractWithDateRangeCommand
{
$this
->setName(self::NAME)
- ->setAliases(self::ALIASES)
->setDescription('List all short URLs')
->addOption(
'page',
diff --git a/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php b/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php
index c75ac9d6..e4c75410 100644
--- a/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php
+++ b/module/CLI/src/Command/ShortUrl/ResolveUrlCommand.php
@@ -19,7 +19,6 @@ use function sprintf;
class ResolveUrlCommand extends Command
{
public const NAME = 'short-url:parse';
- private const ALIASES = ['shortcode:parse', 'short-code:parse'];
private UrlShortenerInterface $urlShortener;
@@ -33,7 +32,6 @@ class ResolveUrlCommand extends Command
{
$this
->setName(self::NAME)
- ->setAliases(self::ALIASES)
->setDescription('Returns the long URL behind a short code')
->addArgument('shortCode', InputArgument::REQUIRED, 'The short code to parse')
->addOption('domain', 'd', InputOption::VALUE_REQUIRED, 'The domain to which the short URL is attached.');
diff --git a/module/CLI/src/Command/Visit/LocateVisitsCommand.php b/module/CLI/src/Command/Visit/LocateVisitsCommand.php
index 0bbd0c90..432ac1bd 100644
--- a/module/CLI/src/Command/Visit/LocateVisitsCommand.php
+++ b/module/CLI/src/Command/Visit/LocateVisitsCommand.php
@@ -30,7 +30,6 @@ use function sprintf;
class LocateVisitsCommand extends AbstractLockedCommand
{
public const NAME = 'visit:locate';
- public const ALIASES = ['visit:process'];
private VisitServiceInterface $visitService;
private IpLocationResolverInterface $ipLocationResolver;
@@ -55,7 +54,6 @@ class LocateVisitsCommand extends AbstractLockedCommand
{
$this
->setName(self::NAME)
- ->setAliases(self::ALIASES)
->setDescription('Resolves visits origin locations.');
}
diff --git a/module/CLI/src/Command/Visit/UpdateDbCommand.php b/module/CLI/src/Command/Visit/UpdateDbCommand.php
deleted file mode 100644
index 367423fd..00000000
--- a/module/CLI/src/Command/Visit/UpdateDbCommand.php
+++ /dev/null
@@ -1,91 +0,0 @@
-geoLiteDbUpdater = $geoLiteDbUpdater;
- }
-
- protected function configure(): void
- {
- $this
- ->setName(self::NAME)
- ->setDescription('[DEPRECATED] Updates the GeoLite2 database file used to geolocate IP addresses')
- ->setHelp(
- 'The GeoLite2 database is updated first Tuesday every month, so this command should be ideally run '
- . 'every first Wednesday'
- )
- ->addOption(
- 'ignoreErrors',
- 'i',
- InputOption::VALUE_NONE,
- 'Makes the command success even iof the update fails.'
- );
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): ?int
- {
- $io = new SymfonyStyle($input, $output);
- $progressBar = new ProgressBar($output);
- $progressBar->start();
-
- try {
- $this->geoLiteDbUpdater->downloadFreshCopy(function (int $total, int $downloaded) use ($progressBar) {
- $progressBar->setMaxSteps($total);
- $progressBar->setProgress($downloaded);
- });
-
- $progressBar->finish();
- $io->newLine();
-
- $io->success('GeoLite2 database properly updated');
- return ExitCodes::EXIT_SUCCESS;
- } catch (RuntimeException $e) {
- $progressBar->finish();
- $io->newLine();
-
- return $this->handleError($e, $io, $input);
- }
- }
-
- private function handleError(RuntimeException $e, SymfonyStyle $io, InputInterface $input): int
- {
- $ignoreErrors = $input->getOption('ignoreErrors');
- $baseErrorMsg = 'An error occurred while updating GeoLite2 database';
-
- if ($ignoreErrors) {
- $io->warning(sprintf('%s, but it was ignored', $baseErrorMsg));
- return ExitCodes::EXIT_SUCCESS;
- }
-
- $io->error($baseErrorMsg);
- if ($io->isVerbose()) {
- $this->getApplication()->renderThrowable($e, $io);
- }
- return ExitCodes::EXIT_FAILURE;
- }
-}
diff --git a/module/CLI/test/Command/Config/GenerateCharsetCommandTest.php b/module/CLI/test/Command/Config/GenerateCharsetCommandTest.php
deleted file mode 100644
index e5430e4a..00000000
--- a/module/CLI/test/Command/Config/GenerateCharsetCommandTest.php
+++ /dev/null
@@ -1,47 +0,0 @@
-add($command);
-
- $this->commandTester = new CommandTester($command);
- }
-
- /** @test */
- public function charactersAreGeneratedFromDefault()
- {
- $prefix = 'Character set: ';
-
- $this->commandTester->execute([]);
- $output = $this->commandTester->getDisplay();
-
- // Both default character set and the new one should have the same length
- $this->assertStringContainsString($prefix, $output);
- }
-
- protected function orderStringLetters($string)
- {
- $letters = str_split($string);
- sort($letters);
- return implode('', $letters);
- }
-}
diff --git a/module/CLI/test/Command/ShortUrl/GeneratePreviewCommandTest.php b/module/CLI/test/Command/ShortUrl/GeneratePreviewCommandTest.php
deleted file mode 100644
index e4029231..00000000
--- a/module/CLI/test/Command/ShortUrl/GeneratePreviewCommandTest.php
+++ /dev/null
@@ -1,92 +0,0 @@
-previewGenerator = $this->prophesize(PreviewGenerator::class);
- $this->shortUrlService = $this->prophesize(ShortUrlService::class);
-
- $command = new GeneratePreviewCommand($this->shortUrlService->reveal(), $this->previewGenerator->reveal());
- $app = new Application();
- $app->add($command);
-
- $this->commandTester = new CommandTester($command);
- }
-
- /** @test */
- public function previewsForEveryUrlAreGenerated()
- {
- $paginator = $this->createPaginator([
- new ShortUrl('http://foo.com'),
- new ShortUrl('https://bar.com'),
- new ShortUrl('http://baz.com/something'),
- ]);
- $this->shortUrlService->listShortUrls(1)->willReturn($paginator)->shouldBeCalledOnce();
-
- $generatePreview1 = $this->previewGenerator->generatePreview('http://foo.com')->willReturn('');
- $generatePreview2 = $this->previewGenerator->generatePreview('https://bar.com')->willReturn('');
- $generatePreview3 = $this->previewGenerator->generatePreview('http://baz.com/something')->willReturn('');
-
- $this->commandTester->execute([]);
- $output = $this->commandTester->getDisplay();
-
- $this->assertStringContainsString('Processing URL http://foo.com', $output);
- $this->assertStringContainsString('Processing URL https://bar.com', $output);
- $this->assertStringContainsString('Processing URL http://baz.com/something', $output);
- $this->assertStringContainsString('Finished processing all URLs', $output);
- $generatePreview1->shouldHaveBeenCalledOnce();
- $generatePreview2->shouldHaveBeenCalledOnce();
- $generatePreview3->shouldHaveBeenCalledOnce();
- }
-
- /** @test */
- public function exceptionWillOutputError()
- {
- $items = [
- new ShortUrl('http://foo.com'),
- new ShortUrl('https://bar.com'),
- new ShortUrl('http://baz.com/something'),
- ];
- $paginator = $this->createPaginator($items);
- $this->shortUrlService->listShortUrls(1)->willReturn($paginator)->shouldBeCalledOnce();
- $this->previewGenerator->generatePreview(Argument::any())->willThrow(PreviewGenerationException::class)
- ->shouldBeCalledTimes(count($items));
-
- $this->commandTester->execute([]);
- $output = $this->commandTester->getDisplay();
- $this->assertEquals(count($items), substr_count($output, 'Error'));
- }
-
- protected function createPaginator(array $items)
- {
- $paginator = new Paginator(new ArrayAdapter($items));
- $paginator->setItemCountPerPage(count($items));
-
- return $paginator;
- }
-}
diff --git a/module/CLI/test/Command/Visit/UpdateDbCommandTest.php b/module/CLI/test/Command/Visit/UpdateDbCommandTest.php
deleted file mode 100644
index 2d6fc478..00000000
--- a/module/CLI/test/Command/Visit/UpdateDbCommandTest.php
+++ /dev/null
@@ -1,75 +0,0 @@
-dbUpdater = $this->prophesize(DbUpdaterInterface::class);
-
- $command = new UpdateDbCommand($this->dbUpdater->reveal());
- $app = new Application();
- $app->add($command);
-
- $this->commandTester = new CommandTester($command);
- }
-
- /** @test */
- public function successMessageIsPrintedIfEverythingWorks(): void
- {
- $download = $this->dbUpdater->downloadFreshCopy(Argument::type('callable'))->will(function () {
- });
-
- $this->commandTester->execute([]);
- $output = $this->commandTester->getDisplay();
- $exitCode = $this->commandTester->getStatusCode();
-
- $this->assertStringContainsString('GeoLite2 database properly updated', $output);
- $this->assertEquals(ExitCodes::EXIT_SUCCESS, $exitCode);
- $download->shouldHaveBeenCalledOnce();
- }
-
- /** @test */
- public function errorMessageIsPrintedIfAnExceptionIsThrown(): void
- {
- $download = $this->dbUpdater->downloadFreshCopy(Argument::type('callable'))->willThrow(RuntimeException::class);
-
- $this->commandTester->execute([]);
- $output = $this->commandTester->getDisplay();
- $exitCode = $this->commandTester->getStatusCode();
-
- $this->assertStringContainsString('An error occurred while updating GeoLite2 database', $output);
- $this->assertEquals(ExitCodes::EXIT_FAILURE, $exitCode);
- $download->shouldHaveBeenCalledOnce();
- }
-
- /** @test */
- public function warningMessageIsPrintedIfAnExceptionIsThrownAndErrorsAreIgnored(): void
- {
- $download = $this->dbUpdater->downloadFreshCopy(Argument::type('callable'))->willThrow(RuntimeException::class);
-
- $this->commandTester->execute(['--ignoreErrors' => true]);
- $output = $this->commandTester->getDisplay();
- $exitCode = $this->commandTester->getStatusCode();
-
- $this->assertStringContainsString('ignored', $output);
- $this->assertEquals(ExitCodes::EXIT_SUCCESS, $exitCode);
- $download->shouldHaveBeenCalledOnce();
- }
-}
diff --git a/module/Core/config/app_options.config.php b/module/Core/config/app_options.config.php
deleted file mode 100644
index ccab5752..00000000
--- a/module/Core/config/app_options.config.php
+++ /dev/null
@@ -1,9 +0,0 @@
- [],
-
-];
diff --git a/module/Core/config/dependencies.config.php b/module/Core/config/dependencies.config.php
index 0ebdae7d..34759868 100644
--- a/module/Core/config/dependencies.config.php
+++ b/module/Core/config/dependencies.config.php
@@ -8,7 +8,6 @@ use Doctrine\Common\Cache\Cache;
use Psr\EventDispatcher\EventDispatcherInterface;
use Shlinkio\Shlink\Core\ErrorHandler;
use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
-use Shlinkio\Shlink\PreviewGenerator\Service\PreviewGenerator;
use Zend\Expressive\Router\RouterInterface;
use Zend\Expressive\Template\TemplateRendererInterface;
use Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory;
@@ -37,7 +36,6 @@ return [
Action\RedirectAction::class => ConfigAbstractFactory::class,
Action\PixelAction::class => ConfigAbstractFactory::class,
Action\QrCodeAction::class => ConfigAbstractFactory::class,
- Action\PreviewAction::class => ConfigAbstractFactory::class,
Middleware\QrCodeCacheMiddleware::class => ConfigAbstractFactory::class,
],
@@ -74,7 +72,6 @@ return [
'Logger_Shlink',
],
Action\QrCodeAction::class => [RouterInterface::class, Service\UrlShortener::class, 'Logger_Shlink'],
- Action\PreviewAction::class => [PreviewGenerator::class, Service\UrlShortener::class, 'Logger_Shlink'],
Middleware\QrCodeCacheMiddleware::class => [Cache::class],
],
diff --git a/module/Core/config/routes.config.php b/module/Core/config/routes.config.php
index b38222df..d636ed23 100644
--- a/module/Core/config/routes.config.php
+++ b/module/Core/config/routes.config.php
@@ -37,23 +37,6 @@ return [
],
'allowed_methods' => [RequestMethod::METHOD_GET],
],
-
- // Deprecated routes
- [
- 'name' => 'short-url-preview',
- 'path' => '/{shortCode}/preview',
- 'middleware' => Action\PreviewAction::class,
- 'allowed_methods' => [RequestMethod::METHOD_GET],
- ],
- [
- 'name' => 'short-url-qr-code-old',
- 'path' => '/qr/{shortCode}[/{size:[0-9]+}]',
- 'middleware' => [
- Middleware\QrCodeCacheMiddleware::class,
- Action\QrCodeAction::class,
- ],
- 'allowed_methods' => [RequestMethod::METHOD_GET],
- ],
],
];
diff --git a/module/Core/src/Action/PreviewAction.php b/module/Core/src/Action/PreviewAction.php
deleted file mode 100644
index d243f12c..00000000
--- a/module/Core/src/Action/PreviewAction.php
+++ /dev/null
@@ -1,63 +0,0 @@
-previewGenerator = $previewGenerator;
- $this->urlShortener = $urlShortener;
- $this->logger = $logger ?: new NullLogger();
- }
-
- /**
- * Process an incoming server request and return a response, optionally delegating
- * to the next middleware component to create the response.
- *
- * @param Request $request
- * @param RequestHandlerInterface $handler
- *
- * @return Response
- */
- public function process(Request $request, RequestHandlerInterface $handler): Response
- {
- $shortCode = $request->getAttribute('shortCode');
-
- try {
- $url = $this->urlShortener->shortCodeToUrl($shortCode);
- $imagePath = $this->previewGenerator->generatePreview($url->getLongUrl());
- return $this->generateImageResponse($imagePath);
- } catch (ShortUrlNotFoundException | PreviewGenerationException $e) {
- $this->logger->warning('An error occurred while generating preview image. {e}', ['e' => $e]);
- return $handler->handle($request);
- }
- }
-}
diff --git a/module/Core/src/Config/SimplifiedConfigParser.php b/module/Core/src/Config/SimplifiedConfigParser.php
index e9c2ae7b..19fe4fb4 100644
--- a/module/Core/src/Config/SimplifiedConfigParser.php
+++ b/module/Core/src/Config/SimplifiedConfigParser.php
@@ -22,7 +22,6 @@ class SimplifiedConfigParser
'short_domain_schema' => ['url_shortener', 'domain', 'schema'],
'short_domain_host' => ['url_shortener', 'domain', 'hostname'],
'validate_url' => ['url_shortener', 'validate_url'],
- 'not_found_redirect_to' => ['not_found_redirects', 'invalid_short_url'], // Deprecated
'invalid_short_url_redirect_to' => ['not_found_redirects', 'invalid_short_url'],
'regular_404_redirect_to' => ['not_found_redirects', 'regular_404'],
'base_url_redirect_to' => ['not_found_redirects', 'base_path'],
diff --git a/module/Core/src/Entity/Visit.php b/module/Core/src/Entity/Visit.php
index c4ee97a2..38c17565 100644
--- a/module/Core/src/Entity/Visit.php
+++ b/module/Core/src/Entity/Visit.php
@@ -90,9 +90,6 @@ class Visit extends AbstractEntity implements JsonSerializable
'date' => $this->date->toAtomString(),
'userAgent' => $this->userAgent,
'visitLocation' => $this->visitLocation,
-
- // Deprecated
- 'remoteAddr' => null,
];
}
diff --git a/module/Core/src/Entity/VisitLocation.php b/module/Core/src/Entity/VisitLocation.php
index ebc8829a..641b078e 100644
--- a/module/Core/src/Entity/VisitLocation.php
+++ b/module/Core/src/Entity/VisitLocation.php
@@ -14,8 +14,8 @@ class VisitLocation extends AbstractEntity implements VisitLocationInterface
private string $countryName;
private string $regionName;
private string $cityName;
- private string $latitude; // FIXME Should be float
- private string $longitude; // FIXME Should be float
+ private float $latitude;
+ private float $longitude;
private string $timezone;
public function __construct(Location $location)
@@ -25,22 +25,22 @@ class VisitLocation extends AbstractEntity implements VisitLocationInterface
public function getCountryName(): string
{
- return $this->countryName ?? '';
+ return $this->countryName;
}
- public function getLatitude(): string
+ public function getLatitude(): float
{
- return $this->latitude ?? '';
+ return $this->latitude;
}
- public function getLongitude(): string
+ public function getLongitude(): float
{
- return $this->longitude ?? '';
+ return $this->longitude;
}
public function getCityName(): string
{
- return $this->cityName ?? '';
+ return $this->cityName;
}
private function exchangeLocationInfo(Location $info): void
@@ -49,8 +49,8 @@ class VisitLocation extends AbstractEntity implements VisitLocationInterface
$this->countryName = $info->countryName();
$this->regionName = $info->regionName();
$this->cityName = $info->city();
- $this->latitude = (string) $info->latitude();
- $this->longitude = (string) $info->longitude();
+ $this->latitude = $info->latitude();
+ $this->longitude = $info->longitude();
$this->timezone = $info->timeZone();
}
@@ -74,8 +74,8 @@ class VisitLocation extends AbstractEntity implements VisitLocationInterface
$this->countryName === '' &&
$this->regionName === '' &&
$this->cityName === '' &&
- ((float) $this->latitude) === 0.0 &&
- ((float) $this->longitude) === 0.0 &&
+ $this->latitude === 0.0 &&
+ $this->longitude === 0.0 &&
$this->timezone === '';
}
}
diff --git a/module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php b/module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php
index 7f901d33..646f1757 100644
--- a/module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php
+++ b/module/Core/src/EventDispatcher/NotifyVisitToWebHooks.php
@@ -78,7 +78,7 @@ class NotifyVisitToWebHooks
'User-Agent' => (string) $this->appOptions,
],
RequestOptions::JSON => [
- 'shortUrl' => $this->transformer->transform($visit->getShortUrl(), false),
+ 'shortUrl' => $this->transformer->transform($visit->getShortUrl()),
'visit' => $visit->jsonSerialize(),
],
];
diff --git a/module/Core/src/Options/AppOptions.php b/module/Core/src/Options/AppOptions.php
index 36b6d58b..06810a68 100644
--- a/module/Core/src/Options/AppOptions.php
+++ b/module/Core/src/Options/AppOptions.php
@@ -15,8 +15,6 @@ class AppOptions extends AbstractOptions
private string $name = '';
private string $version = '1.0';
- /** @deprecated */
- private string $secretKey = '';
private ?string $disableTrackParam = null;
public function getName(): string
@@ -41,23 +39,6 @@ class AppOptions extends AbstractOptions
return $this;
}
- /**
- * @deprecated
- */
- public function getSecretKey(): string
- {
- return $this->secretKey;
- }
-
- /**
- * @deprecated
- */
- protected function setSecretKey(string $secretKey): self
- {
- $this->secretKey = $secretKey;
- return $this;
- }
-
/**
* @return string|null
*/
diff --git a/module/Core/src/Transformer/ShortUrlDataTransformer.php b/module/Core/src/Transformer/ShortUrlDataTransformer.php
index f734cf01..bb19f997 100644
--- a/module/Core/src/Transformer/ShortUrlDataTransformer.php
+++ b/module/Core/src/Transformer/ShortUrlDataTransformer.php
@@ -22,11 +22,11 @@ class ShortUrlDataTransformer implements DataTransformerInterface
/**
* @param ShortUrl $shortUrl
*/
- public function transform($shortUrl, bool $includeDeprecated = true): array
+ public function transform($shortUrl): array
{
$longUrl = $shortUrl->getLongUrl();
- $rawData = [
+ return [
'shortCode' => $shortUrl->getShortCode(),
'shortUrl' => $shortUrl->toString($this->domainConfig),
'longUrl' => $longUrl,
@@ -35,12 +35,6 @@ class ShortUrlDataTransformer implements DataTransformerInterface
'tags' => invoke($shortUrl->getTags(), '__toString'),
'meta' => $this->buildMeta($shortUrl),
];
-
- if ($includeDeprecated) {
- $rawData['originalUrl'] = $longUrl;
- }
-
- return $rawData;
}
private function buildMeta(ShortUrl $shortUrl): array
diff --git a/module/Core/src/Visit/Model/UnknownVisitLocation.php b/module/Core/src/Visit/Model/UnknownVisitLocation.php
index baf056b4..b8926bd5 100644
--- a/module/Core/src/Visit/Model/UnknownVisitLocation.php
+++ b/module/Core/src/Visit/Model/UnknownVisitLocation.php
@@ -11,14 +11,14 @@ final class UnknownVisitLocation implements VisitLocationInterface
return 'Unknown';
}
- public function getLatitude(): string
+ public function getLatitude(): float
{
- return '0.0';
+ return 0.0;
}
- public function getLongitude(): string
+ public function getLongitude(): float
{
- return '0.0';
+ return 0.0;
}
public function getCityName(): string
@@ -33,8 +33,8 @@ final class UnknownVisitLocation implements VisitLocationInterface
'countryName' => 'Unknown',
'regionName' => 'Unknown',
'cityName' => 'Unknown',
- 'latitude' => '0.0',
- 'longitude' => '0.0',
+ 'latitude' => 0.0,
+ 'longitude' => 0.0,
'timezone' => 'Unknown',
];
}
diff --git a/module/Core/src/Visit/Model/VisitLocationInterface.php b/module/Core/src/Visit/Model/VisitLocationInterface.php
index 992e138f..9a296a28 100644
--- a/module/Core/src/Visit/Model/VisitLocationInterface.php
+++ b/module/Core/src/Visit/Model/VisitLocationInterface.php
@@ -10,9 +10,9 @@ interface VisitLocationInterface extends JsonSerializable
{
public function getCountryName(): string;
- public function getLatitude(): string;
+ public function getLatitude(): float;
- public function getLongitude(): string;
+ public function getLongitude(): float;
public function getCityName(): string;
}
diff --git a/module/Core/test/Action/PreviewActionTest.php b/module/Core/test/Action/PreviewActionTest.php
deleted file mode 100644
index 0725c957..00000000
--- a/module/Core/test/Action/PreviewActionTest.php
+++ /dev/null
@@ -1,76 +0,0 @@
-previewGenerator = $this->prophesize(PreviewGenerator::class);
- $this->urlShortener = $this->prophesize(UrlShortener::class);
- $this->action = new PreviewAction($this->previewGenerator->reveal(), $this->urlShortener->reveal());
- }
-
- /** @test */
- public function correctShortCodeReturnsImageResponse(): void
- {
- $shortCode = 'abc123';
- $url = 'foobar.com';
- $shortUrl = new ShortUrl($url);
- $path = __FILE__;
- $this->urlShortener->shortCodeToUrl($shortCode)->willReturn($shortUrl)->shouldBeCalledOnce();
- $this->previewGenerator->generatePreview($url)->willReturn($path)->shouldBeCalledOnce();
-
- $resp = $this->action->process(
- (new ServerRequest())->withAttribute('shortCode', $shortCode),
- $this->prophesize(RequestHandlerInterface::class)->reveal()
- );
-
- $this->assertEquals(filesize($path), $resp->getHeaderLine('Content-length'));
- $this->assertEquals((new finfo(FILEINFO_MIME))->file($path), $resp->getHeaderLine('Content-type'));
- }
-
- /** @test */
- public function invalidShortCodeExceptionFallsBackToNextMiddleware(): void
- {
- $shortCode = 'abc123';
- $this->urlShortener->shortCodeToUrl($shortCode)->willThrow(ShortUrlNotFoundException::class)
- ->shouldBeCalledOnce();
- $delegate = $this->prophesize(RequestHandlerInterface::class);
- $process = $delegate->handle(Argument::any())->willReturn(new Response());
-
- $this->action->process(
- (new ServerRequest())->withAttribute('shortCode', $shortCode),
- $delegate->reveal()
- );
-
- $process->shouldHaveBeenCalledOnce();
- }
-}
diff --git a/module/Core/test/Config/SimplifiedConfigParserTest.php b/module/Core/test/Config/SimplifiedConfigParserTest.php
index 76ba9b1b..c608a44f 100644
--- a/module/Core/test/Config/SimplifiedConfigParserTest.php
+++ b/module/Core/test/Config/SimplifiedConfigParserTest.php
@@ -11,7 +11,7 @@ use function array_merge;
class SimplifiedConfigParserTest extends TestCase
{
- private $postProcessor;
+ private SimplifiedConfigParser $postProcessor;
public function setUp(): void
{
@@ -38,9 +38,9 @@ class SimplifiedConfigParserTest extends TestCase
'disable_track_param' => 'bar',
'short_domain_schema' => 'https',
'short_domain_host' => 'doma.in',
- 'validate_url' => false,
+ 'validate_url' => true,
'delete_short_url_threshold' => 50,
- 'not_found_redirect_to' => 'foobar.com',
+ 'invalid_short_url_redirect_to' => 'foobar.com',
'redis_servers' => [
'tcp://1.1.1.1:1111',
'tcp://1.2.2.2:2222',
@@ -79,7 +79,7 @@ class SimplifiedConfigParserTest extends TestCase
'schema' => 'https',
'hostname' => 'doma.in',
],
- 'validate_url' => false,
+ 'validate_url' => true,
'visits_webhooks' => [
'http://my-api.com/api/v2.3/notify',
'https://third-party.io/foo',
@@ -125,28 +125,4 @@ class SimplifiedConfigParserTest extends TestCase
$this->assertEquals(array_merge($expected, $simplified), $result);
}
-
- /**
- * @test
- * @dataProvider provideConfigWithDeprecates
- */
- public function properlyMapsDeprecatedConfigs(array $config, string $expected): void
- {
- $result = ($this->postProcessor)($config);
- $this->assertEquals($expected, $result['not_found_redirects']['invalid_short_url']);
- }
-
- public function provideConfigWithDeprecates(): iterable
- {
- yield 'only deprecated config' => [['not_found_redirect_to' => 'old_value'], 'old_value'];
- yield 'only new config' => [['invalid_short_url_redirect_to' => 'new_value'], 'new_value'];
- yield 'both configs, new first' => [
- ['invalid_short_url_redirect_to' => 'new_value', 'not_found_redirect_to' => 'old_value'],
- 'new_value',
- ];
- yield 'both configs, deprecated first' => [
- ['not_found_redirect_to' => 'old_value', 'invalid_short_url_redirect_to' => 'new_value'],
- 'new_value',
- ];
- }
}
diff --git a/module/Core/test/Entity/VisitLocationTest.php b/module/Core/test/Entity/VisitLocationTest.php
index 2ea4befa..f662645d 100644
--- a/module/Core/test/Entity/VisitLocationTest.php
+++ b/module/Core/test/Entity/VisitLocationTest.php
@@ -10,16 +10,6 @@ use Shlinkio\Shlink\IpGeolocation\Model\Location;
class VisitLocationTest extends TestCase
{
- /** @test */
- public function valuesFoundWhenExchangingArrayAreCastToString(): void
- {
- $payload = new Location('', '', '', '', 1000.7, -2000.4, '');
- $location = new VisitLocation($payload);
-
- $this->assertSame('1000.7', $location->getLatitude());
- $this->assertSame('-2000.4', $location->getLongitude());
- }
-
/**
* @test
* @dataProvider provideArgs
diff --git a/module/Core/test/Entity/VisitTest.php b/module/Core/test/Entity/VisitTest.php
index ff2c4cec..9af71a09 100644
--- a/module/Core/test/Entity/VisitTest.php
+++ b/module/Core/test/Entity/VisitTest.php
@@ -25,9 +25,6 @@ class VisitTest extends TestCase
'date' => ($date ?? $visit->getDate())->toAtomString(),
'userAgent' => 'Chrome',
'visitLocation' => null,
-
- // Deprecated
- 'remoteAddr' => null,
], $visit->jsonSerialize());
}
diff --git a/module/PreviewGenerator/config/dependencies.config.php b/module/PreviewGenerator/config/dependencies.config.php
deleted file mode 100644
index dc7ceb96..00000000
--- a/module/PreviewGenerator/config/dependencies.config.php
+++ /dev/null
@@ -1,27 +0,0 @@
- [
- 'factories' => [
- Image\ImageBuilder::class => Image\ImageBuilderFactory::class,
- Service\PreviewGenerator::class => ConfigAbstractFactory::class,
- ],
- ],
-
- ConfigAbstractFactory::class => [
- Service\PreviewGenerator::class => [
- Image\ImageBuilder::class,
- Filesystem::class,
- 'config.preview_generation.files_location',
- ],
- ],
-
-];
diff --git a/module/PreviewGenerator/src/ConfigProvider.php b/module/PreviewGenerator/src/ConfigProvider.php
deleted file mode 100644
index 1bc2f7c5..00000000
--- a/module/PreviewGenerator/src/ConfigProvider.php
+++ /dev/null
@@ -1,16 +0,0 @@
- [
- Image::class => ImageFactory::class,
- ]]);
- }
-}
diff --git a/module/PreviewGenerator/src/Image/ImageBuilderInterface.php b/module/PreviewGenerator/src/Image/ImageBuilderInterface.php
deleted file mode 100644
index d11daab0..00000000
--- a/module/PreviewGenerator/src/Image/ImageBuilderInterface.php
+++ /dev/null
@@ -1,12 +0,0 @@
-get('config')['wkhtmltopdf'];
- $image = new Image($config['images'] ?? null);
-
- if ($options['url'] ?? null) {
- $image->setPage($options['url']);
- }
-
- return $image;
- }
-}
diff --git a/module/PreviewGenerator/src/Service/PreviewGenerator.php b/module/PreviewGenerator/src/Service/PreviewGenerator.php
deleted file mode 100644
index 54e967aa..00000000
--- a/module/PreviewGenerator/src/Service/PreviewGenerator.php
+++ /dev/null
@@ -1,58 +0,0 @@
-location = $location;
- $this->imageBuilder = $imageBuilder;
- $this->filesystem = $filesystem;
- }
-
- /**
- * Generates and stores preview for provided website and returns the path to the image file
- *
- * @throws PreviewGenerationException
- */
- public function generatePreview(string $url): string
- {
- $image = $this->imageBuilder->build(Image::class, ['url' => $url]);
-
- // If the file already exists, return its path
- $cacheId = sprintf('preview_%s.%s', urlencode($url), $image->type);
- $path = $this->location . '/' . $cacheId;
- if ($this->filesystem->exists($path)) {
- return $path;
- }
-
- // Save and check if an error occurred
- $image->saveAs($path);
- $error = $image->getError();
- if (! empty($error)) {
- throw PreviewGenerationException::fromImageError($error);
- }
-
- // Cache the path and return it
- return $path;
- }
-}
diff --git a/module/PreviewGenerator/src/Service/PreviewGeneratorInterface.php b/module/PreviewGenerator/src/Service/PreviewGeneratorInterface.php
deleted file mode 100644
index 26aefda0..00000000
--- a/module/PreviewGenerator/src/Service/PreviewGeneratorInterface.php
+++ /dev/null
@@ -1,18 +0,0 @@
-configProvider = new ConfigProvider();
- }
-
- /** @test */
- public function configIsReturned(): void
- {
- $config = ($this->configProvider)();
-
- $this->assertArrayHasKey('dependencies', $config);
- }
-}
diff --git a/module/PreviewGenerator/test/Image/ImageBuilderFactoryTest.php b/module/PreviewGenerator/test/Image/ImageBuilderFactoryTest.php
deleted file mode 100644
index 0319dafc..00000000
--- a/module/PreviewGenerator/test/Image/ImageBuilderFactoryTest.php
+++ /dev/null
@@ -1,28 +0,0 @@
-factory = new ImageBuilderFactory();
- }
-
- /** @test */
- public function serviceIsCreated()
- {
- $instance = $this->factory->__invoke(new ServiceManager(), '');
- $this->assertInstanceOf(ImageBuilder::class, $instance);
- }
-}
diff --git a/module/PreviewGenerator/test/Image/ImageFactoryTest.php b/module/PreviewGenerator/test/Image/ImageFactoryTest.php
deleted file mode 100644
index e9b9fc8e..00000000
--- a/module/PreviewGenerator/test/Image/ImageFactoryTest.php
+++ /dev/null
@@ -1,54 +0,0 @@
-factory = new ImageFactory();
- }
-
- /** @test */
- public function noPageIsSetWhenOptionsAreNotProvided()
- {
- /** @var Image $image */
- $image = $this->factory->__invoke(new ServiceManager(['services' => [
- 'config' => ['wkhtmltopdf' => []],
- ]]), '');
- $this->assertInstanceOf(Image::class, $image);
-
- $ref = new ReflectionObject($image);
- $page = $ref->getProperty('_page');
- $page->setAccessible(true);
- $this->assertNull($page->getValue($image));
- }
-
- /** @test */
- public function aPageIsSetWhenOptionsIncludeTheUrl()
- {
- $expectedPage = 'foo/bar.html';
-
- /** @var Image $image */
- $image = $this->factory->__invoke(new ServiceManager(['services' => [
- 'config' => ['wkhtmltopdf' => []],
- ]]), '', ['url' => $expectedPage]);
- $this->assertInstanceOf(Image::class, $image);
-
- $ref = new ReflectionObject($image);
- $page = $ref->getProperty('_page');
- $page->setAccessible(true);
- $this->assertEquals($expectedPage, $page->getValue($image));
- }
-}
diff --git a/module/PreviewGenerator/test/Service/PreviewGeneratorTest.php b/module/PreviewGenerator/test/Service/PreviewGeneratorTest.php
deleted file mode 100644
index 035a976b..00000000
--- a/module/PreviewGenerator/test/Service/PreviewGeneratorTest.php
+++ /dev/null
@@ -1,85 +0,0 @@
-image = $this->prophesize(Image::class);
- $this->filesystem = $this->prophesize(Filesystem::class);
-
- $this->generator = new PreviewGenerator(new ImageBuilder(new ServiceManager(), [
- 'factories' => [
- Image::class => function () {
- return $this->image->reveal();
- },
- ],
- ]), $this->filesystem->reveal(), 'dir');
- }
-
- /** @test */
- public function alreadyProcessedElementsAreNotProcessed()
- {
- $url = 'http://foo.com';
- $this->filesystem->exists(sprintf('dir/preview_%s.png', urlencode($url)))->willReturn(true)
- ->shouldBeCalledOnce();
- $this->image->saveAs(Argument::cetera())->shouldBeCalledTimes(0);
- $this->assertEquals(sprintf('dir/preview_%s.png', urlencode($url)), $this->generator->generatePreview($url));
- }
-
- /** @test */
- public function nonProcessedElementsAreProcessed()
- {
- $url = 'http://foo.com';
- $cacheId = sprintf('preview_%s.png', urlencode($url));
- $expectedPath = 'dir/' . $cacheId;
-
- $this->filesystem->exists(sprintf('dir/preview_%s.png', urlencode($url)))->willReturn(false)
- ->shouldBeCalledOnce();
-
- $this->image->saveAs($expectedPath)->shouldBeCalledOnce();
- $this->image->getError()->willReturn('')->shouldBeCalledOnce();
- $this->assertEquals($expectedPath, $this->generator->generatePreview($url));
- }
-
- /** @test */
- public function errorWhileGeneratingPreviewThrowsException()
- {
- $url = 'http://foo.com';
- $cacheId = sprintf('preview_%s.png', urlencode($url));
- $expectedPath = 'dir/' . $cacheId;
-
- $this->filesystem->exists(sprintf('dir/preview_%s.png', urlencode($url)))->willReturn(false)
- ->shouldBeCalledOnce();
-
- $this->image->saveAs($expectedPath)->shouldBeCalledOnce();
- $this->image->getError()->willReturn('Error!!')->shouldBeCalledOnce();
-
- $this->expectException(PreviewGenerationException::class);
-
- $this->generator->generatePreview($url);
- }
-}
diff --git a/module/Rest/config/auth.config.php b/module/Rest/config/auth.config.php
index 9d0987e0..f04337bf 100644
--- a/module/Rest/config/auth.config.php
+++ b/module/Rest/config/auth.config.php
@@ -10,7 +10,6 @@ return [
'auth' => [
'routes_whitelist' => [
- Action\AuthenticateAction::class,
Action\HealthAction::class,
Action\ShortUrl\SingleStepCreateShortUrlAction::class,
],
@@ -18,13 +17,10 @@ return [
'plugins' => [
'factories' => [
Authentication\Plugin\ApiKeyHeaderPlugin::class => ConfigAbstractFactory::class,
- Authentication\Plugin\AuthorizationHeaderPlugin::class => ConfigAbstractFactory::class,
],
'aliases' => [
Authentication\Plugin\ApiKeyHeaderPlugin::HEADER_NAME =>
Authentication\Plugin\ApiKeyHeaderPlugin::class,
- Authentication\Plugin\AuthorizationHeaderPlugin::HEADER_NAME =>
- Authentication\Plugin\AuthorizationHeaderPlugin::class,
],
],
],
@@ -40,7 +36,6 @@ return [
],
ConfigAbstractFactory::class => [
- Authentication\Plugin\AuthorizationHeaderPlugin::class => [Authentication\JWTService::class],
Authentication\Plugin\ApiKeyHeaderPlugin::class => [Service\ApiKeyService::class],
Authentication\RequestToHttpAuthPlugin::class => [Authentication\AuthenticationPluginManager::class],
diff --git a/module/Rest/config/dependencies.config.php b/module/Rest/config/dependencies.config.php
index ace2fda7..953d212a 100644
--- a/module/Rest/config/dependencies.config.php
+++ b/module/Rest/config/dependencies.config.php
@@ -17,10 +17,8 @@ return [
'dependencies' => [
'factories' => [
- Authentication\JWTService::class => ConfigAbstractFactory::class,
ApiKeyService::class => ConfigAbstractFactory::class,
- Action\AuthenticateAction::class => ConfigAbstractFactory::class,
Action\HealthAction::class => ConfigAbstractFactory::class,
Action\ShortUrl\CreateShortUrlAction::class => ConfigAbstractFactory::class,
Action\ShortUrl\SingleStepCreateShortUrlAction::class => ConfigAbstractFactory::class,
@@ -38,18 +36,13 @@ return [
ImplicitOptionsMiddleware::class => Middleware\EmptyResponseImplicitOptionsMiddlewareFactory::class,
Middleware\BodyParserMiddleware::class => InvokableFactory::class,
Middleware\CrossDomainMiddleware::class => InvokableFactory::class,
- Middleware\PathVersionMiddleware::class => InvokableFactory::class,
- Middleware\BackwardsCompatibleProblemDetailsMiddleware::class => ConfigAbstractFactory::class,
Middleware\ShortUrl\CreateShortUrlContentNegotiationMiddleware::class => InvokableFactory::class,
- Middleware\ShortUrl\ShortCodePathMiddleware::class => InvokableFactory::class,
],
],
ConfigAbstractFactory::class => [
- Authentication\JWTService::class => [AppOptions::class],
ApiKeyService::class => ['em'],
- Action\AuthenticateAction::class => [ApiKeyService::class, Authentication\JWTService::class, 'Logger_Shlink'],
Action\HealthAction::class => [Connection::class, AppOptions::class, 'Logger_Shlink'],
Action\ShortUrl\CreateShortUrlAction::class => [
Service\UrlShortener::class,
@@ -76,10 +69,6 @@ return [
Action\Tag\DeleteTagsAction::class => [Service\Tag\TagService::class, LoggerInterface::class],
Action\Tag\CreateTagsAction::class => [Service\Tag\TagService::class, LoggerInterface::class],
Action\Tag\UpdateTagAction::class => [Service\Tag\TagService::class, LoggerInterface::class],
-
- Middleware\BackwardsCompatibleProblemDetailsMiddleware::class => [
- 'config.backwards_compatible_problem_details.json_flags',
- ],
],
];
diff --git a/module/Rest/config/routes.config.php b/module/Rest/config/routes.config.php
index 3583a091..d210f13b 100644
--- a/module/Rest/config/routes.config.php
+++ b/module/Rest/config/routes.config.php
@@ -7,7 +7,6 @@ namespace Shlinkio\Shlink\Rest;
return [
'routes' => [
- Action\AuthenticateAction::getRouteDef(),
Action\HealthAction::getRouteDef(),
// Short codes
diff --git a/module/Rest/src/Action/AuthenticateAction.php b/module/Rest/src/Action/AuthenticateAction.php
deleted file mode 100644
index b0919aae..00000000
--- a/module/Rest/src/Action/AuthenticateAction.php
+++ /dev/null
@@ -1,64 +0,0 @@
-apiKeyService = $apiKeyService;
- $this->jwtService = $jwtService;
- }
-
- /**
- * @param Request $request
- * @return Response
- * @throws \InvalidArgumentException
- */
- public function handle(Request $request): Response
- {
- $authData = $request->getParsedBody();
- if (! isset($authData['apiKey'])) {
- return new JsonResponse([
- 'error' => 'INVALID_ARGUMENT',
- 'message' => 'You have to provide a valid API key under the "apiKey" param name.',
- ], self::STATUS_BAD_REQUEST);
- }
-
- // Authenticate using provided API key
- $apiKey = $this->apiKeyService->getByKey($authData['apiKey']);
- if ($apiKey === null || ! $apiKey->isValid()) {
- return new JsonResponse([
- 'error' => 'INVALID_API_KEY',
- 'message' => 'Provided API key does not exist or is invalid.',
- ], self::STATUS_UNAUTHORIZED);
- }
-
- // Generate a JSON Web Token that will be used for authorization in next requests
- $token = $this->jwtService->create($apiKey);
- return new JsonResponse(['token' => $token]);
- }
-}
diff --git a/module/Rest/src/Authentication/JWTService.php b/module/Rest/src/Authentication/JWTService.php
deleted file mode 100644
index 77ec6728..00000000
--- a/module/Rest/src/Authentication/JWTService.php
+++ /dev/null
@@ -1,111 +0,0 @@
-appOptions = $appOptions;
- }
-
- /**
- * Creates a new JSON web token por provided API key
- *
- * @param ApiKey $apiKey
- * @param int $lifetime
- * @return string
- */
- public function create(ApiKey $apiKey, $lifetime = self::DEFAULT_LIFETIME): string
- {
- $currentTimestamp = time();
-
- return $this->encode([
- 'iss' => (string) $this->appOptions,
- 'iat' => $currentTimestamp,
- 'exp' => $currentTimestamp + $lifetime,
- 'sub' => 'auth',
- 'key' => $apiKey->getId(), // The ID is opaque. Returning the key would be insecure
- ]);
- }
-
- /**
- * Refreshes a token and returns it with the new expiration
- *
- * @param string $jwt
- * @param int $lifetime
- * @return string
- * @throws AuthenticationException If the token has expired
- */
- public function refresh(string $jwt, $lifetime = self::DEFAULT_LIFETIME): string
- {
- $payload = $this->getPayload($jwt);
- $payload['exp'] = time() + $lifetime;
- return $this->encode($payload);
- }
-
- /**
- * Verifies that certain JWT is valid
- *
- * @param string $jwt
- * @return bool
- */
- public function verify(string $jwt): bool
- {
- try {
- // If no exception is thrown while decoding the token, it is considered valid
- $this->decode($jwt);
- return true;
- } catch (UnexpectedValueException $e) {
- return false;
- }
- }
-
- /**
- * Decodes certain token and returns the payload
- *
- * @param string $jwt
- * @return array
- * @throws AuthenticationException If the token has expired
- */
- public function getPayload(string $jwt): array
- {
- try {
- return $this->decode($jwt);
- } catch (UnexpectedValueException $e) {
- throw AuthenticationException::expiredJWT($e);
- }
- }
-
- /**
- * @param array $data
- * @return string
- */
- private function encode(array $data): string
- {
- return JWT::encode($data, $this->appOptions->getSecretKey(), self::DEFAULT_ENCRYPTION_ALG);
- }
-
- /**
- * @param string $jwt
- * @return array
- */
- private function decode(string $jwt): array
- {
- return (array) JWT::decode($jwt, $this->appOptions->getSecretKey(), [self::DEFAULT_ENCRYPTION_ALG]);
- }
-}
diff --git a/module/Rest/src/Authentication/JWTServiceInterface.php b/module/Rest/src/Authentication/JWTServiceInterface.php
deleted file mode 100644
index 0ce840f1..00000000
--- a/module/Rest/src/Authentication/JWTServiceInterface.php
+++ /dev/null
@@ -1,50 +0,0 @@
-jwtService = $jwtService;
- }
-
- /**
- * @throws VerifyAuthenticationException
- */
- public function verify(ServerRequestInterface $request): void
- {
- // Get token making sure the an authorization type is provided
- $authToken = $request->getHeaderLine(self::HEADER_NAME);
- $authTokenParts = explode(' ', $authToken);
- if (count($authTokenParts) === 1) {
- throw VerifyAuthenticationException::forMissingAuthType();
- }
-
- // Make sure the authorization type is Bearer
- [$authType, $jwt] = $authTokenParts;
- if (strtolower($authType) !== 'bearer') {
- throw VerifyAuthenticationException::forInvalidAuthType($authType);
- }
-
- try {
- if (! $this->jwtService->verify($jwt)) {
- throw $this->createInvalidTokenError();
- }
- } catch (Throwable $e) {
- throw $this->createInvalidTokenError();
- }
- }
-
- private function createInvalidTokenError(): VerifyAuthenticationException
- {
- return VerifyAuthenticationException::forInvalidAuthToken();
- }
-
- public function update(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
- {
- $authToken = $request->getHeaderLine(self::HEADER_NAME);
- [, $jwt] = explode(' ', $authToken);
- $jwt = $this->jwtService->refresh($jwt);
-
- return $response->withHeader(self::HEADER_NAME, sprintf('Bearer %s', $jwt));
- }
-}
diff --git a/module/Rest/src/Authentication/RequestToHttpAuthPlugin.php b/module/Rest/src/Authentication/RequestToHttpAuthPlugin.php
index bb6454b2..91461704 100644
--- a/module/Rest/src/Authentication/RequestToHttpAuthPlugin.php
+++ b/module/Rest/src/Authentication/RequestToHttpAuthPlugin.php
@@ -17,7 +17,6 @@ class RequestToHttpAuthPlugin implements RequestToHttpAuthPluginInterface
// When more than one is matched, the first one to be found will take precedence.
public const SUPPORTED_AUTH_HEADERS = [
Plugin\ApiKeyHeaderPlugin::HEADER_NAME,
- Plugin\AuthorizationHeaderPlugin::HEADER_NAME,
];
private AuthenticationPluginManagerInterface $authPluginManager;
diff --git a/module/Rest/src/ConfigProvider.php b/module/Rest/src/ConfigProvider.php
index 8624ad66..6352e3c7 100644
--- a/module/Rest/src/ConfigProvider.php
+++ b/module/Rest/src/ConfigProvider.php
@@ -12,6 +12,7 @@ use function sprintf;
class ConfigProvider
{
private const ROUTES_PREFIX = '/rest/v{version:1|2}';
+ private const UNVERSIONED_ROUTES_PREFIX = '/rest';
private Closure $loadConfig;
@@ -33,7 +34,11 @@ class ConfigProvider
// Prepend the routes prefix to every path
foreach ($routes as $key => $route) {
['path' => $path] = $route;
- $routes[$key]['path'] = sprintf('%s%s', self::ROUTES_PREFIX, $path);
+ $routes[$key]['path'] = sprintf(
+ '%s%s',
+ $path === '/health' ? self::UNVERSIONED_ROUTES_PREFIX : self::ROUTES_PREFIX,
+ $path,
+ );
}
return $config;
diff --git a/module/Rest/src/Exception/AuthenticationException.php b/module/Rest/src/Exception/AuthenticationException.php
deleted file mode 100644
index 3e60edb6..00000000
--- a/module/Rest/src/Exception/AuthenticationException.php
+++ /dev/null
@@ -1,16 +0,0 @@
-detail = $e->getMessage();
- $e->title = 'Invalid auth token';
- $e->type = 'INVALID_AUTH_TOKEN';
- $e->status = StatusCodeInterface::STATUS_UNAUTHORIZED;
-
- return $e;
- }
-
- /** @deprecated */
- public static function forMissingAuthType(): self
- {
- $e = new self('You need to provide the Bearer type in the Authorization header.');
-
- $e->detail = $e->getMessage();
- $e->title = 'Invalid authorization';
- $e->type = 'INVALID_AUTHORIZATION';
- $e->status = StatusCodeInterface::STATUS_UNAUTHORIZED;
-
- return $e;
- }
-
- /** @deprecated */
- public static function forInvalidAuthType(string $providedType): self
- {
- $e = new self(sprintf('Provided authorization type %s is not supported. Use Bearer instead.', $providedType));
-
- $e->detail = $e->getMessage();
- $e->title = 'Invalid authorization';
- $e->type = 'INVALID_AUTHORIZATION';
- $e->status = StatusCodeInterface::STATUS_UNAUTHORIZED;
-
- return $e;
- }
}
diff --git a/module/Rest/src/Middleware/BackwardsCompatibleProblemDetailsMiddleware.php b/module/Rest/src/Middleware/BackwardsCompatibleProblemDetailsMiddleware.php
deleted file mode 100644
index 11fce5c9..00000000
--- a/module/Rest/src/Middleware/BackwardsCompatibleProblemDetailsMiddleware.php
+++ /dev/null
@@ -1,63 +0,0 @@
- 'type',
- 'message' => 'detail',
- ];
-
- private int $jsonFlags;
-
- public function __construct(int $jsonFlags)
- {
- $this->jsonFlags = $jsonFlags;
- }
-
- public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
- {
- $resp = $handler->handle($request);
- if ($resp->getHeaderLine('Content-type') !== 'application/problem+json' || ! $this->isVersionOne($request)) {
- return $resp;
- }
-
- try {
- $body = (string) $resp->getBody();
- $payload = $this->makePayloadBackwardsCompatible(json_decode($body));
- } catch (Throwable $e) {
- return $resp;
- }
-
- return new JsonResponse($payload, $resp->getStatusCode(), $resp->getHeaders(), $this->jsonFlags);
- }
-
- private function isVersionOne(ServerRequestInterface $request): bool
- {
- $path = $request->getUri()->getPath();
- return strpos($path, '/v') === false || strpos($path, '/v1') === 0;
- }
-
- private function makePayloadBackwardsCompatible(array $payload): array
- {
- return reduce_left(self::BACKWARDS_COMPATIBLE_FIELDS, function (string $newKey, string $oldKey, $c, $acc) {
- $acc[$oldKey] = $acc[$newKey];
- return $acc;
- }, $payload);
- }
-}
diff --git a/module/Rest/src/Middleware/CrossDomainMiddleware.php b/module/Rest/src/Middleware/CrossDomainMiddleware.php
index aacda9fc..ef98eb92 100644
--- a/module/Rest/src/Middleware/CrossDomainMiddleware.php
+++ b/module/Rest/src/Middleware/CrossDomainMiddleware.php
@@ -27,7 +27,6 @@ class CrossDomainMiddleware implements MiddlewareInterface, RequestMethodInterfa
$response = $response->withHeader('Access-Control-Allow-Origin', $request->getHeader('Origin'))
->withHeader('Access-Control-Expose-Headers', implode(', ', [
Authentication\Plugin\ApiKeyHeaderPlugin::HEADER_NAME,
- Authentication\Plugin\AuthorizationHeaderPlugin::HEADER_NAME,
]));
if ($request->getMethod() !== self::METHOD_OPTIONS) {
return $response;
diff --git a/module/Rest/src/Middleware/PathVersionMiddleware.php b/module/Rest/src/Middleware/PathVersionMiddleware.php
deleted file mode 100644
index 84921710..00000000
--- a/module/Rest/src/Middleware/PathVersionMiddleware.php
+++ /dev/null
@@ -1,30 +0,0 @@
-getUri();
- $path = $uri->getPath();
-
- // If the path does not begin with the version number, prepend v1 by default for BC purposes
- if (strpos($path, '/v') !== 0) {
- $request = $request->withUri($uri->withPath('/v1' . $uri->getPath()));
- }
-
- return $handler->handle($request);
- }
-}
diff --git a/module/Rest/src/Middleware/ShortUrl/ShortCodePathMiddleware.php b/module/Rest/src/Middleware/ShortUrl/ShortCodePathMiddleware.php
deleted file mode 100644
index 683c3af5..00000000
--- a/module/Rest/src/Middleware/ShortUrl/ShortCodePathMiddleware.php
+++ /dev/null
@@ -1,34 +0,0 @@
-getUri();
- $path = $uri->getPath();
-
- // If the path starts with the old prefix, replace it by the new one
- return $handler->handle(
- $request->withUri($uri->withPath(str_replace(self::OLD_PATH_PREFIX, self::NEW_PATH_PREFIX, $path)))
- );
- }
-}
diff --git a/module/Rest/test-api/Action/CreateShortUrlActionTest.php b/module/Rest/test-api/Action/CreateShortUrlActionTest.php
index efff5f33..9ec8e8e2 100644
--- a/module/Rest/test-api/Action/CreateShortUrlActionTest.php
+++ b/module/Rest/test-api/Action/CreateShortUrlActionTest.php
@@ -49,9 +49,7 @@ class CreateShortUrlActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_BAD_REQUEST, $statusCode);
$this->assertEquals(self::STATUS_BAD_REQUEST, $payload['status']);
$this->assertEquals($detail, $payload['detail']);
- $this->assertEquals($detail, $payload['message']); // Deprecated
$this->assertEquals('INVALID_SLUG', $payload['type']);
- $this->assertEquals('INVALID_SLUG', $payload['error']); // Deprecated
$this->assertEquals('Invalid custom slug', $payload['title']);
$this->assertEquals($slug, $payload['customSlug']);
@@ -215,7 +213,7 @@ class CreateShortUrlActionTest extends ApiTestCase
}
/** @test */
- public function failsToCreateShortUrlWithInvalidOriginalUrl(): void
+ public function failsToCreateShortUrlWithInvalidLongUrl(): void
{
$url = 'https://this-has-to-be-invalid.com';
$expectedDetail = sprintf('Provided URL %s is invalid. Try with a different one.', $url);
@@ -225,9 +223,7 @@ class CreateShortUrlActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_BAD_REQUEST, $statusCode);
$this->assertEquals(self::STATUS_BAD_REQUEST, $payload['status']);
$this->assertEquals('INVALID_URL', $payload['type']);
- $this->assertEquals('INVALID_URL', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Invalid URL', $payload['title']);
$this->assertEquals($url, $payload['url']);
}
diff --git a/module/Rest/test-api/Action/DeleteShortUrlActionTest.php b/module/Rest/test-api/Action/DeleteShortUrlActionTest.php
index 4680a6f6..7bf01c51 100644
--- a/module/Rest/test-api/Action/DeleteShortUrlActionTest.php
+++ b/module/Rest/test-api/Action/DeleteShortUrlActionTest.php
@@ -19,9 +19,7 @@ class DeleteShortUrlActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
$this->assertEquals(self::STATUS_NOT_FOUND, $payload['status']);
$this->assertEquals('INVALID_SHORTCODE', $payload['type']);
- $this->assertEquals('INVALID_SHORTCODE', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Short URL not found', $payload['title']);
$this->assertEquals('invalid', $payload['shortCode']);
}
@@ -41,9 +39,7 @@ class DeleteShortUrlActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_UNPROCESSABLE_ENTITY, $resp->getStatusCode());
$this->assertEquals(self::STATUS_UNPROCESSABLE_ENTITY, $payload['status']);
$this->assertEquals('INVALID_SHORTCODE_DELETION', $payload['type']);
- $this->assertEquals('INVALID_SHORTCODE_DELETION', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Cannot delete short URL', $payload['title']);
}
}
diff --git a/module/Rest/test-api/Action/EditShortUrlActionTest.php b/module/Rest/test-api/Action/EditShortUrlActionTest.php
index bbcb043a..024ffb79 100644
--- a/module/Rest/test-api/Action/EditShortUrlActionTest.php
+++ b/module/Rest/test-api/Action/EditShortUrlActionTest.php
@@ -20,9 +20,7 @@ class EditShortUrlActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
$this->assertEquals(self::STATUS_NOT_FOUND, $payload['status']);
$this->assertEquals('INVALID_SHORTCODE', $payload['type']);
- $this->assertEquals('INVALID_SHORTCODE', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Short URL not found', $payload['title']);
$this->assertEquals('invalid', $payload['shortCode']);
}
@@ -40,9 +38,7 @@ class EditShortUrlActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_BAD_REQUEST, $resp->getStatusCode());
$this->assertEquals(self::STATUS_BAD_REQUEST, $payload['status']);
$this->assertEquals('INVALID_ARGUMENT', $payload['type']);
- $this->assertEquals('INVALID_ARGUMENT', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Invalid data', $payload['title']);
}
}
diff --git a/module/Rest/test-api/Action/EditShortUrlTagsActionTest.php b/module/Rest/test-api/Action/EditShortUrlTagsActionTest.php
index e2922092..d48ffc5f 100644
--- a/module/Rest/test-api/Action/EditShortUrlTagsActionTest.php
+++ b/module/Rest/test-api/Action/EditShortUrlTagsActionTest.php
@@ -20,9 +20,7 @@ class EditShortUrlTagsActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_BAD_REQUEST, $resp->getStatusCode());
$this->assertEquals(self::STATUS_BAD_REQUEST, $payload['status']);
$this->assertEquals('INVALID_ARGUMENT', $payload['type']);
- $this->assertEquals('INVALID_ARGUMENT', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Invalid data', $payload['title']);
}
@@ -39,9 +37,7 @@ class EditShortUrlTagsActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
$this->assertEquals(self::STATUS_NOT_FOUND, $payload['status']);
$this->assertEquals('INVALID_SHORTCODE', $payload['type']);
- $this->assertEquals('INVALID_SHORTCODE', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Short URL not found', $payload['title']);
$this->assertEquals('invalid', $payload['shortCode']);
}
diff --git a/module/Rest/test-api/Action/GetVisitsActionTest.php b/module/Rest/test-api/Action/GetVisitsActionTest.php
index 0db06848..f6167f78 100644
--- a/module/Rest/test-api/Action/GetVisitsActionTest.php
+++ b/module/Rest/test-api/Action/GetVisitsActionTest.php
@@ -19,9 +19,7 @@ class GetVisitsActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
$this->assertEquals(self::STATUS_NOT_FOUND, $payload['status']);
$this->assertEquals('INVALID_SHORTCODE', $payload['type']);
- $this->assertEquals('INVALID_SHORTCODE', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Short URL not found', $payload['title']);
$this->assertEquals('invalid', $payload['shortCode']);
}
diff --git a/module/Rest/test-api/Action/ListShortUrlsTest.php b/module/Rest/test-api/Action/ListShortUrlsTest.php
index 0952a627..f8d8c542 100644
--- a/module/Rest/test-api/Action/ListShortUrlsTest.php
+++ b/module/Rest/test-api/Action/ListShortUrlsTest.php
@@ -24,7 +24,6 @@ class ListShortUrlsTest extends ApiTestCase
'validUntil' => null,
'maxVisits' => null,
],
- 'originalUrl' => 'https://shlink.io',
];
private const SHORT_URL_CUSTOM_SLUG_AND_DOMAIN = [
'shortCode' => 'custom-with-domain',
@@ -38,7 +37,6 @@ class ListShortUrlsTest extends ApiTestCase
'validUntil' => null,
'maxVisits' => null,
],
- 'originalUrl' => 'https://google.com',
];
private const SHORT_URL_META = [
'shortCode' => 'def456',
@@ -54,9 +52,6 @@ class ListShortUrlsTest extends ApiTestCase
'validUntil' => null,
'maxVisits' => null,
],
- 'originalUrl' =>
- 'https://blog.alejandrocelaya.com/2017/12/09'
- . '/acmailer-7-0-the-most-important-release-in-a-long-time/',
];
private const SHORT_URL_CUSTOM_SLUG = [
'shortCode' => 'custom',
@@ -70,7 +65,6 @@ class ListShortUrlsTest extends ApiTestCase
'validUntil' => null,
'maxVisits' => 2,
],
- 'originalUrl' => 'https://shlink.io',
];
private const SHORT_URL_CUSTOM_DOMAIN = [
'shortCode' => 'ghi789',
@@ -86,9 +80,6 @@ class ListShortUrlsTest extends ApiTestCase
'validUntil' => null,
'maxVisits' => null,
],
- 'originalUrl' =>
- 'https://blog.alejandrocelaya.com/2019/04/27'
- . '/considerations-to-properly-use-open-source-software-projects/',
];
/**
diff --git a/module/Rest/test-api/Action/ResolveShortUrlActionTest.php b/module/Rest/test-api/Action/ResolveShortUrlActionTest.php
index e4d45f4a..09f48113 100644
--- a/module/Rest/test-api/Action/ResolveShortUrlActionTest.php
+++ b/module/Rest/test-api/Action/ResolveShortUrlActionTest.php
@@ -19,9 +19,7 @@ class ResolveShortUrlActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
$this->assertEquals(self::STATUS_NOT_FOUND, $payload['status']);
$this->assertEquals('INVALID_SHORTCODE', $payload['type']);
- $this->assertEquals('INVALID_SHORTCODE', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Short URL not found', $payload['title']);
$this->assertEquals('invalid', $payload['shortCode']);
}
diff --git a/module/Rest/test-api/Action/UpdateTagActionTest.php b/module/Rest/test-api/Action/UpdateTagActionTest.php
index fa07fcd1..eb70685a 100644
--- a/module/Rest/test-api/Action/UpdateTagActionTest.php
+++ b/module/Rest/test-api/Action/UpdateTagActionTest.php
@@ -23,9 +23,7 @@ class UpdateTagActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_BAD_REQUEST, $resp->getStatusCode());
$this->assertEquals(self::STATUS_BAD_REQUEST, $payload['status']);
$this->assertEquals('INVALID_ARGUMENT', $payload['type']);
- $this->assertEquals('INVALID_ARGUMENT', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Invalid data', $payload['title']);
}
@@ -50,9 +48,7 @@ class UpdateTagActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_NOT_FOUND, $resp->getStatusCode());
$this->assertEquals(self::STATUS_NOT_FOUND, $payload['status']);
$this->assertEquals('TAG_NOT_FOUND', $payload['type']);
- $this->assertEquals('TAG_NOT_FOUND', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Tag not found', $payload['title']);
}
@@ -70,9 +66,7 @@ class UpdateTagActionTest extends ApiTestCase
$this->assertEquals(self::STATUS_CONFLICT, $resp->getStatusCode());
$this->assertEquals(self::STATUS_CONFLICT, $payload['status']);
$this->assertEquals('TAG_CONFLICT', $payload['type']);
- $this->assertEquals('TAG_CONFLICT', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Tag conflict', $payload['title']);
}
diff --git a/module/Rest/test-api/Middleware/AuthenticationTest.php b/module/Rest/test-api/Middleware/AuthenticationTest.php
index d92f4a44..58ab396d 100644
--- a/module/Rest/test-api/Middleware/AuthenticationTest.php
+++ b/module/Rest/test-api/Middleware/AuthenticationTest.php
@@ -21,15 +21,13 @@ class AuthenticationTest extends ApiTestCase
implode('", "', RequestToHttpAuthPlugin::SUPPORTED_AUTH_HEADERS)
);
- $resp = $this->callApi(self::METHOD_GET, '/short-codes');
+ $resp = $this->callApi(self::METHOD_GET, '/short-urls');
$payload = $this->getJsonResponsePayload($resp);
$this->assertEquals(self::STATUS_UNAUTHORIZED, $resp->getStatusCode());
$this->assertEquals(self::STATUS_UNAUTHORIZED, $payload['status']);
$this->assertEquals('INVALID_AUTHORIZATION', $payload['type']);
- $this->assertEquals('INVALID_AUTHORIZATION', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Invalid authorization', $payload['title']);
}
@@ -41,7 +39,7 @@ class AuthenticationTest extends ApiTestCase
{
$expectedDetail = 'Provided API key does not exist or is invalid.';
- $resp = $this->callApi(self::METHOD_GET, '/short-codes', [
+ $resp = $this->callApi(self::METHOD_GET, '/short-urls', [
'headers' => [
Plugin\ApiKeyHeaderPlugin::HEADER_NAME => $apiKey,
],
@@ -51,9 +49,7 @@ class AuthenticationTest extends ApiTestCase
$this->assertEquals(self::STATUS_UNAUTHORIZED, $resp->getStatusCode());
$this->assertEquals(self::STATUS_UNAUTHORIZED, $payload['status']);
$this->assertEquals('INVALID_API_KEY', $payload['type']);
- $this->assertEquals('INVALID_API_KEY', $payload['error']); // Deprecated
$this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
$this->assertEquals('Invalid API key', $payload['title']);
}
@@ -63,53 +59,4 @@ class AuthenticationTest extends ApiTestCase
yield 'key which is expired' => ['expired_api_key'];
yield 'key which is disabled' => ['disabled_api_key'];
}
-
- /**
- * @test
- * @dataProvider provideInvalidAuthorizations
- */
- public function authorizationErrorIsReturnedIfInvalidDataIsProvided(
- string $authValue,
- string $expectedDetail,
- string $expectedType,
- string $expectedTitle
- ): void {
- $resp = $this->callApi(self::METHOD_GET, '/short-codes', [
- 'headers' => [
- Plugin\AuthorizationHeaderPlugin::HEADER_NAME => $authValue,
- ],
- ]);
- $payload = $this->getJsonResponsePayload($resp);
-
- $this->assertEquals(self::STATUS_UNAUTHORIZED, $resp->getStatusCode());
- $this->assertEquals(self::STATUS_UNAUTHORIZED, $payload['status']);
- $this->assertEquals($expectedType, $payload['type']);
- $this->assertEquals($expectedType, $payload['error']); // Deprecated
- $this->assertEquals($expectedDetail, $payload['detail']);
- $this->assertEquals($expectedDetail, $payload['message']); // Deprecated
- $this->assertEquals($expectedTitle, $payload['title']);
- }
-
- public function provideInvalidAuthorizations(): iterable
- {
- yield 'no type' => [
- 'invalid',
- 'You need to provide the Bearer type in the Authorization header.',
- 'INVALID_AUTHORIZATION',
- 'Invalid authorization',
- ];
- yield 'invalid type' => [
- 'Basic invalid',
- 'Provided authorization type Basic is not supported. Use Bearer instead.',
- 'INVALID_AUTHORIZATION',
- 'Invalid authorization',
- ];
- yield 'invalid JWT' => [
- 'Bearer invalid',
- 'Missing or invalid auth token provided. Perform a new authentication request and send provided '
- . 'token on every new request on the Authorization header',
- 'INVALID_AUTH_TOKEN',
- 'Invalid auth token',
- ];
- }
}
diff --git a/module/Rest/test/Action/AuthenticateActionTest.php b/module/Rest/test/Action/AuthenticateActionTest.php
deleted file mode 100644
index 84aa8fbe..00000000
--- a/module/Rest/test/Action/AuthenticateActionTest.php
+++ /dev/null
@@ -1,72 +0,0 @@
-apiKeyService = $this->prophesize(ApiKeyService::class);
- $this->jwtService = $this->prophesize(JWTService::class);
- $this->jwtService->create(Argument::cetera())->willReturn('');
-
- $this->action = new AuthenticateAction($this->apiKeyService->reveal(), $this->jwtService->reveal());
- }
-
- /** @test */
- public function notProvidingAuthDataReturnsError()
- {
- $resp = $this->action->handle(new ServerRequest());
- $this->assertEquals(400, $resp->getStatusCode());
- }
-
- /** @test */
- public function properApiKeyReturnsTokenInResponse()
- {
- $this->apiKeyService->getByKey('foo')->willReturn((new ApiKey())->setId('5'))
- ->shouldBeCalledOnce();
-
- $request = (new ServerRequest())->withParsedBody([
- 'apiKey' => 'foo',
- ]);
- $response = $this->action->handle($request);
- $this->assertEquals(200, $response->getStatusCode());
-
- $response->getBody()->rewind();
- $this->assertTrue(strpos($response->getBody()->getContents(), '"token"') > 0);
- }
-
- /** @test */
- public function invalidApiKeyReturnsErrorResponse()
- {
- $this->apiKeyService->getByKey('foo')->willReturn((new ApiKey())->disable())
- ->shouldBeCalledOnce();
-
- $request = (new ServerRequest())->withParsedBody([
- 'apiKey' => 'foo',
- ]);
- $response = $this->action->handle($request);
- $this->assertEquals(401, $response->getStatusCode());
- }
-}
diff --git a/module/Rest/test/Authentication/JWTServiceTest.php b/module/Rest/test/Authentication/JWTServiceTest.php
deleted file mode 100644
index 76375fdc..00000000
--- a/module/Rest/test/Authentication/JWTServiceTest.php
+++ /dev/null
@@ -1,86 +0,0 @@
-service = new JWTService(new AppOptions([
- 'name' => 'ShlinkTest',
- 'version' => '10000.3.1',
- 'secret_key' => 'foo',
- ]));
- }
-
- /** @test */
- public function tokenIsProperlyCreated()
- {
- $id = '34';
- $token = $this->service->create((new ApiKey())->setId($id));
- $payload = (array) JWT::decode($token, 'foo', [JWTService::DEFAULT_ENCRYPTION_ALG]);
- $this->assertGreaterThanOrEqual($payload['iat'], time());
- $this->assertGreaterThan(time(), $payload['exp']);
- $this->assertEquals($id, $payload['key']);
- $this->assertEquals('auth', $payload['sub']);
- $this->assertEquals('ShlinkTest:v10000.3.1', $payload['iss']);
- }
-
- /** @test */
- public function refreshIncreasesExpiration()
- {
- $originalLifetime = 10;
- $newLifetime = 30;
- $originalPayload = ['exp' => time() + $originalLifetime];
- $token = JWT::encode($originalPayload, 'foo');
- $newToken = $this->service->refresh($token, $newLifetime);
- $newPayload = (array) JWT::decode($newToken, 'foo', [JWTService::DEFAULT_ENCRYPTION_ALG]);
-
- $this->assertGreaterThan($originalPayload['exp'], $newPayload['exp']);
- }
-
- /** @test */
- public function verifyReturnsTrueWhenTheTokenIsCorrect()
- {
- $this->assertTrue($this->service->verify(JWT::encode([], 'foo')));
- }
-
- /** @test */
- public function verifyReturnsFalseWhenTheTokenIsCorrect()
- {
- $this->assertFalse($this->service->verify('invalidToken'));
- }
-
- /** @test */
- public function getPayloadWorksWithCorrectTokens()
- {
- $originalPayload = [
- 'exp' => time() + 10,
- 'sub' => 'testing',
- ];
- $token = JWT::encode($originalPayload, 'foo');
- $this->assertEquals($originalPayload, $this->service->getPayload($token));
- }
-
- /** @test */
- public function getPayloadThrowsExceptionWithIncorrectTokens()
- {
- $this->expectException(AuthenticationException::class);
- $this->service->getPayload('invalidToken');
- }
-}
diff --git a/module/Rest/test/Authentication/Plugin/AuthorizationHeaderPluginTest.php b/module/Rest/test/Authentication/Plugin/AuthorizationHeaderPluginTest.php
deleted file mode 100644
index 71d6eb20..00000000
--- a/module/Rest/test/Authentication/Plugin/AuthorizationHeaderPluginTest.php
+++ /dev/null
@@ -1,119 +0,0 @@
-jwtService = $this->prophesize(JWTServiceInterface::class);
- $this->plugin = new AuthorizationHeaderPlugin($this->jwtService->reveal());
- }
-
- /** @test */
- public function verifyAnAuthorizationWithoutBearerTypeThrowsException()
- {
- $authToken = 'ABC-abc';
- $request = (new ServerRequest())->withHeader(
- AuthorizationHeaderPlugin::HEADER_NAME,
- $authToken
- );
-
- $this->expectException(VerifyAuthenticationException::class);
- $this->expectExceptionMessage(sprintf(
- 'You need to provide the Bearer type in the %s header.',
- AuthorizationHeaderPlugin::HEADER_NAME
- ));
-
- $this->plugin->verify($request);
- }
-
- /** @test */
- public function verifyAnAuthorizationWithWrongTypeThrowsException()
- {
- $authToken = 'Basic ABC-abc';
- $request = (new ServerRequest())->withHeader(
- AuthorizationHeaderPlugin::HEADER_NAME,
- $authToken
- );
-
- $this->expectException(VerifyAuthenticationException::class);
- $this->expectExceptionMessage(
- 'Provided authorization type Basic is not supported. Use Bearer instead.'
- );
-
- $this->plugin->verify($request);
- }
-
- /** @test */
- public function verifyAnExpiredTokenThrowsException()
- {
- $authToken = 'Bearer ABC-abc';
- $request = (new ServerRequest())->withHeader(
- AuthorizationHeaderPlugin::HEADER_NAME,
- $authToken
- );
- $jwtVerify = $this->jwtService->verify('ABC-abc')->willReturn(false);
-
- $this->expectException(VerifyAuthenticationException::class);
- $this->expectExceptionMessage(sprintf(
- 'Missing or invalid auth token provided. Perform a new authentication request and send provided '
- . 'token on every new request on the %s header',
- AuthorizationHeaderPlugin::HEADER_NAME
- ));
-
- $this->plugin->verify($request);
-
- $jwtVerify->shouldHaveBeenCalledOnce();
- }
-
- /** @test */
- public function verifyValidTokenDoesNotThrowException()
- {
- $authToken = 'Bearer ABC-abc';
- $request = (new ServerRequest())->withHeader(
- AuthorizationHeaderPlugin::HEADER_NAME,
- $authToken
- );
- $jwtVerify = $this->jwtService->verify('ABC-abc')->willReturn(true);
-
- $this->plugin->verify($request);
-
- $jwtVerify->shouldHaveBeenCalledOnce();
- }
-
- /** @test */
- public function updateReturnsAnUpdatedResponseWithNewJwt()
- {
- $authToken = 'Bearer ABC-abc';
- $request = (new ServerRequest())->withHeader(
- AuthorizationHeaderPlugin::HEADER_NAME,
- $authToken
- );
- $jwtRefresh = $this->jwtService->refresh('ABC-abc')->willReturn('DEF-def');
-
- $response = $this->plugin->update($request, new Response());
-
- $this->assertTrue($response->hasHeader(AuthorizationHeaderPlugin::HEADER_NAME));
- $this->assertEquals('Bearer DEF-def', $response->getHeaderLine(AuthorizationHeaderPlugin::HEADER_NAME));
- $jwtRefresh->shouldHaveBeenCalledOnce();
- }
-}
diff --git a/module/Rest/test/Authentication/RequestToAuthPluginTest.php b/module/Rest/test/Authentication/RequestToAuthPluginTest.php
index d4de01a8..8b52f408 100644
--- a/module/Rest/test/Authentication/RequestToAuthPluginTest.php
+++ b/module/Rest/test/Authentication/RequestToAuthPluginTest.php
@@ -9,7 +9,6 @@ use Prophecy\Prophecy\ObjectProphecy;
use Shlinkio\Shlink\Rest\Authentication\AuthenticationPluginManagerInterface;
use Shlinkio\Shlink\Rest\Authentication\Plugin\ApiKeyHeaderPlugin;
use Shlinkio\Shlink\Rest\Authentication\Plugin\AuthenticationPluginInterface;
-use Shlinkio\Shlink\Rest\Authentication\Plugin\AuthorizationHeaderPlugin;
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPlugin;
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
use Zend\Diactoros\ServerRequest;
@@ -63,14 +62,7 @@ class RequestToAuthPluginTest extends TestCase
public function provideHeaders(): iterable
{
- yield 'API key header only' => [[
- ApiKeyHeaderPlugin::HEADER_NAME => 'foobar',
- ], ApiKeyHeaderPlugin::HEADER_NAME];
- yield 'Authorization header only' => [[
- AuthorizationHeaderPlugin::HEADER_NAME => 'foobar',
- ], AuthorizationHeaderPlugin::HEADER_NAME];
- yield 'Both headers' => [[
- AuthorizationHeaderPlugin::HEADER_NAME => 'foobar',
+ yield 'API key header' => [[
ApiKeyHeaderPlugin::HEADER_NAME => 'foobar',
], ApiKeyHeaderPlugin::HEADER_NAME];
}
diff --git a/module/Rest/test/ConfigProviderTest.php b/module/Rest/test/ConfigProviderTest.php
index b8cebf93..80919c30 100644
--- a/module/Rest/test/ConfigProviderTest.php
+++ b/module/Rest/test/ConfigProviderTest.php
@@ -33,6 +33,7 @@ class ConfigProviderTest extends TestCase
['path' => '/foo'],
['path' => '/bar'],
['path' => '/baz/foo'],
+ ['path' => '/health'],
],
]);
@@ -42,6 +43,7 @@ class ConfigProviderTest extends TestCase
['path' => '/rest/v{version:1|2}/foo'],
['path' => '/rest/v{version:1|2}/bar'],
['path' => '/rest/v{version:1|2}/baz/foo'],
+ ['path' => '/rest/health'],
], $config['routes']);
}
}
diff --git a/module/Rest/test/Exception/AuthenticationExceptionTest.php b/module/Rest/test/Exception/AuthenticationExceptionTest.php
deleted file mode 100644
index da389acb..00000000
--- a/module/Rest/test/Exception/AuthenticationExceptionTest.php
+++ /dev/null
@@ -1,32 +0,0 @@
-assertEquals($prev, $e->getPrevious());
- $this->assertEquals(-1, $e->getCode());
- $this->assertEquals('The token has expired.', $e->getMessage());
- }
-
- public function providePrev(): iterable
- {
- yield 'with previous exception' => [new Exception('Prev')];
- yield 'without previous exception' => [null];
- }
-}
diff --git a/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php b/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php
index 8bef98a1..1d306fdc 100644
--- a/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php
+++ b/module/Rest/test/Middleware/AuthenticationMiddlewareTest.php
@@ -13,7 +13,7 @@ use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Log\LoggerInterface;
-use Shlinkio\Shlink\Rest\Action\AuthenticateAction;
+use Shlinkio\Shlink\Rest\Action\HealthAction;
use Shlinkio\Shlink\Rest\Authentication\Plugin\AuthenticationPluginInterface;
use Shlinkio\Shlink\Rest\Authentication\RequestToHttpAuthPluginInterface;
use Shlinkio\Shlink\Rest\Middleware\AuthenticationMiddleware;
@@ -37,7 +37,7 @@ class AuthenticationMiddlewareTest extends TestCase
$this->middleware = new AuthenticationMiddleware(
$this->requestToPlugin->reveal(),
- [AuthenticateAction::class],
+ [HealthAction::class],
$this->logger->reveal()
);
}
@@ -72,7 +72,7 @@ class AuthenticationMiddlewareTest extends TestCase
yield 'with whitelisted route' => [(new ServerRequest())->withAttribute(
RouteResult::class,
RouteResult::fromRoute(
- new Route('foo', $dummyMiddleware, Route::HTTP_METHOD_ANY, AuthenticateAction::class)
+ new Route('foo', $dummyMiddleware, Route::HTTP_METHOD_ANY, HealthAction::class)
)
)];
yield 'with OPTIONS method' => [(new ServerRequest())->withAttribute(
diff --git a/module/Rest/test/Middleware/BackwardsCompatibleProblemDetailsMiddlewareTest.php b/module/Rest/test/Middleware/BackwardsCompatibleProblemDetailsMiddlewareTest.php
deleted file mode 100644
index 20a5b04d..00000000
--- a/module/Rest/test/Middleware/BackwardsCompatibleProblemDetailsMiddlewareTest.php
+++ /dev/null
@@ -1,94 +0,0 @@
-handler = $this->prophesize(RequestHandlerInterface::class);
- $this->middleware = new BackwardsCompatibleProblemDetailsMiddleware(0);
- }
-
- /**
- * @test
- * @dataProvider provideNonProcessableResponses
- */
- public function nonProblemDetailsOrInvalidResponsesAreReturnedAsTheyAre(
- Response $response,
- ?ServerRequest $request = null
- ): void {
- $request = $request ?? ServerRequestFactory::fromGlobals();
- $handle = $this->handler->handle($request)->willReturn($response);
-
- $result = $this->middleware->process($request, $this->handler->reveal());
-
- $this->assertSame($response, $result);
- $handle->shouldHaveBeenCalledOnce();
- }
-
- public function provideNonProcessableResponses(): iterable
- {
- yield 'no problem details' => [new Response()];
- yield 'invalid JSON' => [(new Response('data://text/plain,{invalid-json'))->withHeader(
- 'Content-Type',
- 'application/problem+json'
- )];
- yield 'version 2' => [
- (new Response())->withHeader('Content-type', 'application/problem+json'),
- ServerRequestFactory::fromGlobals()->withUri(new Uri('/v2/something')),
- ];
- }
-
- /**
- * @test
- * @dataProvider provideRequestPath
- */
- public function mapsDeprecatedPropertiesWhenRequestIsPerformedToVersionOne(string $requestPath): void
- {
- $request = ServerRequestFactory::fromGlobals()->withUri(new Uri($requestPath));
- $response = $this->jsonResponse([
- 'type' => 'the_type',
- 'detail' => 'the_detail',
- ]);
- $handle = $this->handler->handle($request)->willReturn($response);
-
- /** @var Response\JsonResponse $result */
- $result = $this->middleware->process($request, $this->handler->reveal());
- $payload = $result->getPayload();
-
- $this->assertEquals([
- 'type' => 'the_type',
- 'detail' => 'the_detail',
- 'error' => 'the_type',
- 'message' => 'the_detail',
- ], $payload);
- $handle->shouldHaveBeenCalledOnce();
- }
-
- public function provideRequestPath(): iterable
- {
- yield 'no version' => ['/foo'];
- yield 'version one' => ['/v1/foo'];
- }
-
- private function jsonResponse(array $payload, int $status = 200): Response\JsonResponse
- {
- $headers = ['Content-Type' => 'application/problem+json'];
- return new Response\JsonResponse($payload, $status, $headers);
- }
-}
diff --git a/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php b/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php
index 735338ca..28a85010 100644
--- a/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php
+++ b/module/Rest/test/Middleware/CrossDomainMiddlewareTest.php
@@ -15,7 +15,6 @@ use Zend\Diactoros\ServerRequest;
use Zend\Expressive\Router\Route;
use Zend\Expressive\Router\RouteResult;
-use function implode;
use function Zend\Stratigility\middleware;
class CrossDomainMiddlewareTest extends TestCase
@@ -62,10 +61,10 @@ class CrossDomainMiddlewareTest extends TestCase
$headers = $response->getHeaders();
$this->assertEquals('local', $response->getHeaderLine('Access-Control-Allow-Origin'));
- $this->assertEquals(implode(', ', [
+ $this->assertEquals(
Authentication\Plugin\ApiKeyHeaderPlugin::HEADER_NAME,
- Authentication\Plugin\AuthorizationHeaderPlugin::HEADER_NAME,
- ]), $response->getHeaderLine('Access-Control-Expose-Headers'));
+ $response->getHeaderLine('Access-Control-Expose-Headers')
+ );
$this->assertArrayNotHasKey('Access-Control-Allow-Methods', $headers);
$this->assertArrayNotHasKey('Access-Control-Max-Age', $headers);
$this->assertArrayNotHasKey('Access-Control-Allow-Headers', $headers);
@@ -87,10 +86,10 @@ class CrossDomainMiddlewareTest extends TestCase
$headers = $response->getHeaders();
$this->assertEquals('local', $response->getHeaderLine('Access-Control-Allow-Origin'));
- $this->assertEquals(implode(', ', [
+ $this->assertEquals(
Authentication\Plugin\ApiKeyHeaderPlugin::HEADER_NAME,
- Authentication\Plugin\AuthorizationHeaderPlugin::HEADER_NAME,
- ]), $response->getHeaderLine('Access-Control-Expose-Headers'));
+ $response->getHeaderLine('Access-Control-Expose-Headers')
+ );
$this->assertArrayHasKey('Access-Control-Allow-Methods', $headers);
$this->assertEquals('1000', $response->getHeaderLine('Access-Control-Max-Age'));
$this->assertEquals('foo, bar, baz', $response->getHeaderLine('Access-Control-Allow-Headers'));
diff --git a/module/Rest/test/Middleware/PathVersionMiddlewareTest.php b/module/Rest/test/Middleware/PathVersionMiddlewareTest.php
deleted file mode 100644
index 98e6698d..00000000
--- a/module/Rest/test/Middleware/PathVersionMiddlewareTest.php
+++ /dev/null
@@ -1,58 +0,0 @@
-middleware = new PathVersionMiddleware();
- }
-
- /** @test */
- public function whenVersionIsProvidedRequestRemainsUnchanged(): void
- {
- $request = (new ServerRequest())->withUri(new Uri('/v2/foo'));
-
- $delegate = $this->prophesize(RequestHandlerInterface::class);
- $process = $delegate->handle($request)->willReturn(new Response());
-
- $this->middleware->process($request, $delegate->reveal());
-
- $process->shouldHaveBeenCalled();
- }
-
- /** @test */
- public function versionOneIsPrependedWhenNoVersionIsDefined(): void
- {
- $request = (new ServerRequest())->withUri(new Uri('/bar/baz'));
-
- $delegate = $this->prophesize(RequestHandlerInterface::class);
- $delegate->handle(Argument::type(Request::class))->will(function (array $args) use ($request) {
- $req = array_shift($args);
-
- Assert::assertNotSame($request, $req);
- Assert::assertEquals('/v1/bar/baz', $req->getUri()->getPath());
- return new Response();
- });
-
-
- $this->middleware->process($request, $delegate->reveal());
- }
-}
diff --git a/module/Rest/test/Middleware/ShortUrl/ShortCodePathMiddlewareTest.php b/module/Rest/test/Middleware/ShortUrl/ShortCodePathMiddlewareTest.php
deleted file mode 100644
index fb1ae215..00000000
--- a/module/Rest/test/Middleware/ShortUrl/ShortCodePathMiddlewareTest.php
+++ /dev/null
@@ -1,49 +0,0 @@
-middleware = new ShortCodePathMiddleware();
- $this->requestHandler = $this->prophesize(RequestHandlerInterface::class);
- $this->requestHandler->handle(Argument::type(ServerRequestInterface::class))->willReturn(new Response());
- }
-
- /** @test */
- public function properlyReplacesTheOldPathByTheNewOne()
- {
- $uri = new Uri('/short-codes/foo');
-
- $request = $this->prophesize(ServerRequestInterface::class);
- $request->getUri()->willReturn($uri);
- $withUri = $request->withUri(Argument::that(function (UriInterface $uri) {
- $path = $uri->getPath();
-
- Assert::assertStringContainsString('/short-urls', $path);
- Assert::assertStringNotContainsString('/short-codes', $path);
-
- return $uri;
- }))->willReturn($request->reveal());
-
- $this->middleware->process($request->reveal(), $this->requestHandler->reveal());
-
- $withUri->shouldHaveBeenCalledOnce();
- }
-}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 67d08507..03f73521 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -15,9 +15,6 @@
./module/CLI/test
-
- ./module/PreviewGenerator/test
-