Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
This Laravel jQuery POS role management tutorial covers how to implement user roles to restrict access and protect key features.
In a real-world POS environment, different users should have different access levels. For example, an Admin should be able to manage users, products, and reports, while a Cashier should only access the cart and make transactions.
In this post, you’ll learn how to:
By the end of this guide, your Laravel POS with jQuery app will have a secure and organized user permission system.
php artisan make:middleware RoleMiddleware
Then update the middleware app/Http/Middleware/RoleMiddleware.php:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class RoleMiddleware
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next, ...$roles): Response
{
$user = $request->user();
if (!$user || !in_array($user->role, $roles)) {
return match ($user->role) {
'superadmin' => redirect('/'),
'admin' => redirect('/'),
'cashier' => redirect('/cashier'),
default => abort(403),
};
}
return $next($request);
}
}
Register it in bootstrap/app.php:
use App\Http\Middleware\RoleMiddleware;
// ...
->withMiddleware(function (Middleware $middleware): void {
$middleware->alias([
'role' => RoleMiddleware::class
]);
})
If you’re new to middleware or want a deeper understanding of how it works in Laravel, check out the official Laravel documentation:
🔗 Laravel Middleware Documentation
This guide provides in-depth details on how middleware handles request filtering and route protection in Laravel applications.
Apply the middleware to routes you want to protect:
Replace the contents of routes/web.php with the code below.
<?php
// Laravel POS With jQuery @ https://laravelcenter.com
use App\Http\Controllers\BalanceAdjustmentController;
use App\Http\Controllers\CashierController;
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\ProductCategoryController;
use App\Http\Controllers\ProductController;
use App\Http\Controllers\TableController;
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;
Route::middleware('guest')->match(['get', 'post'], '/login', [UserController::class, 'login'])->name('login');
Route::middleware('auth')->group(function () {
Route::post('/user/logout', [UserController::class, 'logout']);
Route::match(['get', 'post'], '/user/change-password', [UserController::class, 'changePassword']);
Route::middleware('role:superadmin,admin')->group(function () {
Route::view('/', 'layout.admin');
Route::get('dashboard', DashboardController::class);
Route::prefix('user')->controller(UserController::class)->group(function () {
Route::get('/', 'index');
Route::get('form/{id?}', 'form');
Route::match(['post', 'put'], 'submit', 'submit');
Route::delete('delete', 'delete');
});
// Table
Route::prefix('table')->controller(TableController::class)->group(function () {
Route::get('/', 'index');
Route::get('form/{id?}', 'form');
Route::match(['post', 'put'], 'submit', 'submit');
Route::delete('delete', 'delete');
});
// Product
Route::prefix('product')->controller(ProductController::class)->group(function () {
Route::get('/', 'index');
Route::get('form/{id?}', 'form');
Route::match(['post', 'put'], 'submit', 'submit');
Route::delete('delete', 'delete');
});
// Product Category
Route::prefix('product-category')->controller(ProductCategoryController::class)->group(function () {
Route::get('/', 'index');
Route::get('form/{id?}', 'form');
Route::match(['post', 'put'], 'submit', 'submit');
Route::delete('delete', 'delete');
});
// Balance Adjustment
Route::prefix('balance-adjustment')->controller(BalanceAdjustmentController::class)->group(function () {
Route::get('/', 'index');
Route::get('form/{id?}', 'form');
Route::match(['post', 'put'], 'submit', 'submit');
Route::delete('delete', 'delete');
});
});
Route::middleware('role:cashier')->prefix('cashier')->controller(CashierController::class)->group(function () {
// Cashier
Route::get('/', 'index');
Route::get('product/{category}', 'product');
Route::get('table/{id}', 'table');
Route::post('select-table', 'selectTable');
Route::post('update-order-qty', 'updateOrderQty');
Route::post('update-detail-discount', 'updateDetailDiscount');
Route::delete('delete-order-product', 'deleteOrderProduct');
Route::post('update-discount', 'updateDiscount');
Route::post('add-to-order', 'addToOrder');
Route::post('print-invoice', 'printInvoice');
Route::match(['post', 'get'], 'make-payment', 'makePayment');
});
});
Route::fallback(function () {
return view('404');
});
Now, only admins can access admin routes and only cashiers can access POS routes.
Run the following command to compile your assets:
npm run dev
Use <strong>npm run build</strong>
for production.
Once compiled, visit:
http://laravel-jquery-pos
To verify that your role-based route protection is working correctly in your Laravel POS with jQuery project, follow this simple test:
cashier
).✅ This test ensures your middleware is correctly blocking unauthorized users from accessing restricted areas.
Awesome job! 🎉 You’ve now implemented role-based access control in your Laravel POS with jQuery system—giving you full control over what Admins and Cashiers can see and do. With roles, middleware, and conditional UI in place, your POS app is now more secure, structured, and production-ready.
In the next tutorial, we’ll move on to generating powerful reports and filtering sales data by date, user, or status. This will help admins monitor business performance and analyze key metrics directly from the dashboard.
👉 Continue to Part 7: Generate Reports and Filter Sales Data