christhompsontldr/laravel-restricted
Laravel package to restrict access by route, IP, environment or custom rules. Adds simple middleware and configuration to block or allow requests with clear responses—useful for staging locks, admin-only areas, and temporary maintenance restrictions.
Installation:
composer require christhompsontldr/laravel-restricted
Publish the config file:
php artisan vendor:publish --provider="ChrisThompsonTLDR\Restricted\RestrictedServiceProvider"
Configuration:
Edit config/restricted.php to define:
restricted_routes: Routes that should be restricted (e.g., ['/admin/*']).restricted_middleware: Middleware to apply when restricted (e.g., ['restricted']).restricted_guard: Auth guard to use (e.g., web).First Use Case: Toggle restricted mode for a user via:
// Enable restricted mode
Auth::user()->restricted = true;
Auth::user()->save();
// Disable restricted mode
Auth::user()->restricted = false;
Auth::user()->save();
Middleware:
Register the RestrictedMiddleware in app/Http/Kernel.php:
protected $routeMiddleware = [
'restricted' => \ChrisThompsonTLDR\Restricted\Middleware\RestrictedMiddleware::class,
];
Route Protection: Apply the middleware to routes:
Route::middleware(['auth', 'restricted'])->group(function () {
Route::get('/admin', 'AdminController@index');
});
User Restriction Workflow:
if (Auth::user()->isRestricted()) {
// Redirect or show limited UI
}
public function toggleRestrictedStatus(User $user) {
$user->restricted = !$user->restricted;
$user->save();
}
if (!Auth::user()->isRestricted()) {
// Full functionality
} else {
// Limited functionality (e.g., read-only mode)
}
Route-Level Restrictions:
restricted middleware to block access to sensitive routes:
Route::middleware(['auth', 'restricted'])->group(function () {
Route::get('/dashboard', 'DashboardController@index');
});
config/restricted.php:
'restricted_routes' => [
'admin/*',
'settings/*',
'api/admin/*',
],
API Integration:
RestrictedMiddleware to handle API responses:
public function handle($request, Closure $next) {
if (Auth::guard($this->guard)->user()->isRestricted()) {
return response()->json(['error' => 'Restricted access'], 403);
}
return $next($request);
}
View-Based Restrictions:
@if(!Auth::user()->isRestricted())
<button class="delete-btn">Delete</button>
@endif
Blade::directive('restricted', function ($expression) {
return "<?php if(!Auth::user()->isRestricted()): ?>";
});
@restricted
<button>Full Feature</button>
@endrestricted
Event-Based Triggers:
Auth::user()->restricted = true;
Auth::user()->save();
event(new UserRestricted(Auth::user()));
EventServiceProvider:
protected $listen = [
'ChrisThompsonTLDR\Restricted\Events\UserRestricted' => [
'App\Listeners\LogRestrictedAccess',
],
];
Middleware Order Matters:
restricted middleware after auth in Kernel.php to avoid bypassing auth checks:
$middlewareGroups['web'] = [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// ... other middleware
\App\Http\Middleware\Authenticate::class, // Auth first
\ChrisThompsonTLDR\Restricted\Middleware\RestrictedMiddleware::class, // Then restricted
];
Database Column Requirement:
users table must have a restricted column (boolean). Add it via migration if missing:
Schema::table('users', function (Blueprint $table) {
$table->boolean('restricted')->default(false);
});
Caching Issues:
Auth::user()->restricted = true;
Auth::user()->save();
Cache::forget('user.' . Auth::id());
Route Caching:
restricted_routes in config, clear route cache:
php artisan route:clear
Guard-Specific Logic:
web guard. For custom guards (e.g., api), specify it in the middleware:
public function __construct() {
$this->guard = 'api'; // Override default
}
Check Restricted Status:
User model:
public function isRestricted() {
return $this->restricted ?? false;
}
Log Restricted Access:
public function handle($request, Closure $next) {
if (Auth::guard($this->guard)->check() && Auth::guard($this->guard)->user()->isRestricted()) {
\Log::warning('Restricted access attempt by ' . Auth::id());
return redirect()->route('home')->with('error', 'Access restricted');
}
return $next($request);
}
Test Middleware:
middleware helper in tests:
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $this->token,
])->withMiddleware(\ChrisThompsonTLDR\Restricted\Middleware\RestrictedMiddleware::class)
->get('/admin');
Config Overrides:
$this->app->override('restricted', [
'restricted_routes' => ['/test'],
]);
Custom Restricted Logic:
RestrictedMiddleware to add custom logic:
public function handle($request, Closure $next) {
if (Auth::user()->isRestricted()) {
if ($request->is('critical/*')) {
abort(403, 'Critical routes are blocked in restricted mode.');
}
}
return $next($request);
}
Add Restricted Mode UI:
trait HandlesRestrictedMode {
public function checkRestrictedMode() {
if (Auth::user()->isRestricted()) {
return redirect()->route('restricted.dashboard');
}
}
}
API Rate Limiting:
throttle middleware:
Route::middleware(['throttle:60,1', 'restricted'])->post('/api/sensitive', ...);
Dynamic Route Restrictions:
public function boot() {
$restrictedRoutes = config('restricted.dynamic_routes', []);
config(['restricted.restricted_routes' => array_merge(
config('restricted.restricted_routes'),
$restrictedRoutes
)]);
}
Event-Driven Notifications:
Auth::user()->restricted = true;
Auth::user()->save();
event(new UserRestricted(Auth::user()));
public function handle(UserRestricted $event) {
Notification::route('mail', $event->user->email)
->notify(new RestrictedModeNotification());
}
How can I help you explore Laravel packages today?