Laravel add custom middleware to route group - laravel

in my web application i have admin panel and i'm trying to make access to users that they have admin role by this code:
namespace App\Http\Middleware;
use Closure;
class CheckUserAdminRole
{
public function handle($request, Closure $next)
{
if (auth()->check()) {
if (auth()->check() && !auth()->user()->hasRole('admin')) {
auth()->logout();
return redirect(route('system.messages','userIsNotAdmin'));
}
}
return $next($request);
}
}
and in my routs i have this route group:
Route::group(['namespace' => 'Dashboard', 'middleware' => ['auth:web'], 'prefix' => 'dashboard'], function () {
$this->group(['prefix' => 'administrator'], function () {
$this->get('panel', 'AdminController#index');
});
my kernel:
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
...
\App\Http\Middleware\CheckUserAdminRole::class,
];
now when i add my middleware as CheckUserAdminRole to route group like with this code:
Route::group(['namespace' => 'Dashboard', 'middleware' => ['auth:web','CheckUserAdminRole'], 'prefix' => 'dashboard'], function () {
i get this error:
Class CheckUserAdminRole does not exist
this codes couldn't resolve my problem:
php artisan route:clear
php artisan cache:clear
php artisan config:clear
composer dump-autoload

Instead of registering your middleware in the $middleware array, you should register it in $routeMiddleware like so:
protected $routeMiddleware = [
...
'checkAdmin' => \App\Http\Middleware\CheckUserAdminRole::class,
];
Note: registering a middlware in the $middleware array results in it being executed for every request and therefore is not applicable on specific routes.
Then you can use it in your routes with the checkAdmin name:
Route::group(['namespace' => 'Dashboard', 'middleware' => ['auth:web','checkAdmin'], 'prefix' => 'dashboard'], function () {
Source

You can also use middleware and route group together easily like so:
Route::group(['prefix' => 'admin', 'middleware' => 'auth'], function()
{
//All the routes that belongs to the group goes here
Route::get('dashboard', function() {} );
});

Here's a simple fix without touching the Kernel file and taking advantage of the Policy. The accessAdmin is a function created inside Policy file.
Route::group(['namespace' => 'Dashboard', 'middleware' => 'can:accessAdmin, App\User', 'prefix' => 'dashboard'], function () {
$this->group(['prefix' => 'administrator'], function () {
$this->get('panel', 'AdminController#index');
});

You can try middleware with prefix and groups.
Route::middleware(['Auth'])->prefix('api/')->group(function() {
Route::group(['prefix' => 'review/'], function () {
Route::get('/', 'User\Controllers\Api\UserController#getUserReviews');
});
});
Hope its helps

Related

How to Handle domain and sub-domain in Route using Laravel MiddleWare

In my Laravel-5.8 application, I have a multi-company application using a single database. Each table have a company_id derived from the company table as shown below:
id | company_name | subdomain
1 | Main |
2 | Company1 | company1
3 | Company2 | company2
Main=> localhost:8888/myapp
Company1=>localhost:8888/company1.myapp
Company2=>localhost:8888/company2.myapp
I created a middleware:
class VerifyDomain
{
public function handle($request, Closure $next)
{
$domain == "myapp"; // your company app name
$path = $request->getPathInfo(); // should return /company1.myapp or /company2.myapp or /myapp
if (strpos($path, ".") !== false) { // if path has dot.
list($subdomain, $main) = explode('.', $path);
if(strcmp($domain, $main) !== 0){
abort(404); // if domain is not myapp then throw 404 page error
}
} else{
if(strcmp($domain, $path) !== 0){
abort(404); // if domain is not myapp then throw 404 page error
}
$subdomain = ""; // considering for main domain value is empty string.
}
$company = Company::where('subdomain', $subdomain)->firstOrFail(); // if not found then will throw 404
$request->session()->put('subdomain', $company); //store it in session
return $next($request);
}
}
Already, I have two (2) route groups in the route/web.php wgich looks like this:
Route::get('/', ['as' => '/', 'uses' => 'IndexController#getLogin']);
Auth::routes();
Route::get('/dashboard', 'HomeController#index')->name('dashboard');
// Config Module
Route::group(['prefix' => 'config', 'as' => 'config.', 'namespace' => 'Config', 'middleware' => ['auth']], function () {
Route::resource('countries', 'ConfigCountriesController');
Route::resource('nationalities', 'ConfigNationalitiesController');
});
// HR Module
Route::group(['prefix' => 'hr', 'as' => 'hr.', 'namespace' => 'Hr', 'middleware' => ['auth']], function () {
Route::resource('designations', 'HrDesignationsController');
Route::resource('departments', 'HrDepartmentsController');
Route::resource('employee_categories', 'HrEmployeeCategoriesController');
});
I have 2 issues:
If subdomain field is null, then the route should be for main domain: Main=> localhost:8888/myapp else localhost:8888/company1.myapp or localhost:8888/company2.myapp
2.How do I accomodate the route groups above into this:
Route::domain('localhost:8888/myapp')->group(function () {
Route::get('/', function ($id) {
//
});
});
Route::domain('localhost:8888/{subdomain}.myapp')->group(function () {
Route::get('/', function ($company_name, $id) {
$company = Company::where('subdomain', $subdomain)->firstOrFail();
// send the value of $company to data to send different view data
});
});
I'm not really sure that i understand you clearly. But, I hope you'll understand me :)
First thing is you're "domain". I suppose it's not real domain, but just uri. And maybe you should use it something like that:
Auth::routes();
$defaultDomain = config('myconfig.default_domain_name', 'myapp');
// I'm not reccomend to you use localhost:8888 here.
Route::domain('localhost:8888')
->group([
'middleware' => ['veryfy_domain'] // Add your VerifyDomain Middleware here
], function () {
// Here you already have a 'subdomain' param in session
// If you need special logic for default domain, you can out it here
Route::group(['prefix' => '/' . $defaultDomain], function () {
Route::get('/', function ($id) {
//
});
});
// Code below will work only with companies.
Route::group(['prefix' => '/{test}.' . $defaultDomain], function () {
Route::get('/', ['as' => '/', 'uses' => 'IndexController#getLogin']);
Route::get('/dashboard', 'HomeController#index')->name('dashboard');
// Config Module
Route::group(['prefix' => 'config', 'as' => 'config.', 'namespace' => 'Config', 'middleware' => ['auth']], function () {
Route::resource('countries', 'ConfigCountriesController');
Route::resource('nationalities', 'ConfigNationalitiesController');
});
// HR Module
Route::group(['prefix' => 'hr', 'as' => 'hr.', 'namespace' => 'Hr', 'middleware' => ['auth']], function () {
Route::resource('designations', 'HrDesignationsController');
Route::resource('departments', 'HrDepartmentsController');
Route::resource('employee_categories', 'HrEmployeeCategoriesController');
});
});
});
And about your middleware. I see it smth like that:
class VerifyDomain
{
public function handle($request, Closure $next)
{
$request->get('domain_name', $this->getBaseDomain());
$company = Company::where('subdomain', $subdomain)->firstOrFail();
$request->session()->put('subdomain', $company);
return $next($request);
}
// Better to store it in config
protected function getBaseDomain()
{
return config('myconfig.default_domain_name', 'myapp');
}
}
If you really want to use different domains, I think you need in your nginx something like this:
server_name *.myapp myapp;
And of course in your hosts file.
Than you can check it like that:
http://company.myapp
http://company1.myapp
http://myapp
Config example:
Create new file your_project_dir/app/config/myconfig.php (name it as you want)
Put this code in the file:
return [
'default_domain_name' => 'myapp'
];
Now you can use in in youre code as i suggest:
config('myconfig.default_domain_name');

How to call ApiResource with middleware in my routes?

When I use middleware like below, no problem:
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
But if I try to use it with apiResources, like below:
Route::apiResources([
'user' => 'API\UserController',
'posts' => 'API\PostController'
])->middleware('auth:api');
Then I get an error message:
php artisan route:list
BadMethodCallException
Method Illuminate\Routing\RouteRegistrar::apiResources does not
exist.
What is the correct way to call ApiResource with middleware in routes/api.php ?
I don't believe you can add any middleware's to the apiResources, what you could do instead is nest them inside a route group that applies them
Route::group(['middleware' => 'auth:api'], function () {
Route::apiResources([
'user' => 'API\UserController',
'posts' => 'API\PostController'
]);
});
This would also allow you to shorten the controller definitions with the namespace option:
Route::group(['middleware' => 'auth:api', 'namespace' => 'API'], function () {
Route::apiResources([
'user' => 'UserController',
'posts' => 'PostController'
]);
});

Default controller key

I have a laravel route like below :
Route::group(['namespace' => 'Aggregate\Customer\Controller\v1_0','middleware' => 'jwt.auth', 'prefix' => 'api/v1.0/{lang}'], function () {
Route::put('customer/{id}', 'CustomerController#update_customer');
});
And i want to lang key on route 'prefix' => 'api/v1.0/{lang}' be first variable globally in all methods and in all controllers without manual added in all methods like :
See $lang
public function add_address_book($lang,$user_id,AddressBookRequest $request)
{
How can i do that?
One option is update the config var app.locale.
Route::group([
'namespace' => 'Aggregate\Customer\Controller\v1_0',
'middleware' => 'jwt.auth',
'prefix' => 'api/v1.0/{lang}'
], function () {
App::setLocale(app('request')->segment(3));
Route::put('customer/{id}', 'CustomerController#update_customer');
});
Then use
echo App::getLocale();
You can set the default locale and the fallback locale in app/config.php
Another option is to set up a singleton in the app container
Route::group([
'namespace' => 'Aggregate\Customer\Controller\v1_0',
'middleware' => 'jwt.auth',
'prefix' => 'api/v1.0/{lang}'
], function () {
app()->singleton('lang', function () {
return app('request')->segment(3);
});
Route::put('customer/{id}', 'CustomerController#update_customer');
});
Then in your controllers (or anywhere) you can use
echo app('lang');

Remove web middleware in laravel 5.2

I know web middleware group is assigned to every route now. But can someone tell me how to remove if for specefic route? I tried:
class HomeController extends Controller{
public function __construct(){
$this->middleware('web',['except'=>[
'index',
]]);
}
}
And it doesn't work.
Web middleware is now applied to all routes in routes.php. This happens in the RouteServiceProvider map function.
If you have an api for example which should not use web middleware you can go with something like this
public function map(Router $router)
{
$this->mapWebRoutes($router);
$this->mapApiRoutes($router);
}
protected function mapWebRoutes(Router $router)
{
$router->group([
'namespace' => $this->namespace, 'middleware' => 'web',
], function ($router) {
require app_path('Http/routes.php');
});
}
protected function mapApiRoutes(Router $router)
{
$router->group([
'namespace' => $this->namespace, 'middleware' => 'api',
], function ($router) {
require app_path('Http/routes-api.php');
});
}
Now every route in routes.php has web middleware and everything in routes-api.php the api middleware

Laravel always takes me to login page

I'm using Laravel 5's auth module for my app. However after I created the auth functions with php artisan make:auth I can only access two paths:/login and /register no matter how I add routes in the routes.php. All other paths redirect me to the login page. How can I enable users to access certain paths without logging? Thanks.
routes.php:
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::auth();
Route::get('/home', 'HomeController#index');
Route::get('/patient', 'HomeController#registerPatient');
Route::get('test', 'HomeController#index');
Route::group(array('before' =>'auth'), function()
{
Route::get('about', array('as' => 'about','uses' => 'HomeController#about'));
}
);
Route::group(array('before' =>'auth'), function()
{
Route::get('/physician', array('as' => 'physician','uses' => 'HomeController#registerPhysician'));
}
);
Can you share your controller code? i mean do you have the auth middleware in ur controller construct?
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::get('/', function () {
return view('welcome');
});
Route::get('/home', 'HomeController#index');
Route::get('/patient', 'HomeController#registerPatient');
Route::get('test', 'HomeController#index');
});
Route::group(array('before' =>'auth'), function()
{
Route::get('/physician', array('as' => 'physician','uses' => 'HomeController#registerPhysician'));
Route::get('about', array('as' => 'about','uses' => 'HomeController#about'));
}
);
anyway check ur construct method in the homecontrollerand apply the auth middlewere only to certain methods
exemple
public function __construct()
{
$this->middleware('auth', ['except' => [
'about',
'index',
]]);
}
}

Resources