From 6112e17bef0572c716bb9fb2da2c84005c8166ff Mon Sep 17 00:00:00 2001 From: Wendell Adriel Date: Fri, 26 Apr 2024 17:07:14 +0100 Subject: [PATCH 1/8] Remove Laravel Sanctum --- composer.json | 21 +- composer.lock | 605 +++++++++++++++++++++++++++------------------ config/sanctum.php | 69 ------ 3 files changed, 382 insertions(+), 313 deletions(-) delete mode 100644 config/sanctum.php diff --git a/composer.json b/composer.json index 45836c2..c43f6f2 100644 --- a/composer.json +++ b/composer.json @@ -24,12 +24,11 @@ "php": "^8.3", "ext-curl": "*", "guzzlehttp/guzzle": "^7.8", - "laravel/framework": "^11.1", - "laravel/sanctum": "^4.0", + "laravel/framework": "^11.5", "laravel/tinker": "^2.9", "strictus/strictus": "^1.3", "wendelladriel/laravel-validated-dto": "^3.5", - "zircote/swagger-php": "^4.8" + "zircote/swagger-php": "^4.9" }, "require-dev": { "fakerphp/faker": "^1.23", @@ -38,8 +37,8 @@ "nunomaduro/collision": "^8.1", "pestphp/pest": "^2.34", "pestphp/pest-plugin-laravel": "^2.3", - "phpunit/phpunit": "^10.5", - "spatie/laravel-ignition": "^2.4" + "pestphp/pest-plugin-type-coverage": "*", + "spatie/laravel-ignition": "^2.5" }, "autoload": { "psr-4": { @@ -56,9 +55,15 @@ } }, "scripts": { - "lint": ["pint"], - "test": ["pest"], - "swagger": ["sh ./tools/swagger.sh"], + "lint": [ + "pint" + ], + "test": [ + "pest" + ], + "swagger": [ + "sh ./tools/swagger.sh" + ], "prepare": [ "pint --dirty", "@swagger" diff --git a/composer.lock b/composer.lock index 9f7370a..a784029 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "30084a7b0d3b13b1ba7873017b660eae", + "content-hash": "b2e575ae1fed7385093e6c4b96483ab1", "packages": [ { "name": "brick/math", @@ -1047,16 +1047,16 @@ }, { "name": "laravel/framework", - "version": "v11.1.0", + "version": "v11.5.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "4a9195f68b529b20fe01e24864f99991459c48d4" + "reference": "e3c24268f1404805e15099b9f035fe310cb30753" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/4a9195f68b529b20fe01e24864f99991459c48d4", - "reference": "4a9195f68b529b20fe01e24864f99991459c48d4", + "url": "https://api.github.com/repos/laravel/framework/zipball/e3c24268f1404805e15099b9f035fe310cb30753", + "reference": "e3c24268f1404805e15099b9f035fe310cb30753", "shasum": "" }, "require": { @@ -1075,7 +1075,7 @@ "fruitcake/php-cors": "^1.3", "guzzlehttp/guzzle": "^7.8", "guzzlehttp/uri-template": "^1.0", - "laravel/prompts": "^0.1.15", + "laravel/prompts": "^0.1.18", "laravel/serializable-closure": "^1.3", "league/commonmark": "^2.2.1", "league/flysystem": "^3.8.0", @@ -1248,20 +1248,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-03-26T15:17:39+00:00" + "time": "2024-04-23T15:11:31+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.17", + "version": "v0.1.20", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "8ee9f87f7f9eadcbe21e9e72cd4176b2f06cd5b5" + "reference": "bf9a360c484976692de0f3792f30066f4f4b34a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/8ee9f87f7f9eadcbe21e9e72cd4176b2f06cd5b5", - "reference": "8ee9f87f7f9eadcbe21e9e72cd4176b2f06cd5b5", + "url": "https://api.github.com/repos/laravel/prompts/zipball/bf9a360c484976692de0f3792f30066f4f4b34a2", + "reference": "bf9a360c484976692de0f3792f30066f4f4b34a2", "shasum": "" }, "require": { @@ -1303,73 +1303,9 @@ ], "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.17" + "source": "https://github.com/laravel/prompts/tree/v0.1.20" }, - "time": "2024-03-13T16:05:43+00:00" - }, - { - "name": "laravel/sanctum", - "version": "v4.0.1", - "source": { - "type": "git", - "url": "https://github.com/laravel/sanctum.git", - "reference": "d1de99bf8d31199aaf93881561622489ab91ba58" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/d1de99bf8d31199aaf93881561622489ab91ba58", - "reference": "d1de99bf8d31199aaf93881561622489ab91ba58", - "shasum": "" - }, - "require": { - "ext-json": "*", - "illuminate/console": "^11.0", - "illuminate/contracts": "^11.0", - "illuminate/database": "^11.0", - "illuminate/support": "^11.0", - "php": "^8.2", - "symfony/console": "^7.0" - }, - "require-dev": { - "mockery/mockery": "^1.6", - "orchestra/testbench": "^9.0", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Laravel\\Sanctum\\SanctumServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Laravel\\Sanctum\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.", - "keywords": [ - "auth", - "laravel", - "sanctum" - ], - "support": { - "issues": "https://github.com/laravel/sanctum/issues", - "source": "https://github.com/laravel/sanctum" - }, - "time": "2024-03-19T20:09:38+00:00" + "time": "2024-04-18T00:45:25+00:00" }, { "name": "laravel/serializable-closure", @@ -1687,16 +1623,16 @@ }, { "name": "league/flysystem", - "version": "3.26.0", + "version": "3.27.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "072735c56cc0da00e10716dd90d5a7f7b40b36be" + "reference": "4729745b1ab737908c7d055148c9a6b3e959832f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/072735c56cc0da00e10716dd90d5a7f7b40b36be", - "reference": "072735c56cc0da00e10716dd90d5a7f7b40b36be", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4729745b1ab737908c7d055148c9a6b3e959832f", + "reference": "4729745b1ab737908c7d055148c9a6b3e959832f", "shasum": "" }, "require": { @@ -1761,7 +1697,7 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.26.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.27.0" }, "funding": [ { @@ -1773,7 +1709,7 @@ "type": "github" } ], - "time": "2024-03-25T11:49:53+00:00" + "time": "2024-04-07T19:17:50+00:00" }, { "name": "league/flysystem-local", @@ -1892,16 +1828,16 @@ }, { "name": "monolog/monolog", - "version": "3.5.0", + "version": "3.6.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448" + "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c915e2634718dbc8a4a15c61b0e62e7a44e14448", - "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", + "reference": "4b18b21a5527a3d5ffdac2fd35d3ab25a9597654", "shasum": "" }, "require": { @@ -1924,7 +1860,7 @@ "phpstan/phpstan": "^1.9", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-strict-rules": "^1.4", - "phpunit/phpunit": "^10.1", + "phpunit/phpunit": "^10.5.17", "predis/predis": "^1.1 || ^2", "ruflin/elastica": "^7", "symfony/mailer": "^5.4 || ^6", @@ -1977,7 +1913,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.5.0" + "source": "https://github.com/Seldaek/monolog/tree/3.6.0" }, "funding": [ { @@ -1989,20 +1925,20 @@ "type": "tidelift" } ], - "time": "2023-10-27T15:32:31+00:00" + "time": "2024-04-12T21:02:21+00:00" }, { "name": "nesbot/carbon", - "version": "3.2.2", + "version": "3.3.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "2d69b6de67e2a3c0652d0c9dfcfda8b4563c4cee" + "reference": "7219739c4e01d4680c980545821733b6ed8ee880" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/2d69b6de67e2a3c0652d0c9dfcfda8b4563c4cee", - "reference": "2d69b6de67e2a3c0652d0c9dfcfda8b4563c4cee", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7219739c4e01d4680c980545821733b6ed8ee880", + "reference": "7219739c4e01d4680c980545821733b6ed8ee880", "shasum": "" }, "require": { @@ -2095,7 +2031,7 @@ "type": "tidelift" } ], - "time": "2024-03-28T12:59:49+00:00" + "time": "2024-04-18T16:35:06+00:00" }, { "name": "nette/schema", @@ -2880,16 +2816,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.2", + "version": "v0.12.3", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "9185c66c2165bbf4d71de78a69dccf4974f9538d" + "reference": "b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/9185c66c2165bbf4d71de78a69dccf4974f9538d", - "reference": "9185c66c2165bbf4d71de78a69dccf4974f9538d", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73", + "reference": "b6b6cce7d3ee8fbf31843edce5e8f5a72eff4a73", "shasum": "" }, "require": { @@ -2953,9 +2889,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.2" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.3" }, - "time": "2024-03-17T01:53:00+00:00" + "time": "2024-04-02T15:57:53+00:00" }, { "name": "ralouphie/getallheaders", @@ -3327,16 +3263,16 @@ }, { "name": "symfony/console", - "version": "v7.0.4", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f" + "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6b099f3306f7c9c2d2786ed736d0026b2903205f", - "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f", + "url": "https://api.github.com/repos/symfony/console/zipball/fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", + "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", "shasum": "" }, "require": { @@ -3400,7 +3336,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.0.4" + "source": "https://github.com/symfony/console/tree/v7.0.6" }, "funding": [ { @@ -3416,7 +3352,7 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:20+00:00" + "time": "2024-04-01T11:04:53+00:00" }, { "name": "symfony/css-selector", @@ -3552,16 +3488,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.0.4", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "677b24759decff69e65b1e9d1471d90f95ced880" + "reference": "46a4cc138f799886d4bd70477c55c699d3e9dfc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/677b24759decff69e65b1e9d1471d90f95ced880", - "reference": "677b24759decff69e65b1e9d1471d90f95ced880", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/46a4cc138f799886d4bd70477c55c699d3e9dfc8", + "reference": "46a4cc138f799886d4bd70477c55c699d3e9dfc8", "shasum": "" }, "require": { @@ -3607,7 +3543,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.0.4" + "source": "https://github.com/symfony/error-handler/tree/v7.0.6" }, "funding": [ { @@ -3623,7 +3559,7 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:20+00:00" + "time": "2024-03-19T11:57:22+00:00" }, { "name": "symfony/event-dispatcher", @@ -3707,16 +3643,16 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.4.0", + "version": "v3.4.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" + "reference": "4e64b49bf370ade88e567de29465762e316e4224" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/4e64b49bf370ade88e567de29465762e316e4224", + "reference": "4e64b49bf370ade88e567de29465762e316e4224", "shasum": "" }, "require": { @@ -3763,7 +3699,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.2" }, "funding": [ { @@ -3779,7 +3715,7 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "symfony/finder", @@ -3847,16 +3783,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.0.4", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "439fdfdd344943254b1ef6278613e79040548045" + "reference": "8789625dcf36e5fbf753014678a1e090f1bc759c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/439fdfdd344943254b1ef6278613e79040548045", - "reference": "439fdfdd344943254b1ef6278613e79040548045", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8789625dcf36e5fbf753014678a1e090f1bc759c", + "reference": "8789625dcf36e5fbf753014678a1e090f1bc759c", "shasum": "" }, "require": { @@ -3904,7 +3840,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.0.4" + "source": "https://github.com/symfony/http-foundation/tree/v7.0.6" }, "funding": [ { @@ -3920,20 +3856,20 @@ "type": "tidelift" } ], - "time": "2024-02-08T19:22:56+00:00" + "time": "2024-03-19T11:46:48+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.0.5", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "37c24ca28f65e3121a68f3dd4daeb36fb1fa2a72" + "reference": "34c872391046d59af804af62d4573b829cfe4824" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/37c24ca28f65e3121a68f3dd4daeb36fb1fa2a72", - "reference": "37c24ca28f65e3121a68f3dd4daeb36fb1fa2a72", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/34c872391046d59af804af62d4573b829cfe4824", + "reference": "34c872391046d59af804af62d4573b829cfe4824", "shasum": "" }, "require": { @@ -4016,7 +3952,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.0.5" + "source": "https://github.com/symfony/http-kernel/tree/v7.0.6" }, "funding": [ { @@ -4032,20 +3968,20 @@ "type": "tidelift" } ], - "time": "2024-03-04T21:05:24+00:00" + "time": "2024-04-03T06:12:25+00:00" }, { "name": "symfony/mailer", - "version": "v7.0.4", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85" + "reference": "eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/72e16d87bf50a3ce195b9470c06bb9d7b816ea85", - "reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85", + "url": "https://api.github.com/repos/symfony/mailer/zipball/eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0", + "reference": "eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0", "shasum": "" }, "require": { @@ -4096,7 +4032,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.0.4" + "source": "https://github.com/symfony/mailer/tree/v7.0.6" }, "funding": [ { @@ -4112,20 +4048,20 @@ "type": "tidelift" } ], - "time": "2024-02-03T21:34:19+00:00" + "time": "2024-03-28T09:20:36+00:00" }, { "name": "symfony/mime", - "version": "v7.0.3", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716" + "reference": "99362408c9abdf8c7cadcf0529b6fc8b16f5ace2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716", - "reference": "c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716", + "url": "https://api.github.com/repos/symfony/mime/zipball/99362408c9abdf8c7cadcf0529b6fc8b16f5ace2", + "reference": "99362408c9abdf8c7cadcf0529b6fc8b16f5ace2", "shasum": "" }, "require": { @@ -4145,6 +4081,7 @@ "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", "symfony/property-access": "^6.4|^7.0", "symfony/property-info": "^6.4|^7.0", "symfony/serializer": "^6.4|^7.0" @@ -4179,7 +4116,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.0.3" + "source": "https://github.com/symfony/mime/tree/v7.0.6" }, "funding": [ { @@ -4195,7 +4132,7 @@ "type": "tidelift" } ], - "time": "2024-01-30T08:34:29+00:00" + "time": "2024-03-21T19:37:36+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4971,16 +4908,16 @@ }, { "name": "symfony/routing", - "version": "v7.0.5", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "ba6bf07d43289c6a4b4591ddb75bc3bc5f069c19" + "reference": "cded64e5bbf9f31786f1055fcc76718fdd77519c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/ba6bf07d43289c6a4b4591ddb75bc3bc5f069c19", - "reference": "ba6bf07d43289c6a4b4591ddb75bc3bc5f069c19", + "url": "https://api.github.com/repos/symfony/routing/zipball/cded64e5bbf9f31786f1055fcc76718fdd77519c", + "reference": "cded64e5bbf9f31786f1055fcc76718fdd77519c", "shasum": "" }, "require": { @@ -5032,7 +4969,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.0.5" + "source": "https://github.com/symfony/routing/tree/v7.0.6" }, "funding": [ { @@ -5048,20 +4985,20 @@ "type": "tidelift" } ], - "time": "2024-02-27T12:34:35+00:00" + "time": "2024-03-28T21:02:11+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.4.1", + "version": "v3.4.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + "reference": "11bbf19a0fb7b36345861e85c5768844c552906e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e", + "reference": "11bbf19a0fb7b36345861e85c5768844c552906e", "shasum": "" }, "require": { @@ -5114,7 +5051,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.2" }, "funding": [ { @@ -5130,7 +5067,7 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2023-12-19T21:51:00+00:00" }, { "name": "symfony/string", @@ -5314,16 +5251,16 @@ }, { "name": "symfony/translation-contracts", - "version": "v3.4.1", + "version": "v3.4.2", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "06450585bf65e978026bda220cdebca3f867fde7" + "reference": "43810bdb2ddb5400e5c5e778e27b210a0ca83b6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", - "reference": "06450585bf65e978026bda220cdebca3f867fde7", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/43810bdb2ddb5400e5c5e778e27b210a0ca83b6b", + "reference": "43810bdb2ddb5400e5c5e778e27b210a0ca83b6b", "shasum": "" }, "require": { @@ -5372,7 +5309,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.4.2" }, "funding": [ { @@ -5388,7 +5325,7 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2024-01-23T14:51:35+00:00" }, { "name": "symfony/uid", @@ -5466,16 +5403,16 @@ }, { "name": "symfony/var-dumper", - "version": "v7.0.4", + "version": "v7.0.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670" + "reference": "66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e03ad7c1535e623edbb94c22cc42353e488c6670", - "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb", + "reference": "66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb", "shasum": "" }, "require": { @@ -5529,7 +5466,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.0.4" + "source": "https://github.com/symfony/var-dumper/tree/v7.0.6" }, "funding": [ { @@ -5545,7 +5482,7 @@ "type": "tidelift" } ], - "time": "2024-02-15T11:33:06+00:00" + "time": "2024-03-19T11:57:22+00:00" }, { "name": "symfony/yaml", @@ -5889,16 +5826,16 @@ }, { "name": "wendelladriel/laravel-validated-dto", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/WendellAdriel/laravel-validated-dto.git", - "reference": "f19c131dc19c5ddbb16a3ebed843858fb8586981" + "reference": "1261251fe3ccb2afef0faa96108b74a8ac1557e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WendellAdriel/laravel-validated-dto/zipball/f19c131dc19c5ddbb16a3ebed843858fb8586981", - "reference": "f19c131dc19c5ddbb16a3ebed843858fb8586981", + "url": "https://api.github.com/repos/WendellAdriel/laravel-validated-dto/zipball/1261251fe3ccb2afef0faa96108b74a8ac1557e6", + "reference": "1261251fe3ccb2afef0faa96108b74a8ac1557e6", "shasum": "" }, "require": { @@ -5959,20 +5896,20 @@ "type": "github" } ], - "time": "2024-03-13T12:47:19+00:00" + "time": "2024-04-08T09:49:39+00:00" }, { "name": "zircote/swagger-php", - "version": "4.8.7", + "version": "4.9.0", "source": { "type": "git", "url": "https://github.com/zircote/swagger-php.git", - "reference": "2357fafbb084be0f9eda7b5c1a659704fed65b28" + "reference": "b46a36d006f4db4d761995a5add1e7ab0386ed1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zircote/swagger-php/zipball/2357fafbb084be0f9eda7b5c1a659704fed65b28", - "reference": "2357fafbb084be0f9eda7b5c1a659704fed65b28", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/b46a36d006f4db4d761995a5add1e7ab0386ed1d", + "reference": "b46a36d006f4db4d761995a5add1e7ab0386ed1d", "shasum": "" }, "require": { @@ -6038,9 +5975,9 @@ ], "support": { "issues": "https://github.com/zircote/swagger-php/issues", - "source": "https://github.com/zircote/swagger-php/tree/4.8.7" + "source": "https://github.com/zircote/swagger-php/tree/4.9.0" }, - "time": "2024-03-23T06:35:46+00:00" + "time": "2024-04-18T22:32:11+00:00" } ], "packages-dev": [ @@ -6492,16 +6429,16 @@ }, { "name": "laravel/pint", - "version": "v1.15.0", + "version": "v1.15.2", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "c52de679b3ac01207016c179d7ce173e4be128c4" + "reference": "2c9f8004899815f3f0ee3cb28ef7281e2b589134" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/c52de679b3ac01207016c179d7ce173e4be128c4", - "reference": "c52de679b3ac01207016c179d7ce173e4be128c4", + "url": "https://api.github.com/repos/laravel/pint/zipball/2c9f8004899815f3f0ee3cb28ef7281e2b589134", + "reference": "2c9f8004899815f3f0ee3cb28ef7281e2b589134", "shasum": "" }, "require": { @@ -6512,13 +6449,13 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.49.0", - "illuminate/view": "^10.43.0", - "larastan/larastan": "^2.8.1", + "friendsofphp/php-cs-fixer": "^3.54.0", + "illuminate/view": "^10.48.8", + "larastan/larastan": "^2.9.5", "laravel-zero/framework": "^10.3.0", - "mockery/mockery": "^1.6.7", + "mockery/mockery": "^1.6.11", "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.33.6" + "pestphp/pest": "^2.34.7" }, "bin": [ "builds/pint" @@ -6554,7 +6491,7 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-03-26T16:40:24+00:00" + "time": "2024-04-23T15:42:34+00:00" }, { "name": "mockery/mockery", @@ -6797,16 +6734,16 @@ }, { "name": "pestphp/pest", - "version": "v2.34.6", + "version": "v2.34.7", "source": { "type": "git", "url": "https://github.com/pestphp/pest.git", - "reference": "680111fb1e7175a5010b73c115edef58ceef303e" + "reference": "a7a3e4240e341d0fee1c54814ce18adc26ce5a76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/680111fb1e7175a5010b73c115edef58ceef303e", - "reference": "680111fb1e7175a5010b73c115edef58ceef303e", + "url": "https://api.github.com/repos/pestphp/pest/zipball/a7a3e4240e341d0fee1c54814ce18adc26ce5a76", + "reference": "a7a3e4240e341d0fee1c54814ce18adc26ce5a76", "shasum": "" }, "require": { @@ -6816,10 +6753,10 @@ "pestphp/pest-plugin": "^2.1.1", "pestphp/pest-plugin-arch": "^2.7.0", "php": "^8.1.0", - "phpunit/phpunit": "^10.5.16" + "phpunit/phpunit": "^10.5.17" }, "conflict": { - "phpunit/phpunit": ">10.5.16", + "phpunit/phpunit": ">10.5.17", "sebastian/exporter": "<5.1.0", "webmozart/assert": "<1.11.0" }, @@ -6889,7 +6826,7 @@ ], "support": { "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v2.34.6" + "source": "https://github.com/pestphp/pest/tree/v2.34.7" }, "funding": [ { @@ -6901,7 +6838,7 @@ "type": "github" } ], - "time": "2024-03-28T11:36:46+00:00" + "time": "2024-04-05T07:44:17+00:00" }, { "name": "pestphp/pest-plugin", @@ -7118,6 +7055,79 @@ ], "time": "2024-02-17T10:04:08+00:00" }, + { + "name": "pestphp/pest-plugin-type-coverage", + "version": "v2.8.1", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin-type-coverage.git", + "reference": "4be0cf0faca7d207c5d97af8ab68a450ebf8da24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin-type-coverage/zipball/4be0cf0faca7d207c5d97af8ab68a450ebf8da24", + "reference": "4be0cf0faca7d207c5d97af8ab68a450ebf8da24", + "shasum": "" + }, + "require": { + "pestphp/pest-plugin": "^2.1.1", + "php": "^8.1", + "phpstan/phpstan": "^1.10.60", + "tomasvotruba/type-coverage": "^0.2.1" + }, + "require-dev": { + "pestphp/pest": "^2.30.0", + "pestphp/pest-dev-tools": "^2.16.0" + }, + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Pest\\TypeCoverage\\Plugin" + ] + } + }, + "autoload": { + "psr-4": { + "Pest\\TypeCoverage\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Type Coverage plugin for Pest PHP.", + "keywords": [ + "coverage", + "framework", + "pest", + "php", + "plugin", + "test", + "testing", + "type-coverage", + "unit" + ], + "support": { + "issues": "https://github.com/pestphp/pest-plugin-type-coverage/issues", + "source": "https://github.com/pestphp/pest-plugin-type-coverage/tree/v2.8.1" + }, + "funding": [ + { + "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2024-03-08T09:48:04+00:00" + }, { "name": "phar-io/manifest", "version": "2.0.4", @@ -7291,28 +7301,35 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", + "version": "5.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + "reference": "298d2febfe79d03fe714eb871d5538da55205b1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/298d2febfe79d03fe714eb871d5538da55205b1a", + "reference": "298d2febfe79d03fe714eb871d5538da55205b1a", "shasum": "" }, "require": { + "doctrine/deprecations": "^1.1", "ext-filter": "*", - "php": "^7.2 || ^8.0", + "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7", "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" + "mockery/mockery": "~1.3.5", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.13" }, "type": "library", "extra": { @@ -7336,15 +7353,15 @@ }, { "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" + "email": "opensource@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.0" }, - "time": "2021-10-19T17:43:47+00:00" + "time": "2024-04-09T21:13:58+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -7406,16 +7423,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "1.27.0", + "version": "1.28.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "86e4d5a4b036f8f0be1464522f4c6b584c452757" + "reference": "cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/86e4d5a4b036f8f0be1464522f4c6b584c452757", - "reference": "86e4d5a4b036f8f0be1464522f4c6b584c452757", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb", + "reference": "cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb", "shasum": "" }, "require": { @@ -7447,9 +7464,67 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.27.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.28.0" + }, + "time": "2024-04-03T18:51:33+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.10.67", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/16ddbe776f10da6a95ebd25de7c1dbed397dc493", + "reference": "16ddbe776f10da6a95ebd25de7c1dbed397dc493", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" }, - "time": "2024-03-21T13:14:53+00:00" + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2024-04-16T07:22:02+00:00" }, { "name": "phpunit/php-code-coverage", @@ -7774,16 +7849,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.16", + "version": "10.5.17", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "18f8d4a5f52b61fdd9370aaae3167daa0eeb69cd" + "reference": "c1f736a473d21957ead7e94fcc029f571895abf5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/18f8d4a5f52b61fdd9370aaae3167daa0eeb69cd", - "reference": "18f8d4a5f52b61fdd9370aaae3167daa0eeb69cd", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c1f736a473d21957ead7e94fcc029f571895abf5", + "reference": "c1f736a473d21957ead7e94fcc029f571895abf5", "shasum": "" }, "require": { @@ -7855,7 +7930,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.16" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.17" }, "funding": [ { @@ -7871,7 +7946,7 @@ "type": "tidelift" } ], - "time": "2024-03-28T10:08:10+00:00" + "time": "2024-04-05T04:39:01+00:00" }, { "name": "sebastian/cli-parser", @@ -8791,16 +8866,16 @@ }, { "name": "spatie/backtrace", - "version": "1.5.3", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab" + "reference": "8373b9d51638292e3bfd736a9c19a654111b4a23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/483f76a82964a0431aa836b6ed0edde0c248e3ab", - "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/8373b9d51638292e3bfd736a9c19a654111b4a23", + "reference": "8373b9d51638292e3bfd736a9c19a654111b4a23", "shasum": "" }, "require": { @@ -8808,6 +8883,7 @@ }, "require-dev": { "ext-json": "*", + "laravel/serializable-closure": "^1.3", "phpunit/phpunit": "^9.3", "spatie/phpunit-snapshot-assertions": "^4.2", "symfony/var-dumper": "^5.1" @@ -8837,7 +8913,7 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.5.3" + "source": "https://github.com/spatie/backtrace/tree/1.6.1" }, "funding": [ { @@ -8849,7 +8925,7 @@ "type": "other" } ], - "time": "2023-06-28T12:59:17+00:00" + "time": "2024-04-24T13:22:11+00:00" }, { "name": "spatie/flare-client-php", @@ -8922,16 +8998,16 @@ }, { "name": "spatie/ignition", - "version": "1.12.0", + "version": "1.14.0", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "5b6f801c605a593106b623e45ca41496a6e7d56d" + "reference": "80385994caed328f6f9c9952926932e65b9b774c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/5b6f801c605a593106b623e45ca41496a6e7d56d", - "reference": "5b6f801c605a593106b623e45ca41496a6e7d56d", + "url": "https://api.github.com/repos/spatie/ignition/zipball/80385994caed328f6f9c9952926932e65b9b774c", + "reference": "80385994caed328f6f9c9952926932e65b9b774c", "shasum": "" }, "require": { @@ -9001,20 +9077,20 @@ "type": "github" } ], - "time": "2024-01-03T15:49:39+00:00" + "time": "2024-04-26T08:45:51+00:00" }, { "name": "spatie/laravel-ignition", - "version": "2.4.2", + "version": "2.5.2", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "351504f4570e32908839fc5a2dc53bf77d02f85e" + "reference": "c93fcadcc4629775c839ac9a90916f07a660266f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/351504f4570e32908839fc5a2dc53bf77d02f85e", - "reference": "351504f4570e32908839fc5a2dc53bf77d02f85e", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/c93fcadcc4629775c839ac9a90916f07a660266f", + "reference": "c93fcadcc4629775c839ac9a90916f07a660266f", "shasum": "" }, "require": { @@ -9024,7 +9100,7 @@ "illuminate/support": "^10.0|^11.0", "php": "^8.1", "spatie/flare-client-php": "^1.3.5", - "spatie/ignition": "^1.9", + "spatie/ignition": "^1.13.2", "symfony/console": "^6.2.3|^7.0", "symfony/var-dumper": "^6.2.3|^7.0" }, @@ -9093,7 +9169,7 @@ "type": "github" } ], - "time": "2024-02-09T16:08:40+00:00" + "time": "2024-04-16T08:57:16+00:00" }, { "name": "ta-tikoma/phpunit-architecture-test", @@ -9203,6 +9279,63 @@ } ], "time": "2024-03-03T12:36:25+00:00" + }, + { + "name": "tomasvotruba/type-coverage", + "version": "0.2.8", + "source": { + "type": "git", + "url": "https://github.com/TomasVotruba/type-coverage.git", + "reference": "ab4f0506f8df8c6418ec877e356c0efd2c50ed6b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/TomasVotruba/type-coverage/zipball/ab4f0506f8df8c6418ec877e356c0efd2c50ed6b", + "reference": "ab4f0506f8df8c6418ec877e356c0efd2c50ed6b", + "shasum": "" + }, + "require": { + "nette/utils": "^3.2 || ^4.0", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.9.3" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "config/extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "TomasVotruba\\TypeCoverage\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Measure type coverage of your project", + "keywords": [ + "phpstan-extension", + "static analysis" + ], + "support": { + "issues": "https://github.com/TomasVotruba/type-coverage/issues", + "source": "https://github.com/TomasVotruba/type-coverage/tree/0.2.8" + }, + "funding": [ + { + "url": "https://www.paypal.me/rectorphp", + "type": "custom" + }, + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2024-04-26T13:56:40+00:00" } ], "aliases": [], diff --git a/config/sanctum.php b/config/sanctum.php deleted file mode 100644 index 66598f0..0000000 --- a/config/sanctum.php +++ /dev/null @@ -1,69 +0,0 @@ - explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( - '%s%s', - 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', - Sanctum::currentApplicationUrlWithPort() - ))), - - /* - |-------------------------------------------------------------------------- - | Sanctum Guards - |-------------------------------------------------------------------------- - | - | This array contains the authentication guards that will be checked when - | Sanctum is trying to authenticate a request. If none of these guards - | are able to authenticate the request, Sanctum will use the bearer - | token that's present on an incoming request for authentication. - | - */ - - 'guard' => ['web'], - - /* - |-------------------------------------------------------------------------- - | Expiration Minutes - |-------------------------------------------------------------------------- - | - | This value controls the number of minutes until an issued token will be - | considered expired. If this value is null, personal access tokens do - | not expire. This won't tweak the lifetime of first-party sessions. - | - */ - - 'expiration' => null, - - /* - |-------------------------------------------------------------------------- - | Sanctum Middleware - |-------------------------------------------------------------------------- - | - | When authenticating your first-party SPA with Sanctum you may need to - | customize some of the middleware Sanctum uses while processing the - | request. You may change the middleware listed below as required. - | - */ - - 'middleware' => [ - 'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class, - 'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class, - ], - -]; From c6be37fa222402ae70e5bebe1ec6a40c9c977bc8 Mon Sep 17 00:00:00 2001 From: Wendell Adriel Date: Fri, 26 Apr 2024 17:32:03 +0100 Subject: [PATCH 2/8] Add type coverage tests --- README.md | 3 ++- app/Exceptions/Handler.php | 4 ++-- app/Http/Kernel.php | 1 - app/Http/Middleware/ValidateSignature.php | 2 +- composer.json | 4 ++++ config/cors.php | 2 +- exa/Http/Middlewares/BlockViewerUsers.php | 2 +- exa/Http/Middlewares/HasRole.php | 2 +- exa/Http/Responses/ApiErrorResponse.php | 2 +- exa/Http/Responses/ApiSuccessResponse.php | 2 +- exa/Http/Responses/NoContentResponse.php | 2 +- exa/Services/SlackClient.php | 2 +- modules/Auth/Actions/UpdateUser.php | 2 +- modules/Auth/Models/User.php | 4 +--- modules/Auth/Routes/v1.php | 2 +- modules/Common/Routes/v1.php | 2 +- phpunit.xml | 2 ++ 17 files changed, 22 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index c4fd3a9..79a8d10 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,12 @@ * API Documentation with Swagger * Laravel Pint configuration (very opinionated) * Pest v2 for Tests +* Type Coverage Tests * Base classes to speed up the development * DTOs with [Laravel Validated DTO](https://github.com/WendellAdriel/laravel-validated-dto) * Slack Client for notifications * API structured in modules -* Laravel Sanctum for Authentication +* JWT for Authentication * Users management out-of-the-box with simple roles system * Logs on DB for user logins and for actions made on models * [Strictus](https://github.com/php-strictus/strictus) for enforcing local variable types diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index a6b3353..8a1b3ea 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -57,7 +57,7 @@ public function register(): void }); } - public function render($request, Throwable $exception) + public function render($request, Throwable $exception) // @pest-ignore-type { if ($exception instanceof \Illuminate\Auth\AuthenticationException) { return $this->error($exception, Response::HTTP_UNAUTHORIZED, 'Unauthenticated'); @@ -81,7 +81,7 @@ public function render($request, Throwable $exception) return $this->error($exception, Response::HTTP_INTERNAL_SERVER_ERROR); } - protected function unauthenticated($request, \Illuminate\Auth\AuthenticationException $exception) + protected function unauthenticated($request, \Illuminate\Auth\AuthenticationException $exception) // @pest-ignore-type { return $this->error($exception, Response::HTTP_UNAUTHORIZED, 'Unauthenticated'); } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 18c44a5..e720c55 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -41,7 +41,6 @@ class Kernel extends HttpKernel ], 'api' => [ - \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, \Illuminate\Routing\Middleware\ThrottleRequests::class . ':api', \Illuminate\Routing\Middleware\SubstituteBindings::class, \Exa\Http\Middlewares\BlockViewerUsers::class, diff --git a/app/Http/Middleware/ValidateSignature.php b/app/Http/Middleware/ValidateSignature.php index 0b3a971..d979b89 100644 --- a/app/Http/Middleware/ValidateSignature.php +++ b/app/Http/Middleware/ValidateSignature.php @@ -13,7 +13,7 @@ class ValidateSignature extends Middleware * * @var array */ - protected $except = [ + protected array $except = [ // 'fbclid', // 'utm_campaign', // 'utm_content', diff --git a/composer.json b/composer.json index c43f6f2..e38a196 100644 --- a/composer.json +++ b/composer.json @@ -61,11 +61,15 @@ "test": [ "pest" ], + "test:types": [ + "pest --type-coverage --min=100 app/ exa/ modules/" + ], "swagger": [ "sh ./tools/swagger.sh" ], "prepare": [ "pint --dirty", + "@test:types", "@swagger" ], "post-autoload-dump": [ diff --git a/config/cors.php b/config/cors.php index ec8d2d8..c16d1b6 100644 --- a/config/cors.php +++ b/config/cors.php @@ -17,7 +17,7 @@ | */ - 'paths' => ['api/*', 'sanctum/csrf-cookie'], + 'paths' => ['*'], 'allowed_methods' => ['*'], diff --git a/exa/Http/Middlewares/BlockViewerUsers.php b/exa/Http/Middlewares/BlockViewerUsers.php index a0f60b5..e662dde 100644 --- a/exa/Http/Middlewares/BlockViewerUsers.php +++ b/exa/Http/Middlewares/BlockViewerUsers.php @@ -11,7 +11,7 @@ final class BlockViewerUsers { - public function handle(Request $request, Closure $next) + public function handle(Request $request, Closure $next): Closure { $user = Auth::user(); if (is_null($user)) { diff --git a/exa/Http/Middlewares/HasRole.php b/exa/Http/Middlewares/HasRole.php index 0a881d4..928a5ae 100644 --- a/exa/Http/Middlewares/HasRole.php +++ b/exa/Http/Middlewares/HasRole.php @@ -20,7 +20,7 @@ public function __construct(private HasRoleAction $action) /** * @throws AccessDeniedException */ - public function handle(Request $request, Closure $next, string $role) + public function handle(Request $request, Closure $next, string $role): Closure { $user = Auth::user(); if (is_null($user)) { diff --git a/exa/Http/Responses/ApiErrorResponse.php b/exa/Http/Responses/ApiErrorResponse.php index f943bf3..f7c3b31 100644 --- a/exa/Http/Responses/ApiErrorResponse.php +++ b/exa/Http/Responses/ApiErrorResponse.php @@ -19,7 +19,7 @@ public function __construct( ) { } - public function toResponse($request): JsonResponse + public function toResponse($request): JsonResponse // @pest-ignore-type { $response = ['message' => $this->message]; diff --git a/exa/Http/Responses/ApiSuccessResponse.php b/exa/Http/Responses/ApiSuccessResponse.php index 6a2a799..465e580 100644 --- a/exa/Http/Responses/ApiSuccessResponse.php +++ b/exa/Http/Responses/ApiSuccessResponse.php @@ -18,7 +18,7 @@ public function __construct( ) { } - public function toResponse($request): JsonResponse + public function toResponse($request): JsonResponse // @pest-ignore-type { return response()->json( $this->resource->toArray($request), diff --git a/exa/Http/Responses/NoContentResponse.php b/exa/Http/Responses/NoContentResponse.php index 511a8b6..5d44485 100644 --- a/exa/Http/Responses/NoContentResponse.php +++ b/exa/Http/Responses/NoContentResponse.php @@ -15,7 +15,7 @@ public function __construct( ) { } - public function toResponse($request): Response + public function toResponse($request): Response // @pest-ignore-type { return response()->noContent($this->code, $this->headers); } diff --git a/exa/Services/SlackClient.php b/exa/Services/SlackClient.php index f654fd4..8b90dd4 100644 --- a/exa/Services/SlackClient.php +++ b/exa/Services/SlackClient.php @@ -67,7 +67,7 @@ private function formatUsersToMention(array $users): string return ''; } - $formatted = array_map(fn ($user) => "<@{$user}>", $users); + $formatted = array_map(fn (string $user) => "<@{$user}>", $users); return implode(', ', $formatted); } diff --git a/modules/Auth/Actions/UpdateUser.php b/modules/Auth/Actions/UpdateUser.php index d192537..ab51f4a 100644 --- a/modules/Auth/Actions/UpdateUser.php +++ b/modules/Auth/Actions/UpdateUser.php @@ -20,7 +20,7 @@ public function handle(string $uuid, UpdateUserDTO $dto): User { $authUser = Auth::user(); $user = $this->fetchUser->handle($uuid); - $updateData = collect($dto->toArray())->filter(fn ($item) => ! is_null($item))->toArray(); + $updateData = collect($dto->toArray())->filter(fn (string|bool|null $item) => ! is_null($item))->toArray(); if (! $authUser->is_admin) { unset($updateData['role'], $updateData['active']); diff --git a/modules/Auth/Models/User.php b/modules/Auth/Models/User.php index 2057bc4..de13624 100644 --- a/modules/Auth/Models/User.php +++ b/modules/Auth/Models/User.php @@ -11,14 +11,12 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; -use Laravel\Sanctum\HasApiTokens; use Modules\Auth\Support\Role; use Modules\Auth\Traits\HasRole; class User extends Authenticatable { use CommonQueries, - HasApiTokens, HasFactory, HasRole, HasUuidField, @@ -49,7 +47,7 @@ class User extends Authenticatable 'role' => Role::REGULAR->value, ]; - protected static function booted() + protected static function booted(): void { static::addGlobalScope('active-users', fn (Builder $builder) => $builder->where('active', true)); } diff --git a/modules/Auth/Routes/v1.php b/modules/Auth/Routes/v1.php index 99030db..9a40a43 100644 --- a/modules/Auth/Routes/v1.php +++ b/modules/Auth/Routes/v1.php @@ -11,7 +11,7 @@ Route::post('auth/login', [AuthController::class, 'login']); // Protected Routes -Route::middleware('auth:sanctum')->group(function () { +Route::middleware('auth')->group(function () { Route::prefix('auth')->group(function () { Route::post('logout', [AuthController::class, 'logout']); Route::get('me', [AuthController::class, 'user']); diff --git a/modules/Common/Routes/v1.php b/modules/Common/Routes/v1.php index acd4591..4bcc835 100644 --- a/modules/Common/Routes/v1.php +++ b/modules/Common/Routes/v1.php @@ -5,6 +5,6 @@ // Public Routes // Protected Routes -Route::middleware('auth:sanctum')->group(function () { +Route::middleware('auth')->group(function () { // }); diff --git a/phpunit.xml b/phpunit.xml index 0736f98..3467a18 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -22,6 +22,8 @@ ./app + ./exa + ./modules From f1c6b6d984a75230a24fdd187db9d4c47ff8ac13 Mon Sep 17 00:00:00 2001 From: Wendell Adriel Date: Fri, 26 Apr 2024 18:44:18 +0100 Subject: [PATCH 3/8] Refactored migrations and User model --- database/factories/UserFactory.php | 2 +- ...reate_users_table.php => 0001_create_users_table.php} | 1 + ...e.php => 0002_create_password_reset_tokens_table.php} | 0 ..._jobs_table.php => 0003_create_failed_jobs_table.php} | 0 ....php => 0004_create_personal_access_tokens_table.php} | 0 ...ogins_table.php => 0005_create_user_logins_table.php} | 0 ..._logs_table.php => 0006_create_change_logs_table.php} | 0 database/seeders/UserSeeder.php | 4 ++-- modules/Auth/DTOs/CreateUserDTO.php | 9 ++++++--- modules/Auth/Models/User.php | 8 ++++++-- modules/Auth/Support/Role.php | 5 +++++ modules/Auth/Traits/HasRole.php | 2 +- tests/Pest.php | 2 +- 13 files changed, 23 insertions(+), 10 deletions(-) rename database/migrations/{2014_10_12_000000_create_users_table.php => 0001_create_users_table.php} (96%) rename database/migrations/{2014_10_12_100000_create_password_reset_tokens_table.php => 0002_create_password_reset_tokens_table.php} (100%) rename database/migrations/{2019_08_19_000000_create_failed_jobs_table.php => 0003_create_failed_jobs_table.php} (100%) rename database/migrations/{2019_12_14_000001_create_personal_access_tokens_table.php => 0004_create_personal_access_tokens_table.php} (100%) rename database/migrations/{2023_02_18_125127_create_user_logins_table.php => 0005_create_user_logins_table.php} (100%) rename database/migrations/{2023_02_18_125148_create_change_logs_table.php => 0006_create_change_logs_table.php} (100%) diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index c759730..dac7089 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -26,7 +26,7 @@ public function definition(): array 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 'remember_token' => Str::random(10), - 'role' => Role::ADMIN->value, + 'role' => Role::ADMIN, 'active' => true, ]; } diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/0001_create_users_table.php similarity index 96% rename from database/migrations/2014_10_12_000000_create_users_table.php rename to database/migrations/0001_create_users_table.php index ded912f..420f73a 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/0001_create_users_table.php @@ -26,6 +26,7 @@ public function up(): void $table->boolean('active')->default(true); $table->rememberToken(); $table->timestamps(); + $table->softDeletes(); }); } } diff --git a/database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php b/database/migrations/0002_create_password_reset_tokens_table.php similarity index 100% rename from database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php rename to database/migrations/0002_create_password_reset_tokens_table.php diff --git a/database/migrations/2019_08_19_000000_create_failed_jobs_table.php b/database/migrations/0003_create_failed_jobs_table.php similarity index 100% rename from database/migrations/2019_08_19_000000_create_failed_jobs_table.php rename to database/migrations/0003_create_failed_jobs_table.php diff --git a/database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php b/database/migrations/0004_create_personal_access_tokens_table.php similarity index 100% rename from database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php rename to database/migrations/0004_create_personal_access_tokens_table.php diff --git a/database/migrations/2023_02_18_125127_create_user_logins_table.php b/database/migrations/0005_create_user_logins_table.php similarity index 100% rename from database/migrations/2023_02_18_125127_create_user_logins_table.php rename to database/migrations/0005_create_user_logins_table.php diff --git a/database/migrations/2023_02_18_125148_create_change_logs_table.php b/database/migrations/0006_create_change_logs_table.php similarity index 100% rename from database/migrations/2023_02_18_125148_create_change_logs_table.php rename to database/migrations/0006_create_change_logs_table.php diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index 1bc588e..4927063 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -25,7 +25,7 @@ public function run(): void 'email' => 'admin@example.com', 'name' => 'Admin', 'password' => Hash::make('password'), - 'role' => Role::ADMIN->value, + 'role' => Role::ADMIN, ]); return; @@ -34,7 +34,7 @@ public function run(): void $user->update([ 'name' => 'Admin', 'password' => Hash::make('password'), - 'role' => Role::ADMIN->value, + 'role' => Role::ADMIN, ]); } } diff --git a/modules/Auth/DTOs/CreateUserDTO.php b/modules/Auth/DTOs/CreateUserDTO.php index d170d1f..1c7823c 100644 --- a/modules/Auth/DTOs/CreateUserDTO.php +++ b/modules/Auth/DTOs/CreateUserDTO.php @@ -8,6 +8,7 @@ use Illuminate\Validation\Rules\Password; use Modules\Auth\Support\Role; use OpenApi\Attributes as OA; +use WendellAdriel\ValidatedDTO\Casting\EnumCast; use WendellAdriel\ValidatedDTO\ValidatedDTO; #[OA\Schema( @@ -29,7 +30,7 @@ class CreateUserDTO extends ValidatedDTO public string $password; - public string $role; + public Role $role; protected function rules(): array { @@ -53,12 +54,14 @@ protected function rules(): array protected function defaults(): array { return [ - 'role' => Role::REGULAR->value, + 'role' => Role::REGULAR, ]; } protected function casts(): array { - return []; + return [ + 'role' => new EnumCast(Role::class), + ]; } } diff --git a/modules/Auth/Models/User.php b/modules/Auth/Models/User.php index de13624..49fcc66 100644 --- a/modules/Auth/Models/User.php +++ b/modules/Auth/Models/User.php @@ -9,6 +9,7 @@ use Exa\Models\LogChanges; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Modules\Auth\Support\Role; @@ -21,12 +22,14 @@ class User extends Authenticatable HasRole, HasUuidField, LogChanges, - Notifiable; + Notifiable, + SoftDeletes; protected $fillable = [ 'uuid', 'name', 'email', + 'email_verified_at', 'password', 'role', 'active', @@ -39,12 +42,13 @@ class User extends Authenticatable protected $casts = [ 'email_verified_at' => 'datetime', + 'role' => Role::class, 'active' => 'boolean', ]; protected $attributes = [ 'active' => true, - 'role' => Role::REGULAR->value, + 'role' => Role::REGULAR, ]; protected static function booted(): void diff --git a/modules/Auth/Support/Role.php b/modules/Auth/Support/Role.php index ef56220..3e784a0 100644 --- a/modules/Auth/Support/Role.php +++ b/modules/Auth/Support/Role.php @@ -10,4 +10,9 @@ enum Role: string case REGULAR = 'regular'; case MANAGER = 'manager'; case ADMIN = 'admin'; + + public function label(): string + { + return ucfirst($this->value); + } } diff --git a/modules/Auth/Traits/HasRole.php b/modules/Auth/Traits/HasRole.php index 45dbce1..860eb58 100644 --- a/modules/Auth/Traits/HasRole.php +++ b/modules/Auth/Traits/HasRole.php @@ -39,6 +39,6 @@ public function isAdmin(): Attribute public function hasRole(Role $role): bool { - return $this->role === $role->value; + return $this->role === $role; } } diff --git a/tests/Pest.php b/tests/Pest.php index 4bedfe4..e763076 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -52,7 +52,7 @@ function testUser(Role $role): User 'email' => fake()->unique()->safeEmail(), 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password - 'role' => $role->value, + 'role' => $role, 'active' => true, ]); From 304e30bb4c26671a70232436c4d3b83451db2d16 Mon Sep 17 00:00:00 2001 From: Wendell Adriel Date: Fri, 26 Apr 2024 22:30:07 +0100 Subject: [PATCH 4/8] Refactored classes to final --- app/Console/Kernel.php | 2 +- app/Exceptions/Handler.php | 2 +- app/Http/Controllers/Controller.php | 2 +- app/Http/Kernel.php | 2 +- app/Http/Middleware/Authenticate.php | 2 +- app/Http/Middleware/EncryptCookies.php | 2 +- .../PreventRequestsDuringMaintenance.php | 2 +- .../Middleware/RedirectIfAuthenticated.php | 2 +- app/Http/Middleware/TrimStrings.php | 2 +- app/Http/Middleware/TrustHosts.php | 2 +- app/Http/Middleware/TrustProxies.php | 2 +- app/Http/Middleware/ValidateSignature.php | 2 +- app/Http/Middleware/VerifyCsrfToken.php | 2 +- app/Providers/AppServiceProvider.php | 2 +- app/Providers/AuthServiceProvider.php | 2 +- app/Providers/EventServiceProvider.php | 2 +- app/Providers/RouteServiceProvider.php | 26 ++++++++++++++----- database/factories/UserFactory.php | 2 +- database/seeders/DatabaseSeeder.php | 2 +- database/seeders/UserSeeder.php | 2 +- exa/Commands/MakeModuleCommand.php | 17 +++++++++--- exa/DTOs/DatatableDTO.php | 4 ++- exa/Exceptions/AccessDeniedException.php | 2 +- exa/Http/Responses/ApiErrorResponse.php | 2 +- exa/Http/Responses/ApiSuccessResponse.php | 2 +- exa/Http/Responses/NoContentResponse.php | 2 +- exa/Models/ChangeLog.php | 4 ++- exa/Models/LogChanges.php | 2 +- exa/Services/SlackClient.php | 2 +- exa/Support/Datatable.php | 4 +-- exa/Support/Formatter.php | 2 +- modules/Auth/Controllers/AuthController.php | 2 +- modules/Auth/Controllers/UserController.php | 2 +- modules/Auth/DTOs/CreateUserDTO.php | 2 +- modules/Auth/DTOs/LoginDTO.php | 2 +- modules/Auth/DTOs/UpdateUserDTO.php | 2 +- modules/Auth/Models/User.php | 7 +++-- modules/Auth/Models/UserLogin.php | 2 +- modules/Auth/Resources/LoginResource.php | 2 +- modules/Auth/Resources/UserResource.php | 2 +- 40 files changed, 81 insertions(+), 49 deletions(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 41ff6a0..36ba68b 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -8,7 +8,7 @@ use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; -class Kernel extends ConsoleKernel +final class Kernel extends ConsoleKernel { protected $commands = [ MakeModuleCommand::class, diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 8a1b3ea..cc372c2 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -11,7 +11,7 @@ use Illuminate\Support\Arr; use Throwable; -class Handler extends ExceptionHandler +final class Handler extends ExceptionHandler { /** * A list of exception types with their corresponding custom log levels. diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 127499a..f894a90 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -8,7 +8,7 @@ use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Routing\Controller as BaseController; -class Controller extends BaseController +abstract class Controller extends BaseController { use AuthorizesRequests, ValidatesRequests; } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index e720c55..8764987 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -6,7 +6,7 @@ use Illuminate\Foundation\Http\Kernel as HttpKernel; -class Kernel extends HttpKernel +final class Kernel extends HttpKernel { /** * The application's global HTTP middleware stack. diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index cd4ebd3..9ed0aba 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -7,7 +7,7 @@ use Illuminate\Auth\Middleware\Authenticate as Middleware; use Illuminate\Http\Request; -class Authenticate extends Middleware +final class Authenticate extends Middleware { /** * Get the path the user should be redirected to when they are not authenticated. diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php index a293077..49556f5 100644 --- a/app/Http/Middleware/EncryptCookies.php +++ b/app/Http/Middleware/EncryptCookies.php @@ -6,7 +6,7 @@ use Illuminate\Cookie\Middleware\EncryptCookies as Middleware; -class EncryptCookies extends Middleware +final class EncryptCookies extends Middleware { /** * The names of the cookies that should not be encrypted. diff --git a/app/Http/Middleware/PreventRequestsDuringMaintenance.php b/app/Http/Middleware/PreventRequestsDuringMaintenance.php index d7353a2..c82e523 100644 --- a/app/Http/Middleware/PreventRequestsDuringMaintenance.php +++ b/app/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -6,7 +6,7 @@ use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware; -class PreventRequestsDuringMaintenance extends Middleware +final class PreventRequestsDuringMaintenance extends Middleware { /** * The URIs that should be reachable while maintenance mode is enabled. diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 03653b0..a351e8e 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -10,7 +10,7 @@ use Illuminate\Support\Facades\Auth; use Symfony\Component\HttpFoundation\Response; -class RedirectIfAuthenticated +final class RedirectIfAuthenticated { /** * Handle an incoming request. diff --git a/app/Http/Middleware/TrimStrings.php b/app/Http/Middleware/TrimStrings.php index b538af8..b7b3a49 100644 --- a/app/Http/Middleware/TrimStrings.php +++ b/app/Http/Middleware/TrimStrings.php @@ -6,7 +6,7 @@ use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware; -class TrimStrings extends Middleware +final class TrimStrings extends Middleware { /** * The names of the attributes that should not be trimmed. diff --git a/app/Http/Middleware/TrustHosts.php b/app/Http/Middleware/TrustHosts.php index 1a108c3..a6ea229 100644 --- a/app/Http/Middleware/TrustHosts.php +++ b/app/Http/Middleware/TrustHosts.php @@ -6,7 +6,7 @@ use Illuminate\Http\Middleware\TrustHosts as Middleware; -class TrustHosts extends Middleware +final class TrustHosts extends Middleware { /** * Get the host patterns that should be trusted. diff --git a/app/Http/Middleware/TrustProxies.php b/app/Http/Middleware/TrustProxies.php index 5ec274d..beb8b9f 100644 --- a/app/Http/Middleware/TrustProxies.php +++ b/app/Http/Middleware/TrustProxies.php @@ -7,7 +7,7 @@ use Illuminate\Http\Middleware\TrustProxies as Middleware; use Illuminate\Http\Request; -class TrustProxies extends Middleware +final class TrustProxies extends Middleware { /** * The trusted proxies for this application. diff --git a/app/Http/Middleware/ValidateSignature.php b/app/Http/Middleware/ValidateSignature.php index d979b89..1d74f95 100644 --- a/app/Http/Middleware/ValidateSignature.php +++ b/app/Http/Middleware/ValidateSignature.php @@ -6,7 +6,7 @@ use Illuminate\Routing\Middleware\ValidateSignature as Middleware; -class ValidateSignature extends Middleware +final class ValidateSignature extends Middleware { /** * The names of the query string parameters that should be ignored. diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index c4527ee..57b6099 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -6,7 +6,7 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware; -class VerifyCsrfToken extends Middleware +final class VerifyCsrfToken extends Middleware { /** * The URIs that should be excluded from CSRF verification. diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 1c1ed4b..01d874d 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -8,7 +8,7 @@ use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\ServiceProvider; -class AppServiceProvider extends ServiceProvider +final class AppServiceProvider extends ServiceProvider { /** * Register any application services. diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 18f9a64..7854f16 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -7,7 +7,7 @@ // use Illuminate\Support\Facades\Gate; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; -class AuthServiceProvider extends ServiceProvider +final class AuthServiceProvider extends ServiceProvider { /** * The model to policy mappings for the application. diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index ee09f10..4515a14 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -9,7 +9,7 @@ use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Event; -class EventServiceProvider extends ServiceProvider +final class EventServiceProvider extends ServiceProvider { /** * The event to listener mappings for the application. diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 7322c68..afe0b15 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -24,7 +24,7 @@ scheme: 'bearer', bearerFormat: 'JWT' )] -class RouteServiceProvider extends ServiceProvider +final class RouteServiceProvider extends ServiceProvider { /** * The path to the "home" route for your application. @@ -52,20 +52,34 @@ public function boot(): void */ protected function configureRateLimiting(): void { - RateLimiter::for('api', fn (Request $request) => Limit::perMinute(60)->by($request->user()?->id ?: $request->ip())); + RateLimiter::for( + 'api', + fn (Request $request) => Limit::perMinute(60) + ->by($request->user()?->id ?: $request->ip()) + ); } private function configureIndexRoute(): void { Route::get(self::HOME, function () { - return response()->json([ + $data = [ 'application' => config('app.name'), + 'status' => Response::HTTP_OK, + 'datetime' => Carbon::now()->format(Formatter::API_DATETIME_FORMAT), + ]; + + if (! App::environment('local')) { + return response()->json($data); + } + + $data = [ + ...$data, 'environment' => config('app.env'), 'php_version' => phpversion(), 'laravel_version' => App::version(), - 'status' => Response::HTTP_OK, - 'datetime' => Carbon::now()->format(Formatter::API_DATETIME_FORMAT), - ]); + ]; + + return response()->json($data); })->name('login'); } diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index dac7089..a2e5120 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -11,7 +11,7 @@ /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\Modules\Auth\Models\User> */ -class UserFactory extends Factory +final class UserFactory extends Factory { /** * Define the model's default state. diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 3619ab1..1e393eb 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -6,7 +6,7 @@ use Illuminate\Database\Seeder; -class DatabaseSeeder extends Seeder +final class DatabaseSeeder extends Seeder { /** * Seed the application's database. diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index 4927063..22e09dd 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -9,7 +9,7 @@ use Modules\Auth\Models\User; use Modules\Auth\Support\Role; -class UserSeeder extends Seeder +final class UserSeeder extends Seeder { /** * Run the database seeds. diff --git a/exa/Commands/MakeModuleCommand.php b/exa/Commands/MakeModuleCommand.php index e2c9002..157a112 100644 --- a/exa/Commands/MakeModuleCommand.php +++ b/exa/Commands/MakeModuleCommand.php @@ -9,7 +9,7 @@ use Symfony\Component\Console\Attribute\AsCommand; #[AsCommand(name: 'make:module')] -class MakeModuleCommand extends Command +final class MakeModuleCommand extends Command { protected $signature = 'make:module {module : The module name}'; @@ -37,8 +37,19 @@ public function handle(): void private function moduleStructure(): array { return [ - 'Actions', 'Commands', 'Controllers', 'DTOs', 'Events', 'Exceptions', 'Listeners', - 'Models', 'Requests', 'Resources', 'Responses', 'Support', 'Traits', + 'Actions', + 'Commands', + 'Controllers', + 'DTOs', + 'Events', + 'Exceptions', + 'Listeners', + 'Models', + 'Requests', + 'Resources', + 'Responses', + 'Support', + 'Traits', ]; } diff --git a/exa/DTOs/DatatableDTO.php b/exa/DTOs/DatatableDTO.php index b6426a9..08af702 100644 --- a/exa/DTOs/DatatableDTO.php +++ b/exa/DTOs/DatatableDTO.php @@ -7,6 +7,7 @@ use Exa\Support\SortOption; use Illuminate\Validation\Rules\Enum; use OpenApi\Attributes as OA; +use WendellAdriel\ValidatedDTO\Casting\EnumCast; use WendellAdriel\ValidatedDTO\Casting\IntegerCast; use WendellAdriel\ValidatedDTO\ValidatedDTO; @@ -53,7 +54,7 @@ class DatatableDTO extends ValidatedDTO public ?string $sort_field; - public ?string $sort_order; + public ?SortOption $sort_order; public ?string $search; @@ -88,6 +89,7 @@ protected function casts(): array { return [ 'page' => new IntegerCast(), + 'sort_order' => new EnumCast(SortOption::class), ]; } } diff --git a/exa/Exceptions/AccessDeniedException.php b/exa/Exceptions/AccessDeniedException.php index 1d3d75c..bbde7ea 100644 --- a/exa/Exceptions/AccessDeniedException.php +++ b/exa/Exceptions/AccessDeniedException.php @@ -6,7 +6,7 @@ use Illuminate\Http\Response; -class AccessDeniedException extends ExaException +final class AccessDeniedException extends ExaException { public function __construct() { diff --git a/exa/Http/Responses/ApiErrorResponse.php b/exa/Http/Responses/ApiErrorResponse.php index f7c3b31..17025f8 100644 --- a/exa/Http/Responses/ApiErrorResponse.php +++ b/exa/Http/Responses/ApiErrorResponse.php @@ -9,7 +9,7 @@ use Illuminate\Http\Response; use Throwable; -readonly class ApiErrorResponse implements Responsable +final readonly class ApiErrorResponse implements Responsable { public function __construct( private string $message, diff --git a/exa/Http/Responses/ApiSuccessResponse.php b/exa/Http/Responses/ApiSuccessResponse.php index 465e580..75a63fa 100644 --- a/exa/Http/Responses/ApiSuccessResponse.php +++ b/exa/Http/Responses/ApiSuccessResponse.php @@ -9,7 +9,7 @@ use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Response; -readonly class ApiSuccessResponse implements Responsable +final readonly class ApiSuccessResponse implements Responsable { public function __construct( private JsonResource $resource, diff --git a/exa/Http/Responses/NoContentResponse.php b/exa/Http/Responses/NoContentResponse.php index 5d44485..707ca5e 100644 --- a/exa/Http/Responses/NoContentResponse.php +++ b/exa/Http/Responses/NoContentResponse.php @@ -7,7 +7,7 @@ use Illuminate\Contracts\Support\Responsable; use Illuminate\Http\Response; -readonly class NoContentResponse implements Responsable +final readonly class NoContentResponse implements Responsable { public function __construct( private int $code = Response::HTTP_NO_CONTENT, diff --git a/exa/Models/ChangeLog.php b/exa/Models/ChangeLog.php index 975e342..7907dda 100644 --- a/exa/Models/ChangeLog.php +++ b/exa/Models/ChangeLog.php @@ -4,11 +4,12 @@ namespace Exa\Models; +use Exa\Support\ChangeAction; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasOne; use Modules\Auth\Models\User; -class ChangeLog extends Model +final class ChangeLog extends Model { use CommonQueries; @@ -24,6 +25,7 @@ class ChangeLog extends Model ]; protected $casts = [ + 'action' => ChangeAction::class, 'payload' => 'array', 'old_data' => 'array', 'new_data' => 'array', diff --git a/exa/Models/LogChanges.php b/exa/Models/LogChanges.php index 3511029..4f6ed02 100644 --- a/exa/Models/LogChanges.php +++ b/exa/Models/LogChanges.php @@ -54,7 +54,7 @@ public static function logChange(Model $model, ChangeAction $action): void 'user_id' => Auth::check() ? Auth::user()->id : null, 'record_id' => empty($model->id) ? 0 : $model->id, 'table' => $model->getTable(), - 'action' => $action->value, + 'action' => $action, 'payload' => $model->toJson(), 'old_data' => $action !== ChangeAction::CREATE ? json_encode($model->getOriginal()) : null, 'new_data' => $action !== ChangeAction::DELETE ? json_encode($model->getAttributes()) : null, diff --git a/exa/Services/SlackClient.php b/exa/Services/SlackClient.php index 8b90dd4..56ce0da 100644 --- a/exa/Services/SlackClient.php +++ b/exa/Services/SlackClient.php @@ -8,7 +8,7 @@ use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Log; -readonly class SlackClient +final readonly class SlackClient { public function __construct( private string $botName, diff --git a/exa/Support/Datatable.php b/exa/Support/Datatable.php index 6aa3e0f..149feff 100644 --- a/exa/Support/Datatable.php +++ b/exa/Support/Datatable.php @@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Collection; use Illuminate\Pagination\LengthAwarePaginator; -readonly class Datatable +final readonly class Datatable { public const ALL_COLUMNS = ['*']; @@ -32,7 +32,7 @@ public static function applySort(Builder $builder, DatatableDTO $dto): Builder return $builder; } - return $dto->sort_order === SortOption::ASC->value + return $dto->sort_order === SortOption::ASC ? $builder->orderBy($dto->sort_field) : $builder->orderByDesc($dto->sort_field); } diff --git a/exa/Support/Formatter.php b/exa/Support/Formatter.php index a6e90d0..3399aba 100644 --- a/exa/Support/Formatter.php +++ b/exa/Support/Formatter.php @@ -4,7 +4,7 @@ namespace Exa\Support; -readonly class Formatter +final readonly class Formatter { public const ON_LABEL = 'ON'; diff --git a/modules/Auth/Controllers/AuthController.php b/modules/Auth/Controllers/AuthController.php index 9ef1521..01531fe 100644 --- a/modules/Auth/Controllers/AuthController.php +++ b/modules/Auth/Controllers/AuthController.php @@ -15,7 +15,7 @@ use Modules\Auth\Resources\UserResource; use OpenApi\Attributes as OA; -class AuthController extends Controller +final class AuthController extends Controller { #[OA\Post( path: '/v1/auth/login', diff --git a/modules/Auth/Controllers/UserController.php b/modules/Auth/Controllers/UserController.php index 97d6dcd..b90700b 100644 --- a/modules/Auth/Controllers/UserController.php +++ b/modules/Auth/Controllers/UserController.php @@ -21,7 +21,7 @@ use Modules\Auth\Resources\UserResource; use OpenApi\Attributes as OA; -class UserController extends Controller +final class UserController extends Controller { #[OA\Get( path: '/v1/users', diff --git a/modules/Auth/DTOs/CreateUserDTO.php b/modules/Auth/DTOs/CreateUserDTO.php index 1c7823c..9142626 100644 --- a/modules/Auth/DTOs/CreateUserDTO.php +++ b/modules/Auth/DTOs/CreateUserDTO.php @@ -22,7 +22,7 @@ new OA\Property(property: 'role', type: 'string', default: 'regular', enum: ['viewer', 'regular', 'manager', 'admin']), ], )] -class CreateUserDTO extends ValidatedDTO +final class CreateUserDTO extends ValidatedDTO { public string $name; diff --git a/modules/Auth/DTOs/LoginDTO.php b/modules/Auth/DTOs/LoginDTO.php index abd5a1c..92b622d 100644 --- a/modules/Auth/DTOs/LoginDTO.php +++ b/modules/Auth/DTOs/LoginDTO.php @@ -15,7 +15,7 @@ new OA\Property(property: 'password', type: 'string'), ], )] -class LoginDTO extends ValidatedDTO +final class LoginDTO extends ValidatedDTO { public string $email; diff --git a/modules/Auth/DTOs/UpdateUserDTO.php b/modules/Auth/DTOs/UpdateUserDTO.php index 197d315..730915e 100644 --- a/modules/Auth/DTOs/UpdateUserDTO.php +++ b/modules/Auth/DTOs/UpdateUserDTO.php @@ -23,7 +23,7 @@ new OA\Property(property: 'active', type: 'boolean'), ], )] -class UpdateUserDTO extends ValidatedDTO +final class UpdateUserDTO extends ValidatedDTO { public ?string $name; diff --git a/modules/Auth/Models/User.php b/modules/Auth/Models/User.php index 49fcc66..b066d5e 100644 --- a/modules/Auth/Models/User.php +++ b/modules/Auth/Models/User.php @@ -15,7 +15,7 @@ use Modules\Auth\Support\Role; use Modules\Auth\Traits\HasRole; -class User extends Authenticatable +final class User extends Authenticatable { use CommonQueries, HasFactory, @@ -53,6 +53,9 @@ class User extends Authenticatable protected static function booted(): void { - static::addGlobalScope('active-users', fn (Builder $builder) => $builder->where('active', true)); + self::addGlobalScope( + 'active-users', + fn (Builder $builder) => $builder->where('active', true) + ); } } diff --git a/modules/Auth/Models/UserLogin.php b/modules/Auth/Models/UserLogin.php index b3f229f..f064869 100644 --- a/modules/Auth/Models/UserLogin.php +++ b/modules/Auth/Models/UserLogin.php @@ -6,7 +6,7 @@ use Exa\Models\BaseModel; -class UserLogin extends BaseModel +final class UserLogin extends BaseModel { public bool $disableChangeLogs = true; diff --git a/modules/Auth/Resources/LoginResource.php b/modules/Auth/Resources/LoginResource.php index f26b741..de58ea3 100644 --- a/modules/Auth/Resources/LoginResource.php +++ b/modules/Auth/Resources/LoginResource.php @@ -15,7 +15,7 @@ new OA\Property(property: 'token', type: 'string'), ], )] -class LoginResource extends JsonResource +final class LoginResource extends JsonResource { public function toArray(Request $request): array { diff --git a/modules/Auth/Resources/UserResource.php b/modules/Auth/Resources/UserResource.php index cf30d63..afcb067 100644 --- a/modules/Auth/Resources/UserResource.php +++ b/modules/Auth/Resources/UserResource.php @@ -20,7 +20,7 @@ new OA\Property(property: 'updated_at', type: 'string', format: 'date-time'), ], )] -class UserResource extends JsonResource +final class UserResource extends JsonResource { public function toArray(Request $request): array { From b097a04dabff16a7fbe8aaaa9c10da77ce2f55df Mon Sep 17 00:00:00 2001 From: Wendell Adriel Date: Fri, 26 Apr 2024 22:38:35 +0100 Subject: [PATCH 5/8] Add Soft Delete for BaseModel --- exa/Models/BaseModel.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/exa/Models/BaseModel.php b/exa/Models/BaseModel.php index 0b56b0b..65ab812 100644 --- a/exa/Models/BaseModel.php +++ b/exa/Models/BaseModel.php @@ -5,9 +5,11 @@ namespace Exa\Models; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; abstract class BaseModel extends Model { use CommonQueries, - LogChanges; + LogChanges, + SoftDeletes; } From ca5a6923f05a2af3be9fd6af08c7e050e3f3f9d4 Mon Sep 17 00:00:00 2001 From: Wendell Adriel Date: Fri, 26 Apr 2024 22:46:28 +0100 Subject: [PATCH 6/8] Added JWT library and refactored env file --- .env.example | 21 +++- composer.json | 1 + composer.lock | 224 +++++++++++++++++++++++++++++++++++- config/jwt.php | 301 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 542 insertions(+), 5 deletions(-) create mode 100644 config/jwt.php diff --git a/.env.example b/.env.example index 7e4ddf9..e912777 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,4 @@ +# APP CONFIG APP_NAME=ExA APP_ENV=local APP_KEY= @@ -6,14 +7,23 @@ APP_EXTERNAL_PORT=8000 APP_EXTERNAL_PORT_SSL=4000 APP_URL=http://localhost:${APP_EXTERNAL_PORT} SWAGGER_EXTERNAL_PORT=8080 +JWT_SECRET= +# DOCKER BUILD CONFIG M1_PROCESSOR=false XDEBUG_ENABLED=true +# GENERAL CONFIG +FILESYSTEM_DISK=local +BROADCAST_DRIVER=log +QUEUE_CONNECTION=sync + +# LOG CONFIG LOG_CHANNEL=daily LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug +# DATABASE CONFIG DB_CONNECTION=mysql DB_HOST=mysql DB_PORT=3306 @@ -22,20 +32,21 @@ DB_DATABASE=exa DB_USERNAME=exa DB_PASSWORD=secret -BROADCAST_DRIVER=log -CACHE_DRIVER=redis -FILESYSTEM_DISK=local -QUEUE_CONNECTION=sync +# SESSION CONFIG SESSION_DRIVER=redis SESSION_LIFETIME=120 +# CACHE CONFIG +CACHE_DRIVER=redis MEMCACHED_HOST=127.0.0.1 +# REDIS CONFIG REDIS_HOST=redis REDIS_PASSWORD=null REDIS_PORT=6379 REDIS_EXTERNAL_PORT=9000 +# MAIL CONFIG MAIL_MAILER=smtp MAIL_HOST=mailpit MAIL_PORT=1025 @@ -47,12 +58,14 @@ MAIL_FROM_NAME="${APP_NAME}" MAILPIT_EXTERNAL_PORT_SMTP=1025 MAILPIT_EXTERNAL_PORT_HTTP=8025 +# AWS CONFIG AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET= AWS_USE_PATH_STYLE_ENDPOINT=false +# SLACK CONFIG SLACK_NOTIFICATIONS_WEBHOOK= SLACK_NOTIFICATIONS_CHANNEL="#general" SLACK_NOTIFICATIONS_BOT_NAME="EXA-BOT" diff --git a/composer.json b/composer.json index e38a196..264e194 100644 --- a/composer.json +++ b/composer.json @@ -27,6 +27,7 @@ "laravel/framework": "^11.5", "laravel/tinker": "^2.9", "strictus/strictus": "^1.3", + "tymon/jwt-auth": "^2.1", "wendelladriel/laravel-validated-dto": "^3.5", "zircote/swagger-php": "^4.9" }, diff --git a/composer.lock b/composer.lock index a784029..8aefd02 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b2e575ae1fed7385093e6c4b96483ab1", + "content-hash": "8ac765d4bbd14c645882e1986243670c", "packages": [ { "name": "brick/math", @@ -1433,6 +1433,144 @@ }, "time": "2024-01-04T16:10:04+00:00" }, + { + "name": "lcobucci/clock", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/clock.git", + "reference": "6f28b826ea01306b07980cb8320ab30b966cd715" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/6f28b826ea01306b07980cb8320ab30b966cd715", + "reference": "6f28b826ea01306b07980cb8320ab30b966cd715", + "shasum": "" + }, + "require": { + "php": "~8.2.0 || ~8.3.0", + "psr/clock": "^1.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "infection/infection": "^0.27", + "lcobucci/coding-standard": "^11.0.0", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan": "^1.10.25", + "phpstan/phpstan-deprecation-rules": "^1.1.3", + "phpstan/phpstan-phpunit": "^1.3.13", + "phpstan/phpstan-strict-rules": "^1.5.1", + "phpunit/phpunit": "^10.2.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\Clock\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Luís Cobucci", + "email": "lcobucci@gmail.com" + } + ], + "description": "Yet another clock abstraction", + "support": { + "issues": "https://github.com/lcobucci/clock/issues", + "source": "https://github.com/lcobucci/clock/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/lcobucci", + "type": "github" + }, + { + "url": "https://www.patreon.com/lcobucci", + "type": "patreon" + } + ], + "time": "2023-11-17T17:00:27+00:00" + }, + { + "name": "lcobucci/jwt", + "version": "4.3.0", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/4d7de2fe0d51a96418c0d04004986e410e87f6b4", + "reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4", + "shasum": "" + }, + "require": { + "ext-hash": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-sodium": "*", + "lcobucci/clock": "^2.0 || ^3.0", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "infection/infection": "^0.21", + "lcobucci/coding-standard": "^6.0", + "mikey179/vfsstream": "^1.6.7", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/php-invoker": "^3.1", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Cobucci", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "support": { + "issues": "https://github.com/lcobucci/jwt/issues", + "source": "https://github.com/lcobucci/jwt/tree/4.3.0" + }, + "funding": [ + { + "url": "https://github.com/lcobucci", + "type": "github" + }, + { + "url": "https://www.patreon.com/lcobucci", + "type": "patreon" + } + ], + "time": "2023-01-02T13:28:00+00:00" + }, { "name": "league/commonmark", "version": "2.4.2", @@ -5608,6 +5746,90 @@ }, "time": "2023-12-08T13:03:43+00:00" }, + { + "name": "tymon/jwt-auth", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/tymondesigns/jwt-auth.git", + "reference": "51620ebd5b68bb3ce9e66ba86bda303ae5f10f7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tymondesigns/jwt-auth/zipball/51620ebd5b68bb3ce9e66ba86bda303ae5f10f7f", + "reference": "51620ebd5b68bb3ce9e66ba86bda303ae5f10f7f", + "shasum": "" + }, + "require": { + "illuminate/auth": "^9.0|^10.0|^11.0", + "illuminate/contracts": "^9.0|^10.0|^11.0", + "illuminate/http": "^9.0|^10.0|^11.0", + "illuminate/support": "^9.0|^10.0|^11.0", + "lcobucci/jwt": "^4.0", + "nesbot/carbon": "^2.0|^3.0", + "php": "^8.0" + }, + "require-dev": { + "illuminate/console": "^9.0|^10.0|^11.0", + "illuminate/database": "^9.0|^10.0|^11.0", + "illuminate/routing": "^9.0|^10.0|^11.0", + "mockery/mockery": ">=0.9.9", + "phpunit/phpunit": "^9.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "1.0-dev", + "dev-2.x": "2.0-dev" + }, + "laravel": { + "aliases": { + "JWTAuth": "Tymon\\JWTAuth\\Facades\\JWTAuth", + "JWTFactory": "Tymon\\JWTAuth\\Facades\\JWTFactory" + }, + "providers": [ + "Tymon\\JWTAuth\\Providers\\LaravelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Tymon\\JWTAuth\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Sean Tymon", + "email": "tymon148@gmail.com", + "homepage": "https://tymon.xyz", + "role": "Developer" + } + ], + "description": "JSON Web Token Authentication for Laravel and Lumen", + "homepage": "https://github.com/tymondesigns/jwt-auth", + "keywords": [ + "Authentication", + "JSON Web Token", + "auth", + "jwt", + "laravel" + ], + "support": { + "issues": "https://github.com/tymondesigns/jwt-auth/issues", + "source": "https://github.com/tymondesigns/jwt-auth" + }, + "funding": [ + { + "url": "https://www.patreon.com/seantymon", + "type": "patreon" + } + ], + "time": "2024-03-14T19:29:49+00:00" + }, { "name": "vlucas/phpdotenv", "version": "v5.6.0", diff --git a/config/jwt.php b/config/jwt.php new file mode 100644 index 0000000..f83234d --- /dev/null +++ b/config/jwt.php @@ -0,0 +1,301 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return [ + + /* + |-------------------------------------------------------------------------- + | JWT Authentication Secret + |-------------------------------------------------------------------------- + | + | Don't forget to set this in your .env file, as it will be used to sign + | your tokens. A helper command is provided for this: + | `php artisan jwt:secret` + | + | Note: This will be used for Symmetric algorithms only (HMAC), + | since RSA and ECDSA use a private/public key combo (See below). + | + */ + + 'secret' => env('JWT_SECRET'), + + /* + |-------------------------------------------------------------------------- + | JWT Authentication Keys + |-------------------------------------------------------------------------- + | + | The algorithm you are using, will determine whether your tokens are + | signed with a random string (defined in `JWT_SECRET`) or using the + | following public & private keys. + | + | Symmetric Algorithms: + | HS256, HS384 & HS512 will use `JWT_SECRET`. + | + | Asymmetric Algorithms: + | RS256, RS384 & RS512 / ES256, ES384 & ES512 will use the keys below. + | + */ + + 'keys' => [ + + /* + |-------------------------------------------------------------------------- + | Public Key + |-------------------------------------------------------------------------- + | + | A path or resource to your public key. + | + | E.g. 'file://path/to/public/key' + | + */ + + 'public' => env('JWT_PUBLIC_KEY'), + + /* + |-------------------------------------------------------------------------- + | Private Key + |-------------------------------------------------------------------------- + | + | A path or resource to your private key. + | + | E.g. 'file://path/to/private/key' + | + */ + + 'private' => env('JWT_PRIVATE_KEY'), + + /* + |-------------------------------------------------------------------------- + | Passphrase + |-------------------------------------------------------------------------- + | + | The passphrase for your private key. Can be null if none set. + | + */ + + 'passphrase' => env('JWT_PASSPHRASE'), + + ], + + /* + |-------------------------------------------------------------------------- + | JWT time to live + |-------------------------------------------------------------------------- + | + | Specify the length of time (in minutes) that the token will be valid for. + | Defaults to 1 hour. + | + | You can also set this to null, to yield a never expiring token. + | Some people may want this behaviour for e.g. a mobile app. + | This is not particularly recommended, so make sure you have appropriate + | systems in place to revoke the token if necessary. + | Notice: If you set this to null you should remove 'exp' element from 'required_claims' list. + | + */ + + 'ttl' => env('JWT_TTL', 60), + + /* + |-------------------------------------------------------------------------- + | Refresh time to live + |-------------------------------------------------------------------------- + | + | Specify the length of time (in minutes) that the token can be refreshed + | within. I.E. The user can refresh their token within a 2 week window of + | the original token being created until they must re-authenticate. + | Defaults to 2 weeks. + | + | You can also set this to null, to yield an infinite refresh time. + | Some may want this instead of never expiring tokens for e.g. a mobile app. + | This is not particularly recommended, so make sure you have appropriate + | systems in place to revoke the token if necessary. + | + */ + + 'refresh_ttl' => env('JWT_REFRESH_TTL', 20160), + + /* + |-------------------------------------------------------------------------- + | JWT hashing algorithm + |-------------------------------------------------------------------------- + | + | Specify the hashing algorithm that will be used to sign the token. + | + */ + + 'algo' => env('JWT_ALGO', Tymon\JWTAuth\Providers\JWT\Provider::ALGO_HS256), + + /* + |-------------------------------------------------------------------------- + | Required Claims + |-------------------------------------------------------------------------- + | + | Specify the required claims that must exist in any token. + | A TokenInvalidException will be thrown if any of these claims are not + | present in the payload. + | + */ + + 'required_claims' => [ + 'iss', + 'iat', + 'exp', + 'nbf', + 'sub', + 'jti', + ], + + /* + |-------------------------------------------------------------------------- + | Persistent Claims + |-------------------------------------------------------------------------- + | + | Specify the claim keys to be persisted when refreshing a token. + | `sub` and `iat` will automatically be persisted, in + | addition to the these claims. + | + | Note: If a claim does not exist then it will be ignored. + | + */ + + 'persistent_claims' => [ + // 'foo', + // 'bar', + ], + + /* + |-------------------------------------------------------------------------- + | Lock Subject + |-------------------------------------------------------------------------- + | + | This will determine whether a `prv` claim is automatically added to + | the token. The purpose of this is to ensure that if you have multiple + | authentication models e.g. `App\User` & `App\OtherPerson`, then we + | should prevent one authentication request from impersonating another, + | if 2 tokens happen to have the same id across the 2 different models. + | + | Under specific circumstances, you may want to disable this behaviour + | e.g. if you only have one authentication model, then you would save + | a little on token size. + | + */ + + 'lock_subject' => true, + + /* + |-------------------------------------------------------------------------- + | Leeway + |-------------------------------------------------------------------------- + | + | This property gives the jwt timestamp claims some "leeway". + | Meaning that if you have any unavoidable slight clock skew on + | any of your servers then this will afford you some level of cushioning. + | + | This applies to the claims `iat`, `nbf` and `exp`. + | + | Specify in seconds - only if you know you need it. + | + */ + + 'leeway' => env('JWT_LEEWAY', 0), + + /* + |-------------------------------------------------------------------------- + | Blacklist Enabled + |-------------------------------------------------------------------------- + | + | In order to invalidate tokens, you must have the blacklist enabled. + | If you do not want or need this functionality, then set this to false. + | + */ + + 'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true), + + /* + | ------------------------------------------------------------------------- + | Blacklist Grace Period + | ------------------------------------------------------------------------- + | + | When multiple concurrent requests are made with the same JWT, + | it is possible that some of them fail, due to token regeneration + | on every request. + | + | Set grace period in seconds to prevent parallel request failure. + | + */ + + 'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0), + + /* + |-------------------------------------------------------------------------- + | Cookies encryption + |-------------------------------------------------------------------------- + | + | By default Laravel encrypt cookies for security reason. + | If you decide to not decrypt cookies, you will have to configure Laravel + | to not encrypt your cookie token by adding its name into the $except + | array available in the middleware "EncryptCookies" provided by Laravel. + | see https://laravel.com/docs/master/responses#cookies-and-encryption + | for details. + | + | Set it to true if you want to decrypt cookies. + | + */ + + 'decrypt_cookies' => false, + + /* + |-------------------------------------------------------------------------- + | Providers + |-------------------------------------------------------------------------- + | + | Specify the various providers used throughout the package. + | + */ + + 'providers' => [ + + /* + |-------------------------------------------------------------------------- + | JWT Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to create and decode the tokens. + | + */ + + 'jwt' => Tymon\JWTAuth\Providers\JWT\Lcobucci::class, + + /* + |-------------------------------------------------------------------------- + | Authentication Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to authenticate users. + | + */ + + 'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class, + + /* + |-------------------------------------------------------------------------- + | Storage Provider + |-------------------------------------------------------------------------- + | + | Specify the provider that is used to store tokens in the blacklist. + | + */ + + 'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class, + + ], + +]; From 8a99a4cb71e5ec27156454008d87dd74a79ad161 Mon Sep 17 00:00:00 2001 From: Wendell Adriel Date: Sat, 27 Apr 2024 16:58:32 +0100 Subject: [PATCH 7/8] Finished JWT auth implementation --- app/Providers/RouteServiceProvider.php | 2 +- config/auth.php | 7 ++++++- config/cache.php | 5 +++++ config/database.php | 9 +++++++++ config/jwt.php | 4 +++- exa/DTOs/DatatableDTO.php | 2 +- exa/Http/Middlewares/BlockViewerUsers.php | 2 +- exa/Http/Middlewares/HasRole.php | 2 +- exa/Support/JWTStorage.php | 18 ++++++++++++++++++ modules/Auth/Actions/Login.php | 6 +++--- modules/Auth/Controllers/AuthController.php | 2 +- modules/Auth/Models/User.php | 13 ++++++++++++- tests/Feature/ApplicationUpTest.php | 4 ++-- tests/Feature/Auth/DeleteUserTest.php | 2 +- tests/Feature/Auth/FetchUserTest.php | 2 +- tests/Feature/Auth/LoggedUserTest.php | 2 +- tests/Feature/Auth/LogoutTest.php | 12 ------------ 17 files changed, 66 insertions(+), 28 deletions(-) create mode 100644 exa/Support/JWTStorage.php delete mode 100644 tests/Feature/Auth/LogoutTest.php diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index afe0b15..3e41210 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -68,7 +68,7 @@ private function configureIndexRoute(): void 'datetime' => Carbon::now()->format(Formatter::API_DATETIME_FORMAT), ]; - if (! App::environment('local')) { + if (! App::environment('local', 'testing')) { return response()->json($data); } diff --git a/config/auth.php b/config/auth.php index 3fc0e0d..4411511 100644 --- a/config/auth.php +++ b/config/auth.php @@ -16,7 +16,7 @@ */ 'defaults' => [ - 'guard' => 'web', + 'guard' => 'api', 'passwords' => 'users', ], @@ -42,6 +42,11 @@ 'driver' => 'session', 'provider' => 'users', ], + + 'api' => [ + 'driver' => 'jwt', + 'provider' => 'users', + ], ], /* diff --git a/config/cache.php b/config/cache.php index 96efffe..40f0d74 100644 --- a/config/cache.php +++ b/config/cache.php @@ -94,6 +94,11 @@ 'driver' => 'octane', ], + 'jwt' => [ + 'driver' => 'redis', + 'connection' => 'jwt', + 'lock_connection' => 'default', + ], ], /* diff --git a/config/database.php b/config/database.php index d220309..5f2cb58 100644 --- a/config/database.php +++ b/config/database.php @@ -148,6 +148,15 @@ 'database' => env('REDIS_CACHE_DB', '1'), ], + 'jwt' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('JWT_DB', '2'), + ], + ], ]; diff --git a/config/jwt.php b/config/jwt.php index f83234d..9442cc0 100644 --- a/config/jwt.php +++ b/config/jwt.php @@ -1,5 +1,7 @@ Tymon\JWTAuth\Providers\Storage\Illuminate::class, + 'storage' => \Exa\Support\JWTStorage::class, ], diff --git a/exa/DTOs/DatatableDTO.php b/exa/DTOs/DatatableDTO.php index 08af702..11e702c 100644 --- a/exa/DTOs/DatatableDTO.php +++ b/exa/DTOs/DatatableDTO.php @@ -80,7 +80,7 @@ protected function defaults(): array 'page' => 1, 'per_page' => 20, 'sort_field' => null, - 'sort_order' => null, + 'sort_order' => SortOption::ASC, 'search' => null, ]; } diff --git a/exa/Http/Middlewares/BlockViewerUsers.php b/exa/Http/Middlewares/BlockViewerUsers.php index e662dde..a847f9b 100644 --- a/exa/Http/Middlewares/BlockViewerUsers.php +++ b/exa/Http/Middlewares/BlockViewerUsers.php @@ -11,7 +11,7 @@ final class BlockViewerUsers { - public function handle(Request $request, Closure $next): Closure + public function handle(Request $request, Closure $next): mixed { $user = Auth::user(); if (is_null($user)) { diff --git a/exa/Http/Middlewares/HasRole.php b/exa/Http/Middlewares/HasRole.php index 928a5ae..51b8f46 100644 --- a/exa/Http/Middlewares/HasRole.php +++ b/exa/Http/Middlewares/HasRole.php @@ -20,7 +20,7 @@ public function __construct(private HasRoleAction $action) /** * @throws AccessDeniedException */ - public function handle(Request $request, Closure $next, string $role): Closure + public function handle(Request $request, Closure $next, string $role): mixed { $user = Auth::user(); if (is_null($user)) { diff --git a/exa/Support/JWTStorage.php b/exa/Support/JWTStorage.php new file mode 100644 index 0000000..8dc599a --- /dev/null +++ b/exa/Support/JWTStorage.php @@ -0,0 +1,18 @@ +cache = Cache::store('jwt'); + } +} diff --git a/modules/Auth/Actions/Login.php b/modules/Auth/Actions/Login.php index a04df53..aab3e8d 100644 --- a/modules/Auth/Actions/Login.php +++ b/modules/Auth/Actions/Login.php @@ -6,7 +6,6 @@ use Illuminate\Auth\AuthenticationException; use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Str; use Modules\Auth\DTOs\LoginDTO; use Modules\Auth\Models\User; use Modules\Auth\Models\UserLogin; @@ -17,7 +16,8 @@ public function handle(LoginDTO $dto): array { - if (! Auth::attempt($dto->toArray())) { + $token = Auth::attempt($dto->toArray()); + if (! $token) { throw new AuthenticationException(); } @@ -27,7 +27,7 @@ public function handle(LoginDTO $dto): array return [ 'type' => self::TOKEN_TYPE, - 'token' => $user->createToken(Str::slug(config('app.name') . '_login'))->plainTextToken, + 'token' => $token, ]; } diff --git a/modules/Auth/Controllers/AuthController.php b/modules/Auth/Controllers/AuthController.php index 01531fe..978c536 100644 --- a/modules/Auth/Controllers/AuthController.php +++ b/modules/Auth/Controllers/AuthController.php @@ -58,7 +58,7 @@ public function login(Request $request, Login $action): ApiSuccessResponse #[OA\Response(response: '500', description: 'Server Error')] public function logout(): NoContentResponse { - Auth::guard('web')->logout(); + auth()->logout(true); return new NoContentResponse(); } diff --git a/modules/Auth/Models/User.php b/modules/Auth/Models/User.php index b066d5e..212d3dc 100644 --- a/modules/Auth/Models/User.php +++ b/modules/Auth/Models/User.php @@ -14,8 +14,9 @@ use Illuminate\Notifications\Notifiable; use Modules\Auth\Support\Role; use Modules\Auth\Traits\HasRole; +use Tymon\JWTAuth\Contracts\JWTSubject; -final class User extends Authenticatable +final class User extends Authenticatable implements JWTSubject { use CommonQueries, HasFactory, @@ -51,6 +52,16 @@ final class User extends Authenticatable 'role' => Role::REGULAR, ]; + public function getJWTIdentifier(): mixed + { + return $this->getKey(); + } + + public function getJWTCustomClaims(): array + { + return []; + } + protected static function booted(): void { self::addGlobalScope( diff --git a/tests/Feature/ApplicationUpTest.php b/tests/Feature/ApplicationUpTest.php index 9dbdfe4..44cb29c 100644 --- a/tests/Feature/ApplicationUpTest.php +++ b/tests/Feature/ApplicationUpTest.php @@ -11,10 +11,10 @@ expect($this->get('/')->json()) ->toBe([ 'application' => config('app.name'), + 'status' => Response::HTTP_OK, + 'datetime' => Carbon::now()->format(Formatter::API_DATETIME_FORMAT), 'environment' => config('app.env'), 'php_version' => phpversion(), 'laravel_version' => App::version(), - 'status' => Response::HTTP_OK, - 'datetime' => Carbon::now()->format(Formatter::API_DATETIME_FORMAT), ]); }); diff --git a/tests/Feature/Auth/DeleteUserTest.php b/tests/Feature/Auth/DeleteUserTest.php index b0027f6..96b3af1 100644 --- a/tests/Feature/Auth/DeleteUserTest.php +++ b/tests/Feature/Auth/DeleteUserTest.php @@ -11,7 +11,7 @@ expect($this->actingAs(testUser(Role::ADMIN))->delete("v1/users/{$newUser->uuid}")) ->assertNoContent(); - $this->assertDatabaseMissing(User::getModelTable(), [ + $this->assertSoftDeleted(User::getModelTable(), [ 'email' => $newUser->email, ]); }); diff --git a/tests/Feature/Auth/FetchUserTest.php b/tests/Feature/Auth/FetchUserTest.php index 9cf1ead..f73ab61 100644 --- a/tests/Feature/Auth/FetchUserTest.php +++ b/tests/Feature/Auth/FetchUserTest.php @@ -12,7 +12,7 @@ 'uuid' => $newUser->uuid, 'name' => $newUser->name, 'email' => $newUser->email, - 'role' => $newUser->role, + 'role' => $newUser->role->value, 'active' => $newUser->active, 'created_at' => $newUser->created_at->toISOString(), 'updated_at' => $newUser->updated_at->toISOString(), diff --git a/tests/Feature/Auth/LoggedUserTest.php b/tests/Feature/Auth/LoggedUserTest.php index d858c6c..9a2c0a2 100644 --- a/tests/Feature/Auth/LoggedUserTest.php +++ b/tests/Feature/Auth/LoggedUserTest.php @@ -13,7 +13,7 @@ 'uuid' => $user->uuid, 'name' => $user->name, 'email' => $user->email, - 'role' => $user->role, + 'role' => $user->role->value, 'active' => $user->active, 'created_at' => $user->created_at->toISOString(), 'updated_at' => $user->updated_at->toISOString(), diff --git a/tests/Feature/Auth/LogoutTest.php b/tests/Feature/Auth/LogoutTest.php deleted file mode 100644 index fdccd18..0000000 --- a/tests/Feature/Auth/LogoutTest.php +++ /dev/null @@ -1,12 +0,0 @@ -actingAs(testUser(Role::ADMIN)); - - expect($this->post('v1/auth/logout')) - ->assertNoContent(); -}); From 5e87c68e7d80f1723b237ae11a0d33eaca15d55b Mon Sep 17 00:00:00 2001 From: Wendell Adriel Date: Sat, 27 Apr 2024 17:04:57 +0100 Subject: [PATCH 8/8] Readme update --- README.md | 3 ++- composer.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 79a8d10..c0e246e 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ * API Documentation with Swagger * Laravel Pint configuration (very opinionated) * Pest v2 for Tests -* Type Coverage Tests +* Type Coverage Tests with 100% type coverage * Base classes to speed up the development * DTOs with [Laravel Validated DTO](https://github.com/WendellAdriel/laravel-validated-dto) * Slack Client for notifications @@ -37,6 +37,7 @@ * Users management out-of-the-box with simple roles system * Logs on DB for user logins and for actions made on models * [Strictus](https://github.com/php-strictus/strictus) for enforcing local variable types +* Models extending from BaseModel use soft deletes by default ## Using the Template diff --git a/composer.json b/composer.json index 264e194..c60d738 100644 --- a/composer.json +++ b/composer.json @@ -63,7 +63,7 @@ "pest" ], "test:types": [ - "pest --type-coverage --min=100 app/ exa/ modules/" + "pest --type-coverage --min=100" ], "swagger": [ "sh ./tools/swagger.sh"