From 7793618d990166ce999b97a86aa651f6733128de Mon Sep 17 00:00:00 2001 From: Mohammad Alavi Date: Sat, 30 Nov 2024 18:18:36 +0330 Subject: [PATCH 1/2] feat: create publishable default configs --- config/apiato.php | 205 ++++++++++++++++++ src/Commands/SeedDeploymentDataCommand.php | 10 + src/Commands/SeedTestingDataCommand.php | 10 + src/Providers/ApiatoServiceProvider.php | 8 + .../PhpUnit/TestAuthHelperTrait.php | 5 + 5 files changed, 238 insertions(+) create mode 100644 config/apiato.php diff --git a/config/apiato.php b/config/apiato.php new file mode 100644 index 000000000..aa24859ca --- /dev/null +++ b/config/apiato.php @@ -0,0 +1,205 @@ + env('HASH_ID', true), + + 'api' => [ + /* + |-------------------------------------------------------------------------- + | API URL + |-------------------------------------------------------------------------- + */ + 'url' => env('API_URL', 'http://localhost'), + + /* + |-------------------------------------------------------------------------- + | API Prefix + |-------------------------------------------------------------------------- + */ + 'prefix' => env('API_PREFIX', '/'), + + /* + |-------------------------------------------------------------------------- + | API Version Prefix + |-------------------------------------------------------------------------- + */ + 'enable_version_prefix' => true, + + /* + |-------------------------------------------------------------------------- + | Access Token Expiration Time + |-------------------------------------------------------------------------- + | + | In Minutes. Default to 1,440 minutes = 1 day + | + */ + 'expires-in' => env('API_TOKEN_EXPIRES', 1440), + + /* + |-------------------------------------------------------------------------- + | Refresh Token Expiration Time + |-------------------------------------------------------------------------- + | + | In Minutes. Default to 43,200 minutes = 30 days + | + */ + 'refresh-expires-in' => env('API_REFRESH_TOKEN_EXPIRES', 43200), + + /* + |-------------------------------------------------------------------------- + | Enable Disable API Debugging + |-------------------------------------------------------------------------- + | + | If enabled, the Error Exception trace will be injected in the JSON + | response, and it will be logged in the default Log file. + | + */ + 'debug' => env('API_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | Enable/Disable Implicit Grant + |-------------------------------------------------------------------------- + */ + 'enabled-implicit-grant' => env('API_ENABLE_IMPLICIT_GRANT', true), + + /* + |-------------------------------------------------------------------------- + | Rate Limit (throttle) + |-------------------------------------------------------------------------- + | + | Attempts per minutes. + | `attempts` is the number of attempts per `expires` in minutes. + | + */ + 'throttle' => [ + 'enabled' => env('GLOBAL_API_RATE_LIMIT_ENABLED', true), + 'attempts' => env('GLOBAL_API_RATE_LIMIT_ATTEMPTS_PER_MIN', '30'), + 'expires' => env('GLOBAL_API_RATE_LIMIT_EXPIRES_IN_MIN', '1'), + ], + ], + + 'requests' => [ + /* + |-------------------------------------------------------------------------- + | Allow Roles to access all Routes + |-------------------------------------------------------------------------- + | + | Define a list of roles that do not need to go through the "hasAccess" + | check in Requests. These roles automatically pass this check. This is + | useful, if you want to make all routes accessible for admin users. + | + | Usage: ['admin', 'editor'] + | Default: [] + | + */ + 'allow-roles-to-access-all-routes' => [ + env('ADMIN_ROLE', 'admin'), + ], + + /* + |-------------------------------------------------------------------------- + | Force Request Header to Contain header + |-------------------------------------------------------------------------- + | + | By default, users can send request without defining the accept header and + | setting it to [ accept = application/json ]. + | To force the users to define that header, set this to true. + | When set to true, a PHP exception will be thrown preventing users from access + | When set to false, the header will contain a warning message. + | + */ + 'force-accept-header' => false, + + /* + |-------------------------------------------------------------------------- + | Force Valid Request Include Parameters + |-------------------------------------------------------------------------- + | + | By default, users can request to include additional resources into the + | response by using the ?include=... query parameter. The requested top-level + | resource also responds with all available includes. However, the user may + | still request an invalid (i.e., not available) include parameter. This flag + | determines, how to proceed in such a case: + | When set to true, a PHP Exception will be thrown (default) + | When set to false, this invalid include will be skipped + | + */ + 'force-valid-includes' => true, + + /* + |-------------------------------------------------------------------------- + | Use ETags + |-------------------------------------------------------------------------- + | + | This option appends an "ETag" HTTP Header to the Response. This ETag is a + | calculated hash of the content to be delivered. + | Clients can add an "If-None-Match" HTTP Header to the Request and submit + | an (old) ETag. These ETags are validated. If they match (are the same), + | an empty BODY with HTTP STATUS 304 (not modified) is returned! + | + */ + 'use-etag' => false, + + 'params' => [ + // TODO: BC: remove this after removing its usage in ResponseTrait in Core + 'filter' => 'fieldset', + ], + + /* + |-------------------------------------------------------------------------- + | Sparse Fieldsets + |-------------------------------------------------------------------------- + | + | Sparse Fieldsets are a feature of the JSON API spec that allows clients to request only a subset of the + | attributes for a specific resource type. This can be useful for improving performance by reducing the amount + | of data that needs to be transferred over the network. + | + | @see https://jsonapi.org/format/#fetching-sparse-fieldsets + | + */ + 'sparse_fieldsets' => [ + // The name of key in the request to where we should look for the fields to return. + 'request_key' => 'fields', + ], + ], + + 'seeders' => [ + /* + |-------------------------------------------------------------------------- + | Special seeders for apiato:seed-deploy & apiato:seed-test commands + |-------------------------------------------------------------------------- + | + */ + 'deployment' => null, + 'testing' => null, + ], + + 'tests' => [ + /* + |-------------------------------------------------------------------------- + | In order to be able to create testing user in your tests using test helpers, tests needs to know + | the name of the user model.This is working by default but if you are using another + | user model you should update this config. + | This user model MUST have a factory defined. + |-------------------------------------------------------------------------- + | + */ + 'user-class' => null, + + /* + |-------------------------------------------------------------------------- + | In order to be able to create admin testing user in your tests using test helpers, tests needs to know + | the name of the admin state in user factory. This is working by default but if you are using another + | user model or you have changed the default admin state name you should update this config. + |-------------------------------------------------------------------------- + | + */ + 'user-admin-state' => 'admin', + ], +]; diff --git a/src/Commands/SeedDeploymentDataCommand.php b/src/Commands/SeedDeploymentDataCommand.php index f02d16b39..4553fcfe9 100644 --- a/src/Commands/SeedDeploymentDataCommand.php +++ b/src/Commands/SeedDeploymentDataCommand.php @@ -23,6 +23,16 @@ public function __construct() public function handle(): void { + if (!config('apiato.seeders.deployment')) { + $this->error('No Deployment Seeder Found, Please Check Your Config File.'); + return; + } + + if (!class_exists(config('apiato.seeders.deployment'))) { + $this->error('Deployment Seeder Class Not Found.'); + return; + } + $this->call('db:seed', [ '--class' => config('apiato.seeders.deployment'), ]); diff --git a/src/Commands/SeedTestingDataCommand.php b/src/Commands/SeedTestingDataCommand.php index 841d4b1d0..536416287 100644 --- a/src/Commands/SeedTestingDataCommand.php +++ b/src/Commands/SeedTestingDataCommand.php @@ -23,6 +23,16 @@ public function __construct() public function handle(): void { + if (!config('apiato.seeders.testing')) { + $this->error('No Testing Seeder Found, Please Check Your Config File.'); + return; + } + + if (!class_exists(config('apiato.seeders.testing'))) { + $this->error('Testing Seeder Class Not Found.'); + return; + } + $this->call('db:seed', [ '--class' => config('apiato.seeders.testing'), ]); diff --git a/src/Providers/ApiatoServiceProvider.php b/src/Providers/ApiatoServiceProvider.php index 3cfca2e2a..9ca459557 100644 --- a/src/Providers/ApiatoServiceProvider.php +++ b/src/Providers/ApiatoServiceProvider.php @@ -33,6 +33,10 @@ public function register(): void parent::register(); $this->runLoaderRegister(); + + $this->mergeConfigFrom( + __DIR__ . '/../../config/apiato.php', 'apiato' + ); } public function boot(): void @@ -47,5 +51,9 @@ public function boot(): void // Registering custom validation rules $this->extendValidationRules(); + + $this->publishes([ + __DIR__ . '/../../config/apiato.php' => app_path('Ship/Configs/apiato.php'), + ], 'apiato-config'); } } diff --git a/src/Traits/TestTraits/PhpUnit/TestAuthHelperTrait.php b/src/Traits/TestTraits/PhpUnit/TestAuthHelperTrait.php index eb7ddc8f3..3b85ec2fa 100644 --- a/src/Traits/TestTraits/PhpUnit/TestAuthHelperTrait.php +++ b/src/Traits/TestTraits/PhpUnit/TestAuthHelperTrait.php @@ -64,6 +64,11 @@ public function getTestingUser(array|null $userDetails = null, array|null $acces { $this->createUserAsAdmin = $createUserAsAdmin; $this->userClass = $this->userclass ?? config('apiato.tests.user-class'); + + if (!$this->userClass) { + throw new \RuntimeException('User class is not defined in the test class'); + } + $this->userAdminState = config('apiato.tests.user-admin-state'); if (is_null($userDetails)) { From 193b1de1ba5f84fe199581fe2f35cfe439c296ca Mon Sep 17 00:00:00 2001 From: Mohammad-Alavi Date: Sat, 30 Nov 2024 14:54:00 +0000 Subject: [PATCH 2/2] style: apply automated php-cs-fixer changes --- src/Commands/SeedDeploymentDataCommand.php | 2 ++ src/Commands/SeedTestingDataCommand.php | 2 ++ src/Providers/ApiatoServiceProvider.php | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Commands/SeedDeploymentDataCommand.php b/src/Commands/SeedDeploymentDataCommand.php index 4553fcfe9..2d4088ef0 100644 --- a/src/Commands/SeedDeploymentDataCommand.php +++ b/src/Commands/SeedDeploymentDataCommand.php @@ -25,11 +25,13 @@ public function handle(): void { if (!config('apiato.seeders.deployment')) { $this->error('No Deployment Seeder Found, Please Check Your Config File.'); + return; } if (!class_exists(config('apiato.seeders.deployment'))) { $this->error('Deployment Seeder Class Not Found.'); + return; } diff --git a/src/Commands/SeedTestingDataCommand.php b/src/Commands/SeedTestingDataCommand.php index 536416287..d843f5b6f 100644 --- a/src/Commands/SeedTestingDataCommand.php +++ b/src/Commands/SeedTestingDataCommand.php @@ -25,11 +25,13 @@ public function handle(): void { if (!config('apiato.seeders.testing')) { $this->error('No Testing Seeder Found, Please Check Your Config File.'); + return; } if (!class_exists(config('apiato.seeders.testing'))) { $this->error('Testing Seeder Class Not Found.'); + return; } diff --git a/src/Providers/ApiatoServiceProvider.php b/src/Providers/ApiatoServiceProvider.php index 9ca459557..e225d1984 100644 --- a/src/Providers/ApiatoServiceProvider.php +++ b/src/Providers/ApiatoServiceProvider.php @@ -35,7 +35,8 @@ public function register(): void $this->runLoaderRegister(); $this->mergeConfigFrom( - __DIR__ . '/../../config/apiato.php', 'apiato' + __DIR__ . '/../../config/apiato.php', + 'apiato', ); }