Laravel - combining routes by user type - php

I have a web app with 2 users types: admins and customers. In my users table I have a boolean column named "is_admin". When admins login, they should have access to one set of resources; when users login, they should have access to another set of resources.
I have a feeling I need to use either middleware or policies, but cannot find any good examples online.
Any help would be much appreciated.
This is the code from my web.php routes file
Auth::routes();
Route::group(['middleware' => ['auth']], function () {
Route::get('/', 'DashboardController#index')->name('dashboard');
Route::resource('stock-types', 'StockTypeController');
Route::resource('stock-items', 'StockItemController');
Route::resource('companies', 'CompanyController');
Route::resource('addresses', 'AddressController');
Route::resource('contacts', 'ContactController');
Route::resource('deliveries', 'DeliveryController');
Route::resource('settings', 'SettingController', ['only' => [
'index', 'update',
]]);
Route::resource('users', 'UserController');
});

This in an example for admin check
https://laracasts.com/discuss/channels/general-discussion/create-middleware-to-auth-admin-users?page=1

Related

Load backend and frontend routes separately without interfering

I have two kind of routes, admin routes and frontend routes.
The frontend routes
Route::get('{locale?}/', ['uses' => '\App\Http\Controllers\loadViewController#home']);
Route::get('{locale?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#index']);
Route::get('{locale?}/{template?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#detail']);
The backend routes
Route::prefix('admin/dashboard')->group(function () {
Route::get('/', 'DashboardController#index')->name('dashboard');
});
Now when i type admin/dashboard or api/admin, laravel uses the frontend routes to load the views, while i want the backend views to be loaded.
So to filter out the backend routes i tried this
Route::group(['where' => ['page' => '^(?!admin|api)$', 'template' => '^(?!admin|api)$']], function ({
Route::get('{locale?}/', ['uses' => '\App\Http\Controllers\loadViewController#home']);
Route::get('{locale?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#index']);
Route::get('{locale?}/{template?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#detail']);
});
which obviously did not work
Also the frontend routes should not have something like /website, they should all start with /
My question is: How can i load the backend and frontend routes separately without interfering when called, even if they have the same url length in terms of parameters, keep in mind that the admin routes always start with /admin or /api.
Note: i can't put the backend routes before the frontend routes
Thanks in advance!
If you want to you could put a constraint on the locale route parameter:
Route::pattern('locale', '^(?!(api|admin)$)(\w*)');
You can put this in the boot method of you RouteServiceProvider and it will now not allow the locale route parameter to match for 'api' or 'admin'.
You can register seperate routes in RouteServiceProvider. Following is how you can do it.
Inside RouteServiceProvider.php do:
public function map()
{
$this->mapFrontendRoutes();
$this->mapAdminRoutes();
}
Definition of mapFrontendRoutes():
protected function mapFrontendRoutes()
{
Route::prefix('{locales?}')
->middleware('frontend')
->namespace($this->namespace.'\Frontend')
->group(base_path('routes/frontend.php'));
}
Definition of mapAdminRoutes():
protected function mapAdminRoutes()
{
Route::prefix('admin')
->middleware('admin')
->namespace($this->namespace.'\Admin')
->group(base_path('routes/admin.php'));
}
I personally find this very useful, helps to declare interference free and logical routes. Open to feedback.
The simple way is to group both url's as separate groups. Example as follows :
Route::group(['prefix' => 'admin', 'as' => 'admin'], function () {
Route::post('/dashboard', 'AdminController#dashboard');
});
Route::group(['prefix' => 'home', 'as' => 'home'], function () {
Route::get('/record/{id}', 'HomeController#getRecord');
});

Auth or auth-api middleware in api routes in laravel

For apis auth I am currently using:
Route::group([
'middleware' => 'auth:api'
], function() {
Route::post('logout', 'AuthController#logout');
Route::get('user', 'AuthController#user');
});
If I want to use same for session based logins do I need to create same routes in web.php file or can I set up middleware in AuthController constructor with something like this or this?
In this answer 'auth:api' means auth is checking for api so do I need to pass anything there to check for sessions like 'auth:api,web' or what?
Create same routes in web.php just ommit the middleware, as web middleware is applied automatically. Same goes for api.php, auth:api is default middleware there.

Which middleware to use if I want the route to be accessible by guests, authenticated users and everyone else?

At first I decided to organize my routes like I have in the code given below. However, I quickly realized that I couldn't access the routes in the group that uses middleware guest as soon as I log in. Does that mean that routes which I want to be accessible by anyone no matter whether they're logged in or not should not be in any middleware group?
<?php
Route::group(['middleware' => ['web']], function(){
Route::group(['middleware' => ['guest']], function(){
Route::get('/', 'PagesController#index')->name('home');
Route::get('/image/{id}', 'PagesController#specificImage')->name('specificImage');
Route::get('/contact', 'PagesController#contact')->name('contact');
Route::get('/tags', 'PagesController#tags')->name('tags');
Route::get('/tags/{tagName}', 'PagesController#specificTag')->name('specificTag');
Route::get('/albums', 'PagesController#albums')->name('albums');
Route::get('/albums/{albumId}/{albumName}', 'PagesController#specificAlbum')->name('specificAlbum');
Route::post('/signup', 'UsersController#signUp')->name('signup');
Route::post('/signin', 'UsersController#signIn')->name('signin');
Route::post('/sendmail', 'UsersController#sendMail')->name('sendmail');
});
Route::group(['middleware' => ['auth']], function(){
Route::get('/upload', 'PagesController#upload')->name('upload');
Route::get('/logout', 'UsersController#logOut')->name('logout');
Route::get('/imageDelete/{imageId}', 'ImagesController#deleteImage')->name('deleteImage');
Route::get('/deleteTag/{tagId}', 'TagsController#deleteTag')->name('deleteTag');
Route::post('/imageUpload', 'ImagesController#uploadImage')->name('imageUpload');
Route::post('/albumUpload', 'AlbumsController#uploadAlbum')->name('albumUpload');
Route::post('/createTag', 'TagsController#createTag')->name('createTag');
});
});
Remove auth middleware from the route group
Correct! Get rid of the guest middleware, you don't need it.
Just Do not use any middleware.

Laravel 5 deny route for non auth users

I have this Laravel 5 app. There are two controllers: Index and Home.
In the index, I have the pages visible for users that haven't logged in yet. When a user logs in, he goes to the home controller.
Of course, I want a visitor not being able to view the routes under home-controller.
So I put a check inside the constructor for Home. But it redirects back to the index and doesn't seem to be the right way at all.
So having this group of routes:
Route::group(['prefix' => '/home'], function () {
Route::auth();
Route::get('index', 'HomeController#index');
Route::get('logout', 'HomeController#logout');
});
As you can see, I added.
Route::auth();
Which I thought should manage to deny access for visitors that haven't logged in. The home is still accessible for users that haven't logged in yet.
What is the way to describe directly inside the route.php that a bunch of routes (inside a group I guess) should first go through the authentication before serving the route?
Are you using this code within your controller?
public function __construct()
{
$this->middleware('auth');
}
You should add a auth middleware to protect your home group:
Route::auth();
Route::group(['middleware' => 'auth'], function() {
Route::group(['prefix' => '/home'], function () {
Route::get('index', 'HomeController#index');
Route::get('logout', 'HomeController#logout');
});
});
You may have a look at this: https://laravel.com/docs/5.2/authentication#protecting-routes
Its really simple in Laravel only thing you have to use is a single Middleware
see this DOC
EX:
Route::get('profile', ['middleware' => 'auth', 'uses' => 'ProfileController#show']);
this profile show route works only if user logged in.
If you have multiple routes to protect from non-authenticate users then use a route group,
Route::group(['prefix' => '/home', 'middleware' => ['auth']], function()
{
// user need to logged in order to access these routes
Route::get('/', function()
{
});
});
In kernal.php add 'auth' => 'MyespaceAdmin\Http\Middleware\Authenticate' in $routeMiddleware.
Authenticate.php in middleware directory check handle function for below code.
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('your login page url');
}
}
Then use middleware auth in routes or in your controller

Laravel Routing - Separate some routes

I have a route defined as:
Route::resource('item', 'ItemController');
What I want to do is put some of these routes, particularly edit and delete inside a group.
Route::group(['middleware' => ['role']], function() {
Route::resource('item', 'ItemController', ['only' => ['edit', 'delete']]);
}
This doesn't work, though. Do I have to define each route one by one then? Or is there a better solution to this?
EDIT:
I'm sorry, but it seems I did not ask the question properly. So let me make some clarifications here.
I have a basic auth user which can create and view items. What I don't want it to do is edit and delete.
I then also have a role user which do everything auth can do AND edit and delete items.
So basically, regular authorized users can have SOME access to items while role users have COMPLETE access.
The current code seems to give role users ONLY edit and delete functionalities and no view or create.
To make it even more clearer, here's what my actual route looks like:
Route::group(['middleware' => ['auth']], function()
{
Route::resource('items', 'SitesController');
Route::group(['middleware' => ['role']], function() {
Route::resource('item', 'ItemController', ['only' => ['edit', 'delete']]);
});
});
Maybe I'm going about this the wrong way?
The code above will work, you just named the action incorrectly. You should have used destroy instead of delete. Try the following code:
Route::resource('item', 'ItemController');
Route::group(['middleware' => ['role']], function() {
Route::resource('item', 'ItemController', ['only' => ['edit', 'destroy']]);
});
You can run php artisan route:list to verify. You should see role middleware enabled in 2 of your routes.

Categories