├── CHANGELOG.md ├── LICENSE ├── README.md ├── UPGRADING.md ├── composer.json ├── config └── ban.php ├── contracts ├── Ban.php ├── BanService.php └── Bannable.php ├── database └── migrations │ └── 2017_03_04_000000_create_bans_table.php └── src ├── Console └── Commands │ └── DeleteExpiredBans.php ├── Events ├── ModelWasBanned.php └── ModelWasUnbanned.php ├── Http └── Middleware │ ├── ForbidBannedUser.php │ └── LogsOutBannedUser.php ├── Models └── Ban.php ├── Observers └── BanObserver.php ├── Providers └── BanServiceProvider.php ├── Scopes └── BannedAtScope.php ├── Services └── BanService.php └── Traits ├── Bannable.php ├── HasBannedAtHelpers.php ├── HasBannedAtScope.php └── HasBansRelation.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `cybercog/laravel-ban` are documented in [Laravel Ban releases] page. 4 | 5 | [Laravel Ban releases]: https://github.com/cybercog/laravel-ban/releases 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020, Anton Komarev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Ban 2 | 3 | ![cog-laravel-ban](https://user-images.githubusercontent.com/1849174/44558308-1d8e0580-a74c-11e8-8e2a-ec297bbc3f12.png) 4 | 5 |

6 | Discord 7 | Releases 8 | Build 9 | StyleCI 10 | Code Quality 11 | License 12 |

13 | 14 | ## Introduction 15 | 16 | Laravel Ban simplify management of Eloquent model's ban. Make any model bannable in a minutes! 17 | 18 | Use case is not limited to User model, any Eloquent model could be banned: Organizations, Teams, Groups and others. 19 | 20 | ## Contents 21 | 22 | - [Features](#features) 23 | - [Installation](#installation) 24 | - [Usage](#usage) 25 | - [Prepare bannable model](#prepare-bannable-model) 26 | - [Prepare bannable model database table](#prepare-bannable-model-database-table) 27 | - [Available methods](#available-methods) 28 | - [Scopes](#scopes) 29 | - [Events](#events) 30 | - [Middleware](#middleware) 31 | - [Scheduling](#scheduling) 32 | - [Integrations](#integrations) 33 | - [Changelog](#changelog) 34 | - [Upgrading](#upgrading) 35 | - [Contributing](#contributing) 36 | - [Testing](#testing) 37 | - [Security](#security) 38 | - [Contributors](#contributors) 39 | - [Alternatives](#alternatives) 40 | - [License](#license) 41 | - [About CyberCog](#about-cybercog) 42 | 43 | ## Features 44 | 45 | - Model can have many bans. 46 | - Removed bans kept in history as soft deleted records. 47 | - Most parts of the logic is handled by the `BanService`. 48 | - Has middleware to prevent banned user route access. 49 | - Use case is not limited to `User` model, any Eloquent model could be banned. 50 | - Events firing on models `ban` and `unban`. 51 | - Designed to work with Laravel Eloquent models. 52 | - Has [Laravel Nova support](https://github.com/cybercog/laravel-nova-ban). 53 | - Using contracts to keep high customization capabilities. 54 | - Using traits to get functionality out of the box. 55 | - Following PHP Standard Recommendations: 56 | - [PSR-1 (Basic Coding Standard)](http://www.php-fig.org/psr/psr-1/). 57 | - [PSR-2 (Coding Style Guide)](http://www.php-fig.org/psr/psr-2/). 58 | - [PSR-4 (Autoloading Standard)](http://www.php-fig.org/psr/psr-4/). 59 | - Covered with unit tests. 60 | 61 | ## Installation 62 | 63 | First, pull in the package through Composer: 64 | 65 | ```shell 66 | composer require cybercog/laravel-ban 67 | ``` 68 | 69 | #### Registering package 70 | 71 | > The package will automatically register itself. This step required for Laravel 5.4 or earlier releases only. 72 | 73 | Include the service provider within `app/config/app.php`: 74 | 75 | ```php 76 | 'providers' => [ 77 | Cog\Laravel\Ban\Providers\BanServiceProvider::class, 78 | ], 79 | ``` 80 | 81 | #### Apply database migrations 82 | 83 | At last, you need to publish and run database migrations: 84 | 85 | ```shell 86 | php artisan vendor:publish --provider="Cog\Laravel\Ban\Providers\BanServiceProvider" --tag="migrations" 87 | php artisan migrate 88 | ``` 89 | 90 | ## Usage 91 | 92 | ### Prepare bannable model 93 | 94 | ```php 95 | use Cog\Contracts\Ban\Bannable as BannableInterface; 96 | use Cog\Laravel\Ban\Traits\Bannable; 97 | use Illuminate\Foundation\Auth\User as Authenticatable; 98 | 99 | class User extends Authenticatable implements BannableInterface 100 | { 101 | use Bannable; 102 | } 103 | ``` 104 | 105 | ### Prepare bannable model database table 106 | 107 | Bannable model must have `nullable timestamp` column named `banned_at`. This value used as flag and simplify checks if user was banned. If you are trying to make default Laravel User model to be bannable you can use example below. 108 | 109 | #### Create a new migration file 110 | 111 | ```shell 112 | php artisan make:migration add_banned_at_column_to_users_table 113 | ``` 114 | 115 | Then insert the following code into migration file: 116 | 117 | ```php 118 | timestamp('banned_at')->nullable(); 130 | }); 131 | } 132 | 133 | public function down(): void 134 | { 135 | Schema::table('users', function (Blueprint $table) { 136 | $table->dropColumn('banned_at'); 137 | }); 138 | } 139 | }; 140 | ``` 141 | 142 | ### Available methods 143 | 144 | #### Apply ban for the entity 145 | 146 | ```php 147 | $user->ban(); 148 | ``` 149 | 150 | #### Apply ban for the entity with reason comment 151 | 152 | ```php 153 | $user->ban([ 154 | 'comment' => 'Enjoy your ban!', 155 | ]); 156 | ``` 157 | 158 | #### Apply ban for the entity which will be deleted over time 159 | 160 | ```php 161 | $user->ban([ 162 | 'expired_at' => '2086-03-28 00:00:00', 163 | ]); 164 | ``` 165 | 166 | `expired_at` attribute could be `\Carbon\Carbon` instance or any string which could be parsed by `\Carbon\Carbon::parse($string)` method: 167 | 168 | ```php 169 | $user->ban([ 170 | 'expired_at' => '+1 month', 171 | ]); 172 | ``` 173 | 174 | #### Remove ban from entity 175 | 176 | ```php 177 | $user->unban(); 178 | ``` 179 | 180 | On `unban` all related ban models are soft deletes. 181 | 182 | #### Check if entity is banned 183 | 184 | ```php 185 | $user->isBanned(); 186 | ``` 187 | 188 | #### Check if entity is not banned 189 | 190 | ```php 191 | $user->isNotBanned(); 192 | ``` 193 | 194 | #### Delete expired bans manually 195 | 196 | ```php 197 | app(\Cog\Contracts\Ban\BanService::class)->deleteExpiredBans(); 198 | ``` 199 | 200 | #### Determine if ban is permanent 201 | 202 | ```php 203 | $ban = $user->ban(); 204 | 205 | $ban->isPermanent(); // true 206 | ``` 207 | 208 | Or pass `null` value. 209 | 210 | ```php 211 | $ban = $user->ban([ 212 | 'expired_at' => null, 213 | ]); 214 | 215 | $ban->isPermanent(); // true 216 | ``` 217 | 218 | #### Determine if ban is temporary 219 | 220 | ```php 221 | $ban = $user->ban([ 222 | 'expired_at' => '2086-03-28 00:00:00', 223 | ]); 224 | 225 | $ban->isTemporary(); // true 226 | ``` 227 | 228 | ### Scopes 229 | 230 | #### Get all models which are not banned 231 | 232 | ```php 233 | $users = User::withoutBanned()->get(); 234 | ``` 235 | 236 | #### Get banned and not banned models 237 | 238 | ```php 239 | $users = User::withBanned()->get(); 240 | ``` 241 | 242 | #### Get only banned models 243 | 244 | ```php 245 | $users = User::onlyBanned()->get(); 246 | ``` 247 | 248 | #### Scope auto-apply 249 | 250 | To apply query scopes all the time you can define `shouldApplyBannedAtScope` method in bannable model. If method returns `true` all banned models will be hidden by default. 251 | 252 | ```php 253 | use Cog\Contracts\Ban\Bannable as BannableInterface; 254 | use Cog\Laravel\Ban\Traits\Bannable; 255 | use Illuminate\Foundation\Auth\User as Authenticatable; 256 | 257 | class User extends Authenticatable implements BannableInterface 258 | { 259 | use Bannable; 260 | 261 | /** 262 | * Determine if BannedAtScope should be applied by default. 263 | * 264 | * @return bool 265 | */ 266 | public function shouldApplyBannedAtScope() 267 | { 268 | return true; 269 | } 270 | } 271 | ``` 272 | 273 | ### Events 274 | 275 | If entity is banned `\Cog\Laravel\Ban\Events\ModelWasBanned` event is fired. 276 | 277 | Is entity is unbanned `\Cog\Laravel\Ban\Events\ModelWasUnbanned` event is fired. 278 | 279 | ### Middleware 280 | 281 | This package has route middleware designed to prevent banned users to go to protected routes. 282 | 283 | To use it define new middleware in `$routeMiddleware` array of `app/Http/Kernel.php` file: 284 | 285 | ```php 286 | protected $routeMiddleware = [ 287 | 'forbid-banned-user' => \Cog\Laravel\Ban\Http\Middleware\ForbidBannedUser::class, 288 | ] 289 | ``` 290 | 291 | Then use it in any routes and route groups you need to protect: 292 | 293 | ```php 294 | Route::get('/', [ 295 | 'uses' => 'UsersController@profile', 296 | 'middleware' => 'forbid-banned-user', 297 | ]); 298 | ``` 299 | 300 | If you want force logout banned user on protected routes access, use `LogsOutBannedUser` middleware instead: 301 | 302 | ```php 303 | protected $routeMiddleware = [ 304 | 'logs-out-banned-user' => \Cog\Laravel\Ban\Http\Middleware\LogsOutBannedUser::class, 305 | ] 306 | ``` 307 | 308 | ### Scheduling 309 | 310 | After you have performed the basic installation you can start using the `ban:delete-expired` command. In most cases you'll want to schedule these command so you don't have to manually run it everytime you need to delete expired bans and unban models. 311 | 312 | The command can be scheduled in Laravel's console kernel, just like any other command. 313 | 314 | ```php 315 | // app/Console/Kernel.php 316 | 317 | protected function schedule(Schedule $schedule) 318 | { 319 | $schedule->command('ban:delete-expired')->everyMinute(); 320 | } 321 | ``` 322 | 323 | Of course, the time used in the code above is just example. Adjust it to suit your own preferences. 324 | 325 | ## Integrations 326 | 327 | - [Laravel Nova Ban](https://github.com/cybercog/laravel-nova-ban) 328 | 329 | ## Changelog 330 | 331 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 332 | 333 | ## Upgrading 334 | 335 | Please see [UPGRADING](UPGRADING.md) for detailed upgrade instructions. 336 | 337 | ## Contributing 338 | 339 | Please see [CONTRIBUTING](CONTRIBUTING.md) for details. 340 | 341 | ## Testing 342 | 343 | Run the tests with: 344 | 345 | ```shell 346 | vendor/bin/phpunit 347 | ``` 348 | 349 | ## Security 350 | 351 | If you discover any security related issues, please email open@cybercog.su instead of using the issue tracker. 352 | 353 | ## Contributors 354 | 355 | | ![@antonkomarev](https://avatars.githubusercontent.com/u/1849174?s=110)
Anton Komarev
| ![@badrshs](https://avatars.githubusercontent.com/u/26596347?s=110)
badr aldeen shek salim
| ![@rickmacgillis](https://avatars.githubusercontent.com/u/8941225?s=110)
Rick Mac Gillis
| ![@AnsellC](https://avatars.githubusercontent.com/u/2049714?s=110)
AnsellC
| ![@joearcher](https://avatars.githubusercontent.com/u/1125046?s=110)
Joe Archer
| 356 | | :---: | :---: |:--------------------------------------------------------------------------------------------------------------------------------------------:| :---: | :---: | 357 | | ![@Im-Fran](https://avatars.githubusercontent.com/u/30329003?s=110)
Francisco Solis
| ![@jadamec](https://avatars.githubusercontent.com/u/19595874?s=110)
Jakub Adamec
| ![@ilzrv](https://avatars.githubusercontent.com/u/28765966?s=110)
Ilia Lazarev
| ![@ZeoKnight](https://avatars.githubusercontent.com/u/1521472?s=110)
ZeoKnight
| | 358 | 359 | [Laravel Ban contributors list](../../contributors) 360 | 361 | ## Alternatives 362 | 363 | - https://github.com/imanghafoori1/laravel-temp-tag 364 | 365 | ## License 366 | 367 | - `Laravel Ban` package is open-sourced software licensed under the [MIT License](LICENSE) by [Anton Komarev]. 368 | - `Fat Boss In Jail` image licensed under [Creative Commons 3.0](https://creativecommons.org/licenses/by/3.0/us/) by Gan Khoon Lay. 369 | 370 | ## 🌟 Stargazers over time 371 | 372 | [![Stargazers over time](https://chart.yhype.me/github/repository-star/v1/83971055.svg)](https://yhype.me?utm_source=github&utm_medium=cybercog-laravel-ban&utm_content=chart-repository-star-cumulative) 373 | 374 | ## About CyberCog 375 | 376 | [CyberCog](https://cybercog.su) is a Social Unity of enthusiasts. Research the best solutions in product & software development is our passion. 377 | 378 | - [Follow us on Twitter](https://twitter.com/cybercog) 379 | - [Read our articles on Medium](https://medium.com/cybercog) 380 | 381 | CyberCog 382 | 383 | [Anton Komarev]: https://komarev.com 384 | -------------------------------------------------------------------------------- /UPGRADING.md: -------------------------------------------------------------------------------- 1 | # Upgrade Guide 2 | 3 | - [From v2 to v3](#from-v2-to-v3) 4 | 5 | ## From v2 to v3 6 | 7 | Because there are many breaking changes an upgrade is not that easy. There are many edge cases this guide does not cover. 8 | We accept PRs to improve this guide. 9 | 10 | Find and replace: 11 | 12 | - Find all `Cog\Ban\Contracts\Ban` and replace with `Cog\Contracts\Ban\Ban` 13 | - Find all `Cog\Ban\Contracts\HasBans` and replace with `Cog\Contracts\Ban\Bannable` 14 | - Find all `Cog\Ban\Contracts\BanService` and replace with `Cog\Contracts\Ban\BanService` 15 | - Find all `Cog\Ban\Traits\HasBans` and replace with `Cog\Laravel\Ban\Traits\Bannable` 16 | - Find all `Cog\Ban` and replace with `Cog\Laravel\Ban` 17 | 18 | In classes which works with bans: 19 | 20 | - Find `Ban::whereOwnedBy` replace with `Ban::whereBannable` 21 | - Find calls of methods or attributes on the Ban model like `ownedBy`, `owner`, `getOwner` and replace them with `bannable` 22 | 23 | These database changes should be performed: 24 | 25 | - Rename `ban` table to `bans` 26 | - Rename `bans` database column `owned_by_id` to `bannable_id` 27 | - Rename `bans` database column `owned_by_type` to `bannable_type` 28 | - Update name of migration file in `migrations` table from `2017_03_04_000000_create_ban_table` to `2017_03_04_000000_create_bans_table` 29 | 30 | To make all changes in MySQL you could run these 3 commands one by one: 31 | 32 | ```mysql 33 | ALTER TABLE `ban` RENAME TO `bans`; 34 | 35 | ALTER TABLE `bans` 36 | CHANGE COLUMN `owned_by_id` `bannable_id` INT(10) UNSIGNED NOT NULL, 37 | CHANGE COLUMN `owned_by_type` `bannable_type` VARCHAR(255) NOT NULL, 38 | DROP INDEX `ban_owned_by_id_owned_by_type_index`, 39 | ADD INDEX `ban_bannable_id_bannable_type_index` (`bannable_id` ASC, `bannable_type` ASC); 40 | 41 | UPDATE `migrations` 42 | SET `migration` = '2017_03_04_000000_create_bans_table' 43 | WHERE `migration` = '2017_03_04_000000_create_ban_table' 44 | LIMIT 1; 45 | ``` 46 | 47 | Migration files: 48 | 49 | - Delete `database/migrations/2017_03_04_000000_create_ban_table.php` migration file (from v3 service provider automatically loading migration files or republish it if custom changes are required to be done). 50 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cybercog/laravel-ban", 3 | "description": "Laravel Ban simplify blocking and banning Eloquent models.", 4 | "type": "library", 5 | "license": "MIT", 6 | "keywords": [ 7 | "cybercog", 8 | "cog", 9 | "laravel", 10 | "eloquent", 11 | "trait", 12 | "justice", 13 | "user", 14 | "ban", 15 | "block", 16 | "restrict", 17 | "forbid", 18 | "arrest", 19 | "jail" 20 | ], 21 | "authors": [ 22 | { 23 | "name": "Anton Komarev", 24 | "email": "anton@komarev.com", 25 | "homepage": "https://komarev.com", 26 | "role": "Developer" 27 | } 28 | ], 29 | "homepage": "https://komarev.com/sources/laravel-ban", 30 | "support": { 31 | "email": "open@cybercog.su", 32 | "issues": "https://github.com/cybercog/laravel-ban/issues", 33 | "wiki": "https://github.com/cybercog/laravel-ban/wiki", 34 | "source": "https://github.com/cybercog/laravel-ban", 35 | "docs": "https://github.com/cybercog/laravel-ban/wiki" 36 | }, 37 | "require": { 38 | "php": "^8.0", 39 | "illuminate/database": "^9.0|^10.0|^11.0|^12.0", 40 | "illuminate/events": "^9.0|^10.0|^11.0|^12.0", 41 | "illuminate/support": "^9.0|^10.0|^11.0|^12.0" 42 | }, 43 | "require-dev": { 44 | "mockery/mockery": "^1.0", 45 | "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", 46 | "phpunit/phpunit": "^9.6|^10.5|^11.5.3" 47 | }, 48 | "autoload": { 49 | "psr-4": { 50 | "Cog\\Contracts\\Ban\\": "contracts/", 51 | "Cog\\Laravel\\Ban\\": "src/" 52 | } 53 | }, 54 | "autoload-dev": { 55 | "psr-4": { 56 | "Cog\\Tests\\Laravel\\Ban\\": "tests/", 57 | "Cog\\Tests\\Laravel\\Ban\\Database\\Factories\\": "tests/database/factories" 58 | } 59 | }, 60 | "scripts": { 61 | "test": "vendor/bin/phpunit" 62 | }, 63 | "config": { 64 | "sort-packages": true 65 | }, 66 | "extra": { 67 | "laravel": { 68 | "providers": [ 69 | "Cog\\Laravel\\Ban\\Providers\\BanServiceProvider" 70 | ] 71 | } 72 | }, 73 | "minimum-stability": "dev", 74 | "prefer-stable": true 75 | } 76 | -------------------------------------------------------------------------------- /config/ban.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | return [ 15 | 16 | /* 17 | |-------------------------------------------------------------------------- 18 | | Ban Database Migrations 19 | |-------------------------------------------------------------------------- 20 | | 21 | | Determine if default package migrations should be registered. 22 | | Set value to `false` when using customized migrations. 23 | | 24 | */ 25 | 26 | 'load_default_migrations' => true, 27 | 28 | /* 29 | |--------------------------------------------------------------------------- 30 | | URL to redirect banned user to 31 | |--------------------------------------------------------------------------- 32 | | 33 | | Provide a url, this is where a banned user will be redirected to 34 | | by the middleware. 35 | | 36 | | For example: 37 | | 38 | | 'redirect_url' => route('banned.user'), 39 | | 40 | | or 41 | | 42 | | 'redirect_url' => '/user/banned', 43 | | 44 | | Leaving the value as null will result in a redirect "back". 45 | | 46 | */ 47 | 48 | 'redirect_url' => null, 49 | 50 | ]; 51 | -------------------------------------------------------------------------------- /contracts/Ban.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Contracts\Ban; 15 | 16 | interface Ban 17 | { 18 | /** 19 | * Determine if Ban is permanent. 20 | * 21 | * @return bool 22 | */ 23 | public function isPermanent(): bool; 24 | 25 | /** 26 | * Determine if Ban is temporary. 27 | * 28 | * @return bool 29 | */ 30 | public function isTemporary(): bool; 31 | } 32 | -------------------------------------------------------------------------------- /contracts/BanService.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Contracts\Ban; 15 | 16 | interface BanService 17 | { 18 | /** 19 | * Ban entity. 20 | * 21 | * @param \Cog\Contracts\Ban\Bannable $bannable 22 | * @param array $attributes 23 | * @return \Cog\Contracts\Ban\Ban 24 | */ 25 | public function ban(Bannable $bannable, array $attributes = []): Ban; 26 | 27 | /** 28 | * Unban entity. 29 | * 30 | * @param \Cog\Contracts\Ban\Bannable $bannable 31 | * @return void 32 | */ 33 | public function unban(Bannable $bannable): void; 34 | 35 | /** 36 | * Delete all expired Ban models. 37 | * 38 | * @return void 39 | */ 40 | public function deleteExpiredBans(): void; 41 | } 42 | -------------------------------------------------------------------------------- /contracts/Bannable.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Contracts\Ban; 15 | 16 | interface Bannable 17 | { 18 | /** 19 | * Ban model. 20 | * 21 | * @param null|array $attributes 22 | * @return \Cog\Contracts\Ban\Ban 23 | */ 24 | public function ban(array $attributes = []): Ban; 25 | 26 | /** 27 | * Remove ban from model. 28 | * 29 | * @return void 30 | */ 31 | public function unban(): void; 32 | 33 | /** 34 | * If model is banned. 35 | * 36 | * @return bool 37 | */ 38 | public function isBanned(): bool; 39 | 40 | /** 41 | * If model is not banned. 42 | * 43 | * @return bool 44 | */ 45 | public function isNotBanned(): bool; 46 | } 47 | -------------------------------------------------------------------------------- /database/migrations/2017_03_04_000000_create_bans_table.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | use Illuminate\Database\Migrations\Migration; 15 | use Illuminate\Database\Schema\Blueprint; 16 | use Illuminate\Support\Facades\Schema; 17 | 18 | class CreateBansTable extends Migration 19 | { 20 | /** 21 | * Run the migrations. 22 | * 23 | * @return void 24 | */ 25 | public function up(): void 26 | { 27 | Schema::create('bans', function (Blueprint $table) { 28 | $table->increments('id'); 29 | $table->morphs('bannable'); 30 | $table->nullableMorphs('created_by'); 31 | $table->text('comment')->nullable(); 32 | $table->timestamp('expired_at')->nullable(); 33 | $table->softDeletes(); 34 | $table->timestamps(); 35 | 36 | $table->index('expired_at'); 37 | }); 38 | } 39 | 40 | /** 41 | * Reverse the migrations. 42 | * 43 | * @return void 44 | */ 45 | public function down(): void 46 | { 47 | Schema::dropIfExists('bans'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Console/Commands/DeleteExpiredBans.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Console\Commands; 15 | 16 | use Cog\Laravel\Ban\Services\BanService; 17 | use Illuminate\Console\Command; 18 | 19 | class DeleteExpiredBans extends Command 20 | { 21 | /** 22 | * The name and signature of the console command. 23 | * 24 | * @var string 25 | */ 26 | protected $signature = 'ban:delete-expired'; 27 | 28 | /** 29 | * The console command description. 30 | * 31 | * @var string 32 | */ 33 | protected $description = 'Delete expired ban models.'; 34 | 35 | /** 36 | * Ban service. 37 | * 38 | * @var \Cog\Contracts\Ban\BanService 39 | */ 40 | protected $service; 41 | 42 | /** 43 | * Execute the console command. 44 | * 45 | * @return void 46 | */ 47 | public function handle(): void 48 | { 49 | $this->service = app(BanService::class); 50 | 51 | $this->service->deleteExpiredBans(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Events/ModelWasBanned.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Events; 15 | 16 | use Cog\Contracts\Ban\Ban as BanContract; 17 | use Cog\Contracts\Ban\Bannable as BannableContract; 18 | use Illuminate\Contracts\Queue\ShouldQueue; 19 | 20 | class ModelWasBanned implements ShouldQueue 21 | { 22 | /** 23 | * @var \Cog\Contracts\Ban\Bannable 24 | */ 25 | public $model; 26 | 27 | /** 28 | * @var \Cog\Contracts\Ban\Ban 29 | */ 30 | public $ban; 31 | 32 | /** 33 | * @param \Cog\Contracts\Ban\Bannable $bannable 34 | * @param \Cog\Contracts\Ban\Ban $ban 35 | */ 36 | public function __construct(BannableContract $bannable, BanContract $ban) 37 | { 38 | $this->model = $bannable; 39 | $this->ban = $ban; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Events/ModelWasUnbanned.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Events; 15 | 16 | use Cog\Contracts\Ban\Bannable as BannableContract; 17 | use Illuminate\Contracts\Queue\ShouldQueue; 18 | 19 | class ModelWasUnbanned implements ShouldQueue 20 | { 21 | /** 22 | * @var \Cog\Contracts\Ban\Bannable 23 | */ 24 | public $model; 25 | 26 | /** 27 | * @param \Cog\Contracts\Ban\Bannable $model 28 | */ 29 | public function __construct(BannableContract $model) 30 | { 31 | $this->model = $model; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Http/Middleware/ForbidBannedUser.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Http\Middleware; 15 | 16 | use Closure; 17 | use Cog\Contracts\Ban\Bannable as BannableContract; 18 | use Illuminate\Contracts\Auth\Guard; 19 | 20 | class ForbidBannedUser 21 | { 22 | /** 23 | * The Guard implementation. 24 | * 25 | * @var \Illuminate\Contracts\Auth\Guard 26 | */ 27 | protected $auth; 28 | 29 | /** 30 | * @param \Illuminate\Contracts\Auth\Guard $auth 31 | */ 32 | public function __construct(Guard $auth) 33 | { 34 | $this->auth = $auth; 35 | } 36 | 37 | /** 38 | * Handle an incoming request. 39 | * 40 | * @param \Illuminate\Http\Request $request 41 | * @param \Closure $next 42 | * @return mixed 43 | * 44 | * @throws \Exception 45 | */ 46 | public function handle($request, Closure $next) 47 | { 48 | $user = $this->auth->user(); 49 | 50 | if ($user && $user instanceof BannableContract && $user->isBanned()) { 51 | $redirectUrl = config('ban.redirect_url', null); 52 | $errors = [ 53 | 'login' => 'This account is blocked.', 54 | ]; 55 | 56 | $responseCode = $request->header('X-Inertia') ? 303 : 302; 57 | if ($redirectUrl === null) { 58 | return redirect()->back($responseCode)->withInput()->withErrors($errors); 59 | } else { 60 | return redirect($redirectUrl, $responseCode)->withInput()->withErrors($errors); 61 | } 62 | } 63 | 64 | return $next($request); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Http/Middleware/LogsOutBannedUser.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Http\Middleware; 15 | 16 | use Closure; 17 | use Cog\Contracts\Ban\Bannable as BannableContract; 18 | use Illuminate\Contracts\Auth\Guard; 19 | use Illuminate\Contracts\Auth\StatefulGuard as StatefulGuardContract; 20 | 21 | class LogsOutBannedUser 22 | { 23 | /** 24 | * The Guard implementation. 25 | * 26 | * @var \Illuminate\Contracts\Auth\Guard 27 | */ 28 | protected $auth; 29 | 30 | /** 31 | * @param \Illuminate\Contracts\Auth\Guard $auth 32 | */ 33 | public function __construct(Guard $auth) 34 | { 35 | $this->auth = $auth; 36 | } 37 | 38 | /** 39 | * Handle an incoming request. 40 | * 41 | * @param \Illuminate\Http\Request $request 42 | * @param \Closure $next 43 | * @return mixed 44 | * 45 | * @throws \Exception 46 | */ 47 | public function handle($request, Closure $next) 48 | { 49 | $user = $this->auth->user(); 50 | 51 | if ($user && $user instanceof BannableContract && $user->isBanned()) { 52 | if ($this->auth instanceof StatefulGuardContract) { 53 | // TODO: Cover with tests 54 | $this->auth->logout(); 55 | } 56 | 57 | $redirectUrl = config('ban.redirect_url', null); 58 | $errors = [ 59 | 'login' => 'This account is blocked.', 60 | ]; 61 | 62 | $responseCode = $request->header('X-Inertia') ? 303 : 302; 63 | if ($redirectUrl === null) { 64 | return redirect()->back($responseCode)->withInput()->withErrors($errors); 65 | } else { 66 | return redirect($redirectUrl, $responseCode)->withInput()->withErrors($errors); 67 | } 68 | } 69 | 70 | return $next($request); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Models/Ban.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Models; 15 | 16 | use Cog\Contracts\Ban\Ban as BanContract; 17 | use Cog\Contracts\Ban\Bannable as BannableContract; 18 | use Illuminate\Database\Eloquent\Builder; 19 | use Illuminate\Database\Eloquent\Factories\HasFactory; 20 | use Illuminate\Database\Eloquent\Model; 21 | use Illuminate\Database\Eloquent\Relations\MorphTo; 22 | use Illuminate\Database\Eloquent\SoftDeletes; 23 | use Illuminate\Support\Carbon; 24 | 25 | class Ban extends Model implements BanContract 26 | { 27 | use HasFactory; 28 | use SoftDeletes; 29 | 30 | /** 31 | * The table associated with the model. 32 | * 33 | * @var string 34 | */ 35 | protected $table = 'bans'; 36 | 37 | /** 38 | * The attributes that are mass assignable. 39 | * 40 | * @var array 41 | */ 42 | protected $fillable = [ 43 | 'comment', 44 | 'expired_at', 45 | 'created_by_type', 46 | 'created_by_id', 47 | ]; 48 | 49 | /** 50 | * The attributes that should be cast to native types. 51 | * 52 | * @var array 53 | */ 54 | protected $casts = [ 55 | 'expired_at' => 'datetime', 56 | 'deleted_at' => 'datetime', 57 | ]; 58 | 59 | /** 60 | * Expired timestamp mutator. 61 | * 62 | * @param \Illuminate\Support\Carbon|string $value 63 | * @return void 64 | */ 65 | public function setExpiredAtAttribute($value): void 66 | { 67 | if (!is_null($value) && !$value instanceof Carbon) { 68 | $value = Carbon::parse($value); 69 | } 70 | 71 | $this->attributes['expired_at'] = $value; 72 | } 73 | 74 | /** 75 | * Entity responsible for ban. 76 | * 77 | * @return \Illuminate\Database\Eloquent\Relations\MorphTo 78 | */ 79 | public function createdBy(): MorphTo 80 | { 81 | return $this->morphTo('created_by'); 82 | } 83 | 84 | /** 85 | * Bannable model. 86 | * 87 | * @return \Illuminate\Database\Eloquent\Relations\MorphTo 88 | */ 89 | public function bannable(): MorphTo 90 | { 91 | return $this->morphTo('bannable'); 92 | } 93 | 94 | /** 95 | * Determine if Ban is permanent. 96 | * 97 | * @return bool 98 | */ 99 | public function isPermanent(): bool 100 | { 101 | return !isset($this->attributes['expired_at']) || is_null($this->attributes['expired_at']); 102 | } 103 | 104 | /** 105 | * Determine if Ban is temporary. 106 | * 107 | * @return bool 108 | */ 109 | public function isTemporary(): bool 110 | { 111 | return !$this->isPermanent(); 112 | } 113 | 114 | /** 115 | * Scope a query to only include models by owner. 116 | * 117 | * @param \Illuminate\Database\Eloquent\Builder $query 118 | * @param \Cog\Contracts\Ban\Bannable $bannable 119 | * @return \Illuminate\Database\Eloquent\Builder 120 | */ 121 | public function scopeWhereBannable(Builder $query, BannableContract $bannable): Builder 122 | { 123 | return $query->where([ 124 | 'bannable_type' => $bannable->getMorphClass(), 125 | 'bannable_id' => $bannable->getKey(), 126 | ]); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/Observers/BanObserver.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Observers; 15 | 16 | use Cog\Contracts\Ban\Ban as BanContract; 17 | use Cog\Laravel\Ban\Events\ModelWasBanned; 18 | use Cog\Laravel\Ban\Events\ModelWasUnbanned; 19 | 20 | class BanObserver 21 | { 22 | /** 23 | * Handle the creating event for the Ban model. 24 | * 25 | * @param \Cog\Contracts\Ban\Ban $ban 26 | * @return void 27 | */ 28 | public function creating(BanContract $ban): void 29 | { 30 | $bannedBy = auth()->user(); 31 | if ($bannedBy && is_null($ban->created_by_type) && is_null($ban->created_by_id)) { 32 | $ban->fill([ 33 | 'created_by_type' => $bannedBy->getMorphClass(), 34 | 'created_by_id' => $bannedBy->getKey(), 35 | ]); 36 | } 37 | } 38 | 39 | /** 40 | * Handle the created event for the Ban model. 41 | * 42 | * @param \Cog\Contracts\Ban\Ban $ban 43 | * @return void 44 | */ 45 | public function created(BanContract $ban): void 46 | { 47 | $bannable = $ban->bannable()->withBanned()->first(); 48 | $bannable->setBannedFlag($ban->created_at)->save(); 49 | 50 | event(new ModelWasBanned($bannable, $ban)); 51 | } 52 | 53 | /** 54 | * Handle the deleted event for the Ban model. 55 | * 56 | * @param \Cog\Contracts\Ban\Ban $ban 57 | * @return void 58 | */ 59 | public function deleted(BanContract $ban): void 60 | { 61 | $bannable = $ban->bannable()->withBanned()->first(); 62 | if ($bannable->bans->count() === 0) { 63 | $bannable->unsetBannedFlag()->save(); 64 | 65 | event(new ModelWasUnbanned($bannable)); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Providers/BanServiceProvider.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Providers; 15 | 16 | use Cog\Contracts\Ban\Ban as BanContract; 17 | use Cog\Contracts\Ban\BanService as BanServiceContract; 18 | use Cog\Laravel\Ban\Console\Commands\DeleteExpiredBans; 19 | use Cog\Laravel\Ban\Models\Ban; 20 | use Cog\Laravel\Ban\Observers\BanObserver; 21 | use Cog\Laravel\Ban\Services\BanService; 22 | use Illuminate\Support\Facades\Config; 23 | use Illuminate\Support\ServiceProvider; 24 | 25 | class BanServiceProvider extends ServiceProvider 26 | { 27 | /** 28 | * Register bindings in the container. 29 | * 30 | * @return void 31 | */ 32 | public function register(): void 33 | { 34 | $this->registerContracts(); 35 | $this->registerConsoleCommands(); 36 | } 37 | 38 | /** 39 | * Perform post-registration booting of services. 40 | * 41 | * @return void 42 | * 43 | * @throws \Illuminate\Contracts\Container\BindingResolutionException 44 | */ 45 | public function boot(): void 46 | { 47 | $this->configure(); 48 | $this->registerPublishes(); 49 | $this->registerObservers(); 50 | } 51 | 52 | /** 53 | * Register Ban's console commands. 54 | * 55 | * @return void 56 | */ 57 | protected function registerConsoleCommands(): void 58 | { 59 | if ($this->app->runningInConsole()) { 60 | $this->app->bind('command.ban:delete-expired', DeleteExpiredBans::class); 61 | 62 | $this->commands([ 63 | 'command.ban:delete-expired', 64 | ]); 65 | } 66 | } 67 | 68 | /** 69 | * Register Ban's classes in the container. 70 | * 71 | * @return void 72 | */ 73 | protected function registerContracts(): void 74 | { 75 | $this->app->bind(BanContract::class, Ban::class); 76 | $this->app->singleton(BanServiceContract::class, BanService::class); 77 | } 78 | 79 | /** 80 | * Register Ban's models observers. 81 | * 82 | * @return void 83 | * 84 | * @throws \Illuminate\Contracts\Container\BindingResolutionException 85 | */ 86 | protected function registerObservers(): void 87 | { 88 | $this->app->make(BanContract::class)->observe(new BanObserver); 89 | } 90 | 91 | /** 92 | * Setup the resource publishing groups for Ban. 93 | * 94 | * @return void 95 | */ 96 | protected function registerPublishes(): void 97 | { 98 | if ($this->app->runningInConsole()) { 99 | $this->publishes([ 100 | __DIR__ . '/../../config/ban.php' => config_path('ban.php'), 101 | ], 'ban-config'); 102 | 103 | $this->publishes([ 104 | __DIR__ . '/../../database/migrations' => database_path('migrations'), 105 | ], 'migrations'); 106 | } 107 | 108 | $this->registerMigrations(); 109 | } 110 | 111 | /** 112 | * Register the Ban migrations. 113 | * 114 | * @return void 115 | */ 116 | private function registerMigrations(): void 117 | { 118 | if ($this->app->runningInConsole() && $this->shouldLoadDefaultMigrations()) { 119 | $this->loadMigrationsFrom(__DIR__ . '/../../database/migrations'); 120 | } 121 | } 122 | 123 | /** 124 | * Merge Ban configuration with the application configuration. 125 | * 126 | * @return void 127 | */ 128 | private function configure(): void 129 | { 130 | if (!$this->app->configurationIsCached()) { 131 | $this->mergeConfigFrom(__DIR__ . '/../../config/ban.php', 'ban'); 132 | } 133 | } 134 | 135 | /** 136 | * Determine if we should register default migrations. 137 | * 138 | * @return bool 139 | */ 140 | private function shouldLoadDefaultMigrations(): bool 141 | { 142 | return Config::get('ban.load_default_migrations', true); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/Scopes/BannedAtScope.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Scopes; 15 | 16 | use Illuminate\Database\Eloquent\Builder; 17 | use Illuminate\Database\Eloquent\Model; 18 | use Illuminate\Database\Eloquent\Scope; 19 | 20 | class BannedAtScope implements Scope 21 | { 22 | /** 23 | * All of the extensions to be added to the builder. 24 | * 25 | * @var array 26 | */ 27 | protected $extensions = [ 28 | 'WithBanned', 29 | 'WithoutBanned', 30 | 'OnlyBanned', 31 | ]; 32 | 33 | /** 34 | * Apply the scope to a given Eloquent query builder. 35 | * 36 | * @param \Illuminate\Database\Eloquent\Builder $builder 37 | * @param \Illuminate\Database\Eloquent\Model $model 38 | * @return \Illuminate\Database\Eloquent\Builder 39 | */ 40 | public function apply(Builder $builder, Model $model) 41 | { 42 | if (method_exists($model, 'shouldApplyBannedAtScope') && $model->shouldApplyBannedAtScope()) { 43 | return $builder->whereNull('banned_at'); 44 | } 45 | 46 | return $builder; 47 | } 48 | 49 | /** 50 | * Extend the query builder with the needed functions. 51 | * 52 | * @param \Illuminate\Database\Eloquent\Builder $builder 53 | * @return void 54 | */ 55 | public function extend(Builder $builder): void 56 | { 57 | foreach ($this->extensions as $extension) { 58 | $this->{"add{$extension}"}($builder); 59 | } 60 | } 61 | 62 | /** 63 | * Add the `withBanned` extension to the builder. 64 | * 65 | * @param \Illuminate\Database\Eloquent\Builder $builder 66 | * @return void 67 | */ 68 | protected function addWithBanned(Builder $builder): void 69 | { 70 | $builder->macro('withBanned', function (Builder $builder) { 71 | return $builder->withoutGlobalScope($this); 72 | }); 73 | } 74 | 75 | /** 76 | * Add the `withoutBanned` extension to the builder. 77 | * 78 | * @param \Illuminate\Database\Eloquent\Builder $builder 79 | * @return void 80 | */ 81 | protected function addWithoutBanned(Builder $builder): void 82 | { 83 | $builder->macro('withoutBanned', function (Builder $builder) { 84 | return $builder->withoutGlobalScope($this)->whereNull('banned_at'); 85 | }); 86 | } 87 | 88 | /** 89 | * Add the `onlyBanned` extension to the builder. 90 | * 91 | * @param \Illuminate\Database\Eloquent\Builder $builder 92 | * @return void 93 | */ 94 | protected function addOnlyBanned(Builder $builder): void 95 | { 96 | $builder->macro('onlyBanned', function (Builder $builder) { 97 | return $builder->withoutGlobalScope($this)->whereNotNull('banned_at'); 98 | }); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Services/BanService.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Services; 15 | 16 | use Cog\Contracts\Ban\Ban as BanContract; 17 | use Cog\Contracts\Ban\Bannable as BannableContract; 18 | use Cog\Contracts\Ban\BanService as BanServiceContract; 19 | use Cog\Laravel\Ban\Models\Ban; 20 | use Illuminate\Support\Carbon; 21 | 22 | class BanService implements BanServiceContract 23 | { 24 | /** 25 | * Ban entity. 26 | * 27 | * @param \Cog\Contracts\Ban\Bannable $bannable 28 | * @param array $attributes 29 | * @return \Cog\Contracts\Ban\Ban 30 | */ 31 | public function ban(BannableContract $bannable, array $attributes = []): BanContract 32 | { 33 | return $bannable->bans()->create($attributes); 34 | } 35 | 36 | /** 37 | * Unban entity. 38 | * 39 | * @param \Cog\Contracts\Ban\Bannable $bannable 40 | * @return void 41 | */ 42 | public function unban(BannableContract $bannable): void 43 | { 44 | $bannable->bans->each(function ($ban) { 45 | $ban->delete(); 46 | }); 47 | } 48 | 49 | /** 50 | * Delete all expired Ban models. 51 | * 52 | * @return void 53 | */ 54 | public function deleteExpiredBans(): void 55 | { 56 | $bans = Ban::query() 57 | ->where('expired_at', '<=', Carbon::now()->format('Y-m-d H:i:s')) 58 | ->get(); 59 | 60 | $bans->each(function ($ban) { 61 | $ban->delete(); 62 | }); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Traits/Bannable.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Traits; 15 | 16 | trait Bannable 17 | { 18 | use HasBannedAtHelpers; 19 | use HasBannedAtScope; 20 | use HasBansRelation; 21 | } 22 | -------------------------------------------------------------------------------- /src/Traits/HasBannedAtHelpers.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Traits; 15 | 16 | use Cog\Contracts\Ban\Ban as BanContract; 17 | use Cog\Contracts\Ban\BanService as BanServiceContract; 18 | use Illuminate\Support\Carbon; 19 | 20 | trait HasBannedAtHelpers 21 | { 22 | /** 23 | * Set banned flag. 24 | * 25 | * @return $this 26 | */ 27 | public function setBannedFlag() 28 | { 29 | $this->setAttribute('banned_at', Carbon::now()); 30 | 31 | return $this; 32 | } 33 | 34 | /** 35 | * Unset banned flag. 36 | * 37 | * @return $this 38 | */ 39 | public function unsetBannedFlag() 40 | { 41 | $this->setAttribute('banned_at', null); 42 | 43 | return $this; 44 | } 45 | 46 | /** 47 | * If model is banned. 48 | * 49 | * @return bool 50 | */ 51 | public function isBanned(): bool 52 | { 53 | return $this->getAttributeValue('banned_at') !== null; 54 | } 55 | 56 | /** 57 | * If model is not banned. 58 | * 59 | * @return bool 60 | */ 61 | public function isNotBanned(): bool 62 | { 63 | return !$this->isBanned(); 64 | } 65 | 66 | /** 67 | * Ban model. 68 | * 69 | * @param null|array $attributes 70 | * @return \Cog\Contracts\Ban\Ban 71 | */ 72 | public function ban(array $attributes = []): BanContract 73 | { 74 | return app(BanServiceContract::class)->ban($this, $attributes); 75 | } 76 | 77 | /** 78 | * Remove ban from model. 79 | * 80 | * @return void 81 | */ 82 | public function unban(): void 83 | { 84 | app(BanServiceContract::class)->unban($this); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Traits/HasBannedAtScope.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Traits; 15 | 16 | use Cog\Laravel\Ban\Scopes\BannedAtScope; 17 | 18 | trait HasBannedAtScope 19 | { 20 | /** 21 | * Boot the HasBannedAtScope trait for a model. 22 | * 23 | * @return void 24 | */ 25 | public static function bootHasBannedAtScope(): void 26 | { 27 | static::addGlobalScope(new BannedAtScope()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Traits/HasBansRelation.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | declare(strict_types=1); 13 | 14 | namespace Cog\Laravel\Ban\Traits; 15 | 16 | use Cog\Contracts\Ban\Ban as BanContract; 17 | use Illuminate\Database\Eloquent\Relations\MorphMany; 18 | 19 | trait HasBansRelation 20 | { 21 | /** 22 | * Entity Bans. 23 | * 24 | * @return \Illuminate\Database\Eloquent\Relations\MorphMany 25 | */ 26 | public function bans(): MorphMany 27 | { 28 | return $this->morphMany(app(BanContract::class), 'bannable'); 29 | } 30 | } 31 | --------------------------------------------------------------------------------