{"id":41199892,"url":"https://github.com/mchev/banhammer","last_synced_at":"2026-01-22T20:41:09.418Z","repository":{"id":65815105,"uuid":"600413975","full_name":"mchev/banhammer","owner":"mchev","description":"Banhammer for Laravel offers a simple way to ban any Model by ID, UUID and by IP or Country.","archived":false,"fork":false,"pushed_at":"2025-07-28T14:15:42.000Z","size":135,"stargazers_count":355,"open_issues_count":0,"forks_count":27,"subscribers_count":3,"default_branch":"2.x","last_synced_at":"2025-07-28T16:11:27.940Z","etag":null,"topics":["access","autorization","ban","block","countries","ip","laravel","middleware","package","php","restrict","security","trait","user"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mchev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"mchev"}},"created_at":"2023-02-11T12:22:30.000Z","updated_at":"2025-07-28T14:11:48.000Z","dependencies_parsed_at":"2023-12-19T10:02:31.035Z","dependency_job_id":"5f947f1d-38ad-42bb-b502-933f5940a2e1","html_url":"https://github.com/mchev/banhammer","commit_stats":{"total_commits":84,"total_committers":4,"mean_commits":21.0,"dds":"0.19047619047619047","last_synced_commit":"71720458639f290fdd682850ec66b2c21d172333"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/mchev/banhammer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchev%2Fbanhammer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchev%2Fbanhammer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchev%2Fbanhammer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchev%2Fbanhammer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mchev","download_url":"https://codeload.github.com/mchev/banhammer/tar.gz/refs/heads/2.x","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mchev%2Fbanhammer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28670595,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T19:36:09.361Z","status":"ssl_error","status_checked_at":"2026-01-22T19:36:05.567Z","response_time":144,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["access","autorization","ban","block","countries","ip","laravel","middleware","package","php","restrict","security","trait","user"],"created_at":"2026-01-22T20:41:08.819Z","updated_at":"2026-01-22T20:41:09.400Z","avatar_url":"https://github.com/mchev.png","language":"PHP","funding_links":["https://github.com/sponsors/mchev"],"categories":[],"sub_categories":[],"readme":"# Banhammer 🔨\n\n\u003e A simple and powerful ban package for Laravel - ban models, IPs, and countries with ease.\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/mchev/banhammer.svg?style=flat-square)](https://packagist.org/packages/mchev/banhammer)\n[![GitHub Tests Action Status](https://github.com/laravel/pint/workflows/tests/badge.svg)](https://github.com/mchev/banhammer/actions/workflows/run-tests.yml)\n[![Total Downloads](https://img.shields.io/packagist/dt/mchev/banhammer.svg?style=flat-square)](https://packagist.org/packages/mchev/banhammer)\n[![Package for laravel](https://img.shields.io/badge/Package%20for%20Laravel-grey.svg?style=flat-square\u0026logo=laravel\u0026logoColor=white)](https://packagist.org/packages/mchev/banhammer)\n\nBanhammer allows you to ban any Eloquent model, IP addresses, and even entire countries. Bans can be permanent or temporary with automatic expiration.\n\n---\n\n## 📋 Table of Contents\n\n- [Quick Start](#-quick-start)\n- [Features](#-features)\n- [Installation](#-installation)\n- [Usage Guide](#-usage-guide)\n  - [Banning Models](#banning-models)\n  - [Banning IPs](#banning-ips)\n  - [Country Blocking](#country-blocking)\n  - [Middleware](#middleware)\n  - [Scheduler](#scheduler)\n  - [Events](#events)\n- [Advanced Topics](#-advanced-topics)\n  - [Metas](#metas)\n  - [UUIDs](#uuids)\n  - [Upgrading](#upgrading-to-20-from-1x)\n- [Development](#-development)\n\n---\n\n## 🚀 Quick Start\n\n```bash\ncomposer require mchev/banhammer\nphp artisan vendor:publish --provider=\"Mchev\\Banhammer\\BanhammerServiceProvider\" --tag=\"migrations\"\nphp artisan migrate\n```\n\nAdd the trait to your model:\n\n```php\nuse Mchev\\Banhammer\\Traits\\Bannable;\n\nclass User extends Model\n{\n    use Bannable;\n}\n```\n\nBan a user:\n\n```php\n$user-\u003eban();\n```\n\n---\n\n## ✨ Features\n\n- ✅ Ban any Eloquent model (User, Team, etc.)\n- ✅ Ban IP addresses (single or multiple)\n- ✅ Block entire countries\n- ✅ Temporary or permanent bans\n- ✅ Automatic expiration handling\n- ✅ Middleware protection\n- ✅ Event system\n- ✅ Metadata support\n- ✅ Laravel 9, 10, 11 \u0026 12 compatible\n\n---\n\n## 📦 Installation\n\n### Requirements\n\n- PHP 8.0+\n- Laravel 9, 10, 11 or 12\n\n### Setup\n\n1. **Install the package:**\n   ```bash\n   composer require mchev/banhammer\n   ```\n\n2. **Publish and run migrations:**\n   ```bash\n   php artisan vendor:publish --provider=\"Mchev\\Banhammer\\BanhammerServiceProvider\" --tag=\"migrations\"\n   php artisan migrate\n   ```\n\n3. **Publish config (optional):**\n   ```bash\n   php artisan vendor:publish --provider=\"Mchev\\Banhammer\\BanhammerServiceProvider\" --tag=\"config\"\n   ```\n\n   \u003e 💡 The config file allows you to customize table name, model, fallback URLs, and more.\n\n---\n\n## 📖 Usage Guide\n\n### Banning Models\n\n#### Make a Model Bannable\n\nAdd the `Bannable` trait to any model:\n\n```php\nuse Mchev\\Banhammer\\Traits\\Bannable;\n\nclass User extends Model\n{\n    use Bannable;\n}\n```\n\n\u003e 💡 You can add the trait to multiple models (User, Team, Group, etc.)\n\n#### Basic Operations\n\n| Action | Code |\n|--------|------|\n| **Ban a user** | `$user-\u003eban()` |\n| **Ban with expiration** | `$user-\u003ebanUntil('2 days')` |\n| **Check if banned** | `$user-\u003eisBanned()` |\n| **Check if not banned** | `$user-\u003eisNotBanned()` |\n| **Unban** | `$user-\u003eunban()` |\n\n#### Advanced Ban Options\n\n```php\n$user-\u003eban([\n    'comment' =\u003e \"You've been evil\",\n    'ip' =\u003e \"8.8.8.8\",\n    'expired_at' =\u003e Carbon::now()-\u003eaddDays(7),\n    'created_by_type' =\u003e 'App\\Models\\Admin',\n    'created_by_id' =\u003e auth()-\u003eid(),\n    'metas' =\u003e [\n        'route' =\u003e request()-\u003eroute()-\u003egetName(),\n        'user_agent' =\u003e request()-\u003eheader('user-agent')\n    ]\n]);\n```\n\n\u003e ⚠️ Without `expired_at`, the ban is permanent.\n\n#### Query Scopes\n\n```php\n// Get banned users\n$bannedUsers = User::banned()-\u003eget();\n\n// Get non-banned users\n$activeUsers = User::notBanned()-\u003eget();\n\n// Alternative syntax\n$activeUsers = User::banned(false)-\u003eget();\n```\n\n#### List Bans\n\n```php\n// All bans for a model\n$bans = $user-\u003ebans()-\u003eget();\n\n// Only expired bans\n$expired = $user-\u003ebans()-\u003eexpired()-\u003eget();\n\n// Active bans\n$active = $user-\u003ebans()-\u003enotExpired()-\u003eget();\n```\n\n---\n\n### Banning IPs\n\n#### Basic Operations\n\n```php\nuse Mchev\\Banhammer\\IP;\n\n// Ban single IP\nIP::ban(\"8.8.8.8\");\n\n// Ban multiple IPs\nIP::ban([\"8.8.8.8\", \"4.4.4.4\", \"1.1.1.1\"]);\n\n// Ban with expiration\nIP::ban(\"8.8.8.8\", [], now()-\u003eaddMinutes(10));\n\n// Ban with metadata\nIP::ban(\"8.8.8.8\", [\n    'reason' =\u003e 'spam',\n    'severity' =\u003e 'high'\n]);\n```\n\n#### Unban IPs\n\n```php\n// Unban single IP\nIP::unban(\"8.8.8.8\");\n\n// Unban multiple IPs\nIP::unban([\"8.8.8.8\", \"4.4.4.4\"]);\n```\n\n#### Check \u0026 List Banned IPs\n\n```php\n// Check if IP is banned\nIP::isBanned(\"8.8.8.8\"); // bool\n\n// Get all banned IPs\n$ips = IP::banned()-\u003eget(); // Collection\n$ips = IP::banned()-\u003epluck('ip')-\u003etoArray(); // Array\n```\n\n---\n\n### Country Blocking\n\nBlock access from specific countries automatically.\n\n#### Configuration\n\n1. **Enable country blocking** in `config/ban.php`:\n   ```php\n   'block_by_country' =\u003e true,\n   ```\n\n2. **Specify blocked countries**:\n   ```php\n   'blocked_countries' =\u003e ['FR', 'ES', 'US'],\n   ```\n\nThat's it! The middleware will automatically block requests from these countries.\n\n\u003e ⚠️ **Rate Limit Notice:** The free version of ip-api.com has a limit of 45 requests/minute. Exceeding this will result in 429 errors until the limit resets.\n\n\u003e 💡 **Want to improve this?** If you have suggestions for better geolocation services or want to contribute improvements, please [open an issue](https://github.com/mchev/banhammer/issues) or submit a [pull request](https://github.com/mchev/banhammer/pulls).\n\n---\n\n### Middleware\n\nProtect your routes with ban middleware:\n\n#### Available Middleware\n\n| Middleware | Description |\n|-----------|-------------|\n| `auth.banned` | Blocks banned users |\n| `ip.banned` | Blocks banned IPs |\n| `logout.banned` | Logs out and blocks banned users/IPs |\n\n#### Usage\n\n```php\n// Single route\nRoute::get('/dashboard', [DashboardController::class, 'index'])\n    -\u003emiddleware('auth.banned');\n\n// Route group\nRoute::middleware(['auth.banned'])-\u003egroup(function () {\n    Route::get('/profile', [ProfileController::class, 'index']);\n    Route::get('/settings', [SettingsController::class, 'index']);\n});\n\n// Block IPs on all routes\n// Add to app/Http/Kernel.php:\nprotected $middleware = [\n    // ...\n    \\Mchev\\Banhammer\\Middleware\\IPBanned::class,\n];\n```\n\n\u003e 💡 **Tip:** `logout.banned` includes the functionality of both `auth.banned` and `ip.banned`, so you don't need to use them together.\n\n---\n\n### Scheduler\n\nBanhammer automatically deletes expired bans using Laravel's scheduler.\n\n#### Setup\n\n\u003e ⚠️ **Important:** You must have a cron job running Laravel's scheduler:\n\u003e ```bash\n\u003e * * * * * cd /path-to-your-project \u0026\u0026 php artisan schedule:run \u003e\u003e /dev/null 2\u003e\u00261\n\u003e ```\n\u003e \n\u003e See: [Laravel Scheduler Docs](https://laravel.com/docs/scheduling#running-the-scheduler)\n\n#### Configuration\n\nBy default, the `banhammer:unban` command runs **every minute**. You can customize this:\n\n**Disable automatic scheduler:**\n```php\n// config/ban.php\n'scheduler_enabled' =\u003e false,\n```\n\nOr via environment:\n```env\nBANHAMMER_SCHEDULER_ENABLED=false\n```\n\n**Change frequency:**\n```php\n// config/ban.php\n'scheduler_periodicity' =\u003e 'everyFiveMinutes', // or 'hourly', 'daily', etc.\n```\n\nOr via environment:\n```env\nBANHAMMER_SCHEDULER_PERIODICITY=everyFiveMinutes\n```\n\n**Available frequencies:** `everyMinute`, `everyFiveMinutes`, `everyTenMinutes`, `everyFifteenMinutes`, `everyThirtyMinutes`, `hourly`, `daily`, `twiceDaily`, etc.\n\n---\n\n### Events\n\nListen to ban/unban events:\n\n```php\nuse Mchev\\Banhammer\\Events\\ModelWasBanned;\nuse Mchev\\Banhammer\\Events\\ModelWasUnbanned;\n\nEvent::listen(ModelWasBanned::class, function ($event) {\n    // User was banned\n    Log::info(\"User {$event-\u003eban-\u003ebannable-\u003eid} was banned\");\n});\n\nEvent::listen(ModelWasUnbanned::class, function ($event) {\n    // User was unbanned\n    Log::info(\"User {$event-\u003eban-\u003ebannable-\u003eid} was unbanned\");\n});\n```\n\n---\n\n## 🔧 Advanced Topics\n\n### Metas\n\nStore additional data with bans:\n\n```php\n// Set meta\n$ban-\u003esetMeta('username', 'Jane');\n$ban-\u003esetMeta('reason', 'spam');\n\n// Get meta\n$ban-\u003egetMeta('username'); // 'Jane'\n\n// Check if meta exists\n$ban-\u003ehasMeta('username'); // true\n\n// Remove meta\n$ban-\u003eforgetMeta('username');\n```\n\n#### Filter by Meta\n\n```php\n// Find bans with specific meta\nIP::banned()-\u003ewhereMeta('username', 'Jane')-\u003eget();\n$user-\u003ebans()-\u003ewhereMeta('reason', 'spam')-\u003eget();\nUser::whereBansMeta('username', 'Jane')-\u003eget();\n```\n\n#### Ban with Metas\n\n```php\n// When banning\n$user-\u003eban([\n    'metas' =\u003e [\n        'route' =\u003e request()-\u003eroute()-\u003egetName(),\n        'user_agent' =\u003e request()-\u003eheader('user-agent')\n    ]\n]);\n\nIP::ban(\"8.8.8.8\", [\n    'reason' =\u003e 'spam',\n    'severity' =\u003e 'high'\n]);\n```\n\n---\n\n### UUIDs\n\nTo use UUIDs instead of auto-incrementing IDs:\n\n1. **Publish migrations:**\n   ```bash\n   php artisan vendor:publish --provider=\"Mchev\\Banhammer\\BanhammerServiceProvider\" --tag=\"migrations\"\n   ```\n\n2. **Edit the migration:**\n   ```diff\n   - $table-\u003eid();\n   + $table-\u003euuid('id');\n   ```\n\n3. **Create a custom Ban model:**\n   ```php\n   namespace App\\Models;\n   \n   use Illuminate\\Database\\Eloquent\\Concerns\\HasUuids;\n   use Mchev\\Banhammer\\Models\\Ban as BanhammerBan;\n   \n   class Ban extends BanhammerBan\n   {\n       use HasUuids;\n   }\n   ```\n\n4. **Update config:**\n   ```php\n   // config/ban.php\n   'model' =\u003e \\App\\Models\\Ban::class,\n   ```\n\n---\n\n### Upgrading To 2.0 from 1.x\n\n1. **Update composer.json:**\n   ```json\n   \"require\": {\n       \"mchev/banhammer\": \"^2.0\"\n   }\n   ```\n\n2. **Update the package:**\n   ```bash\n   composer update mchev/banhammer\n   ```\n\n3. **Update configuration:**\n   ```bash\n   # Backup your current config\n   cp config/ban.php config/ban.php.backup\n   \n   # Republish config\n   php artisan vendor:publish --provider=\"Mchev\\Banhammer\\BanhammerServiceProvider\" --tag=\"config\" --force\n   \n   # Review and merge any custom settings\n   ```\n\n---\n\n## 🛠️ Development\n\n### Commands\n\n```bash\n# Manually delete expired bans\nphp artisan banhammer:unban\n\n# Permanently delete all expired bans\nphp artisan banhammer:clear\n```\n\n### Programmatic Usage\n\n```php\nuse Mchev\\Banhammer\\Banhammer;\n\n// Delete expired bans\nBanhammer::unbanExpired();\n\n// Permanently delete expired bans\nBanhammer::clear();\n```\n\n### Testing\n\n```bash\ncomposer test\n```\n\n---\n\n## 🤝 Contributing\n\nWe welcome contributions! Please:\n\n- Open issues for bug reports or feature requests\n- Submit pull requests (mark as \"ready for review\")\n- Ensure all tests pass\n- Follow Laravel coding standards\n\n\u003e 💡 Pull requests in \"draft\" state will be closed after a few days of inactivity.\n\n---\n\n## 🙏 Credits\n\nInspired by [laravel-ban](https://github.com/cybercog/laravel-ban) from [cybercog](https://github.com/cybercog).\n\n---\n\n## 📄 License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmchev%2Fbanhammer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmchev%2Fbanhammer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmchev%2Fbanhammer/lists"}