diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 6606896..7605e6a 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -11,50 +11,43 @@ jobs: test: runs-on: ubuntu-latest strategy: - fail-fast: true + fail-fast: false matrix: php: [8.3, 8.2, 8.1, 8.0] - laravel: [11.*, 10.*, 9.*] - dependency-version: [prefer-lowest, prefer-stable] + laravel: ["^11.0", "^10.0", "^9.0"] + dependency-version: [prefer-stable] include: - - laravel: 11.* - testbench: ^9.0 - - laravel: 10.* - testbench: ^8.0 - - laravel: 9.* - testbench: ^7.0 + - laravel: "^11.0" + testbench: 9.* + - laravel: "^10.0" + testbench: 8.* + - laravel: "^9.0" + testbench: 7.* exclude: - - laravel: 9.* - php: 8.3 - - laravel: 10.* + - laravel: "^11.0" + php: 8.1 + - laravel: "^11.0" php: 8.0 - - laravel: 11.* + - laravel: "^10.0" php: 8.0 - - laravel: 11.* - php: 8.1 - name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} - ${{ matrix.os }} + name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo + extensions: curl, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, iconv coverage: none - - name: Setup problem matchers - run: | - echo "::add-matcher::${{ runner.tool_cache }}/php.json" - echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - name: Install dependencies run: | - composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" "nesbot/carbon:>=2.62.1" --no-interaction --no-update - composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-progress + composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" "symfony/console:>=4.3.4" "mockery/mockery:^1.3.2" "nesbot/carbon:>=2.62.1" --no-interaction --no-update + composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction - name: Execute tests run: vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index 83c9b9f..8054c8d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .idea .phpunit.result.cache +.phpunit.cache build composer.lock coverage diff --git a/.phpunit.cache/test-results b/.phpunit.cache/test-results deleted file mode 100644 index 72ac2cc..0000000 --- a/.phpunit.cache/test-results +++ /dev/null @@ -1 +0,0 @@ -{"version":1,"defects":[],"times":{"Mchev\\Banhammer\\Tests\\Unit\\IPBannedMiddlewareTest::it_blocks_the_banned_ip":0.002,"Mchev\\Banhammer\\Tests\\Unit\\IPBanTest::test_ip_ban_with_metas":0.003,"Mchev\\Banhammer\\Tests\\Unit\\IPBanTest::test_ip_is_unbanned":0.003,"Mchev\\Banhammer\\Tests\\Unit\\IPBanTest::test_ip_is_banned":0.003,"Mchev\\Banhammer\\Tests\\Unit\\IPBanTest::test_multiple_ip_are_banned":0.002,"Mchev\\Banhammer\\Tests\\Unit\\IPBanTest::test_ip_ban_can_be_created":0.05,"Mchev\\Banhammer\\Tests\\Unit\\BlockByCountryMiddlewareTest::it_allows_request_from_non_blocked_country":0.001,"Mchev\\Banhammer\\Tests\\Unit\\BlockByCountryMiddlewareTest::it_blocks_request_from_blocked_country":0.001,"Mchev\\Banhammer\\Tests\\Unit\\BlockByCountryMiddlewareTest::it_allows_request_when_cache_is_present":0.007,"Mchev\\Banhammer\\Tests\\Unit\\BlockByCountryMiddlewareTest::it_allows_request_when_country_check_fails":0.023}} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 91c6c09..b13ac11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to `banhammer` will be documented in this file. +## v2.3.0 - 2024-05-24 + +- Added UUID support @KieranLProctor +- Added Configurable model support @KieranLProctor + ## v2.2.0 - 2024-03-12 - Laravel 11 support @@ -22,7 +27,7 @@ This new version introduce the block by country middleware ## v1.2.0 - 2023-03-02 -- Adding Metas (cutom properties) to bans. +- Adding Metas (cutom properties) to bans. @mepsd - You may have to run `php artisan migrate` if you are upgrading from v1.1.x ## v1.1.5 - 2023-02-21 diff --git a/README.md b/README.md index 809f660..43f4256 100644 --- a/README.md +++ b/README.md @@ -24,13 +24,14 @@ Banned models can have an expiration date and will be automatically unbanned usi - [Scheduler](#scheduler) - [Events](#events) - [Miscellaneous](#misc) -6. [Testing](#testing) -7. [Changelog](#changelog) -8. [Roadmap / Todo](#roadmap--todo) -9. [Contributing](#contributing) -10. [Security Vulnerabilities](#security-vulnerabilities) -11. [Credits](#credits) -12. [License](#license) +6. [UUIDs](#uuids) +7. [Testing](#testing) +8. [Changelog](#changelog) +9. [Roadmap / Todo](#roadmap--todo) +10. [Contributing](#contributing) +11. [Security Vulnerabilities](#security-vulnerabilities) +12. [Credits](#credits) +13. [License](#license) ## Version Compatibility @@ -48,19 +49,22 @@ You can install the package via composer: composer require mchev/banhammer ``` -Then run the migrations with: +Then publish and run the migrations with: + +> To use UUIDs see [UUIDs](#uuids) ```bash +php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="migrations" php artisan migrate ``` You can publish the config file with: ```bash -php artisan vendor:publish --tag="banhammer-config" +php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="config" ``` -It is possible to define the table name and the fallback_url in the `config/ban.php` file. +It is possible to define the table name, the model and the fallback_url in the `config/ban.php` file. ## Upgrading To 2.0 from 1.x @@ -86,7 +90,7 @@ composer update mchev/banhammer - Backup your previous configuration file located at `config/ban.php`. - Force republish the new configuration using the command: ```bash - php artisan vendor:publish --tag="banhammer-config" --force + php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="config" --force ``` - Review the new configuration file and make any necessary edits. @@ -337,6 +341,52 @@ Or you can use the command: php artisan banhammer:clear ``` +## UUIDs + +To use UUIDs make sure you publish and edit the migration files. + +```bash +php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="migrations" +``` + +```diff +- $table->id(); ++ $table->uuid('id'); +``` + +You will then need to make a model that extends `Mchev\Banhammer\Models\Ban`: + +```php + Although most of the methods needed are already available from the base model, you can add any additional methods here. + +Finally update the published `ban.php` config file to load the model you have created: + +```diff + /* + |-------------------------------------------------------------------------- + | Model Name + |-------------------------------------------------------------------------- + | + | Specify the model which you want to use as your Ban model. + | + */ + +- 'model' => \Mchev\Banhammer\Models\Ban::class, ++ 'model' => \App\Models\YouBanClass::class, +``` + ## Testing ```bash diff --git a/config/config.php b/config/config.php index 200ff27..c84b709 100644 --- a/config/config.php +++ b/config/config.php @@ -14,6 +14,17 @@ 'table' => 'bans', + /* + |-------------------------------------------------------------------------- + | Model Name + |-------------------------------------------------------------------------- + | + | Specify the model which you want to use as your Ban model. + | + */ + + 'model' => \Mchev\Banhammer\Models\Ban::class, + /* |-------------------------------------------------------------------------- | Where to Redirect Banned Users diff --git a/database/migrations/create_bans_table.php b/database/migrations/create_bans_table.php index 6b75882..99ff97e 100644 --- a/database/migrations/create_bans_table.php +++ b/database/migrations/create_bans_table.php @@ -20,7 +20,6 @@ public function up(): void $table->timestamp('expired_at')->nullable(); $table->softDeletes(); $table->timestamps(); - $table->index('ip'); $table->index('expired_at'); }); diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 0bc1b47..5514b4c 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,25 +1,18 @@ - - - - tests - - - - - - - - - - - - - - - + + + + tests/Unit + + + - ./src + src - + + + + + + diff --git a/phpunit.xml.dist.bak b/phpunit.xml.dist.bak deleted file mode 100644 index c7b5079..0000000 --- a/phpunit.xml.dist.bak +++ /dev/null @@ -1,48 +0,0 @@ - - - - - tests - - - - - ./src - - - - - - - - - - - - - - - - - - - - diff --git a/src/Banhammer.php b/src/Banhammer.php index 3c25c63..cdbbfa6 100644 --- a/src/Banhammer.php +++ b/src/Banhammer.php @@ -3,18 +3,17 @@ namespace Mchev\Banhammer; use Illuminate\Support\Facades\Cache; -use Mchev\Banhammer\Models\Ban; class Banhammer { public static function unbanExpired(): void { - Ban::expired()->delete(); + config('ban.model')::expired()->delete(); Cache::put('banned-ips', IP::banned()->pluck('ip')->toArray()); } public static function clear(): void { - Ban::onlyTrashed()->forceDelete(); + config('ban.model')::onlyTrashed()->forceDelete(); } } diff --git a/src/BanhammerServiceProvider.php b/src/BanhammerServiceProvider.php index 6bda4c1..c665f96 100644 --- a/src/BanhammerServiceProvider.php +++ b/src/BanhammerServiceProvider.php @@ -11,7 +11,6 @@ use Mchev\Banhammer\Middleware\BlockByCountry; use Mchev\Banhammer\Middleware\IPBanned; use Mchev\Banhammer\Middleware\LogoutBanned; -use Mchev\Banhammer\Models\Ban; use Mchev\Banhammer\Observers\BanObserver; class BanhammerServiceProvider extends ServiceProvider @@ -21,9 +20,7 @@ class BanhammerServiceProvider extends ServiceProvider */ public function boot(): void { - $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); - - Ban::observe(BanObserver::class); + config('ban.model')::observe(BanObserver::class); $router = $this->app->make(Router::class); $router->aliasMiddleware('auth.banned', AuthBanned::class); @@ -38,12 +35,12 @@ public function boot(): void // Publishing the config. $this->publishes([ __DIR__.'/../config/config.php' => config_path('ban.php'), - ], 'banhammer-config'); + ], 'config'); // Publishing migrations - // $this->publishes([ - // __DIR__.'/../database/migrations' => database_path('migrations'), - // ], 'banhammer-migrations'); + $this->publishes([ + __DIR__.'/../database/migrations' => database_path('migrations'), + ], 'migrations'); // Registering package commands. $this->commands([ diff --git a/src/Events/ModelWasBanned.php b/src/Events/ModelWasBanned.php index 8c51193..638ba01 100644 --- a/src/Events/ModelWasBanned.php +++ b/src/Events/ModelWasBanned.php @@ -3,11 +3,10 @@ namespace Mchev\Banhammer\Events; use Illuminate\Contracts\Queue\ShouldQueue; -use Mchev\Banhammer\Models\Ban; class ModelWasBanned implements ShouldQueue { - public function __construct(public $model, public Ban $ban) + public function __construct(public $model, public $ban) { } } diff --git a/src/Exceptions/BanhammerException.php b/src/Exceptions/BanhammerException.php index 019a60a..21ad698 100644 --- a/src/Exceptions/BanhammerException.php +++ b/src/Exceptions/BanhammerException.php @@ -10,7 +10,7 @@ class BanhammerException extends HttpException { - public function __construct($message = null, Exception $previous = null, $code = 0) + public function __construct($message = null, ?Exception $previous = null, $code = 0) { parent::__construct(403, $message, $previous, [], $code); } diff --git a/src/IP.php b/src/IP.php index d4bd12b..9794d20 100644 --- a/src/IP.php +++ b/src/IP.php @@ -4,17 +4,16 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\Cache; -use Mchev\Banhammer\Models\Ban; class IP { - public static function ban(string|array $ips, array $metas = [], string $date = null): void + public static function ban(string|array $ips, array $metas = [], ?string $date = null): void { $bannedIps = self::getBannedIPsFromCache(); foreach ((array) $ips as $ip) { if (! in_array($ip, $bannedIps)) { - Ban::create([ + config('ban.model')::create([ 'ip' => $ip, 'metas' => count($metas) ? $metas : null, 'expired_at' => $date, @@ -26,20 +25,20 @@ public static function ban(string|array $ips, array $metas = [], string $date = public static function unban(string|array $ips): void { $ips = (array) $ips; - Ban::whereIn('ip', $ips)->delete(); + config('ban.model')::whereIn('ip', $ips)->delete(); Cache::put('banned-ips', self::banned()->pluck('ip')->toArray()); } public static function isBanned(string $ip): bool { - return Ban::where('ip', $ip) + return config('ban.model')::where('ip', $ip) ->notExpired() ->exists(); } public static function banned(): Builder { - return Ban::whereNotNull('ip') + return config('ban.model')::whereNotNull('ip') ->with('createdBy') ->notExpired(); } diff --git a/src/Observers/BanObserver.php b/src/Observers/BanObserver.php index 5923ecb..c429cb7 100644 --- a/src/Observers/BanObserver.php +++ b/src/Observers/BanObserver.php @@ -6,11 +6,10 @@ use Mchev\Banhammer\Events\ModelWasBanned; use Mchev\Banhammer\Events\ModelWasUnbanned; use Mchev\Banhammer\IP; -use Mchev\Banhammer\Models\Ban; class BanObserver { - public function creating(Ban $ban): void + public function creating($ban): void { $user = auth()->user(); if ($user && is_null($ban->created_by_type) && is_null($ban->created_by_id)) { @@ -21,19 +20,19 @@ public function creating(Ban $ban): void } } - public function created(Ban $ban): void + public function created($ban): void { event(new ModelWasBanned($ban->bannable(), $ban)); $this->updateCachedIps($ban); } - public function deleted(Ban $ban): void + public function deleted($ban): void { event(new ModelWasUnbanned($ban->bannable())); $this->updateCachedIps($ban); } - public function updateCachedIps(Ban $ban): void + public function updateCachedIps($ban): void { if ($ban->ip) { Cache::put('banned-ips', IP::banned()->pluck('ip')->unique()->toArray()); diff --git a/src/Traits/Bannable.php b/src/Traits/Bannable.php index 4b6f95f..6b57c9b 100644 --- a/src/Traits/Bannable.php +++ b/src/Traits/Bannable.php @@ -13,7 +13,7 @@ trait Bannable */ public function bans(): MorphMany { - return $this->morphMany(Ban::class, 'bannable'); + return $this->morphMany(config('ban.model'), 'bannable'); } /** diff --git a/tests/TestCase.php b/tests/TestCase.php index fe7d3f3..f46da50 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -21,4 +21,10 @@ protected function getPackageProviders($app): array 'Mchev\Banhammer\BanhammerServiceProvider', ]; } + + protected function defineDatabaseMigrations() + { + // $this->loadLaravelMigrations(); + $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); + } } diff --git a/tests/Unit/BlockByCountryMiddlewareTest.php b/tests/Unit/BlockByCountryMiddlewareTest.php index 33cb479..7215fd5 100644 --- a/tests/Unit/BlockByCountryMiddlewareTest.php +++ b/tests/Unit/BlockByCountryMiddlewareTest.php @@ -2,6 +2,7 @@ namespace Mchev\Banhammer\Tests\Unit; +use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Mchev\Banhammer\Exceptions\BanhammerException; @@ -12,10 +13,10 @@ class BlockByCountryMiddlewareTest extends TestCase { - /** @var BlockByCountry */ + use RefreshDatabase; + private $middleware; - /** @var IpApiService|\Mockery\MockInterface */ private $ipApiService; protected function setUp(): void