I'm starting my first Laravel project (first MVC / OOPHP project infact) and could use some help with routes.
I followed the guide at https://medium.com/employbl/easily-build-administrator-login-into-a-laravel-5-app-8a942e4fef37 to add a check if user is admin when loading a page. It works for normal view routes, e.g.
Route::get('/admin/something', 'AdminController#admin_something')
->middleware('is_admin')
->name('admin');
But I now have a resource route and get an error when I add the two -> lines to the route. So this works with no auth:
Route::resource('thingies', 'ThingyController');
But with this:
Route::resource('thingies', 'ThingyController')
->middleware('is_admin')
->name('admin');
I get the error Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_RECOVERABLE_ERROR)
Too few arguments to function Illuminate\Routing\PendingResourceRegistration::name(), 1 passed in /var/www/routes/web.php on line 24 and exactly 2 expected
What do I need to do differently to add this auth to a resource route?
The is_admin() function from the tutorial:
const ADMIN_TYPE = 'admin';
const DEFAULT_TYPE = 'default';
public function isAdmin() {
return $this->type === self::ADMIN_TYPE;
}
And the middleware:
namespace App\Http\Middleware;
use Closure;
class IsAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(auth()->user()->isAdmin()) {
return $next($request);
}
return redirect('home');
}
}
You can't name your route "admin" with ->name('admin'); at the end of your resource route because it concerns all CRUD routes in one statement and Laravel build-in system has already named them.
You're on the good way, just delete the last line like so, it should works :
Route::resource('thingies', 'ThingyController')
->middleware('is_admin');
You cannot give a 'name' to a resource route. but you can give names to each method in the resource controller separately.
to do so name() function required 2 parameters.
method name
name for that method route.
,
Route::resource('thingies', 'ThingyController')
->middleware('is_admin')
->name('create', 'admin.create');
Related
I am trying to get the source of the url that does the request POST/GET to a route. For example:
Route::post('/do-something', somethingController#getWhoRequesting);
Then as example, on the view I do ajax or a simple form post to that route, which is from localhost:8888/my-web-view. How do I get the url of who is requesting to my /do-something endpoint? I expect on getWhoRequesting(), but I get the '/my-web-view'.
Thanks in advance
You can get full url from requestin controller using request
request()->fullUrl(); or $request->fullUrl();
Updates:
If you want to capture all request then you can create middleware and assign it to all routes
php artisan make:middleware RequestCapture
then file will be look like this
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class RequestCapture
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
//here you can capture all $request for assigned middleware routes
return $next($request);
}
}
Also register this middleware in kernal.php in protected $routeMiddleware
'requestCapture' => \App\Http\Middleware\RequestCapture::class,
then you can assign to routegroup
Route::group(['middleware' => 'requestCapture'], function () {
});
You could use path method of Laravel. The path method returns the request's path information. So, if the incoming request is targeted at http://example.com/foo/bar, the path method will return foo/bar:
$uri = $request->path();
I hope it is something you are looking for ??
I am trying to implement a user registration system in Laravel 5.7 where I am facing an issue.
I have two tables for Users- Admin(created by copying default Laravel auth),
new routes, new middleware for admin. Every thing works fine while using guards.
I was trying to limit the user login by adding Approve/Disapprove functionality.
I added an extra column - admin(boolean) to the Users table.
In Login controller - LoginController.php Page, I added
protected function authenticated($request, $user)
{
if ( $request->user()->admin != 1)
// if($user->admin != 1)
{
return redirect()->route('approval');
}
else
{
return redirect('/engineer');
}
}
so that, when the admin is 1 I am directed to '/engineer' where as in other case I am directed to 'approval'.
It works as desired!.
Issue I am now facing is that if I try to access the 'engineer'
using user whose not approved I am able to access the page. I am not sure how to restrict it. The page is still restricted to public.
Since the controller will be accessed by both the user and admin, I used __construct in the controller
web.php
Route::resource('engineer', 'engineerController');
engineerController.php
public function __construct()
{
$this->middleware('auth:web,admin');
}
My Understanding is that the condition is only checked when the user logs in and there after its exits.
Do I need to create a new middle ware in order to keep the authorised page intact?
I am a self learner and new to laravel. I am pretty sure that I am not following the right practice. I started something and was trying to follow it till I finish. Please guide me through it.
Along with it please let me how could I have done it better.
You would need to define a Middleware that would check if the Engineer is approved or not.
Obviously, you would also need to keep that in an is_approved column for example.
<?php
namespace App\Http\Middleware;
use Closure;
class CheckEngineerApproval
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (! auth()->user->is_approved) {
return redirect('user.approve');
}
return $next($request);
}
}
Then, add it in your $routeMiddleware array in your Kernel.
protected $routeMiddleware = [
//
//
'engineer.approved' => \App\Http\Middleware\CheckEngineerApproval::class,
];
Finally, you can add the Middleware in your Controller's constructor as well.
public function __construct()
{
$this->middleware(['auth:web','admin','engineer.approved']);
}
I created a Laravel REST API. My routes are auto-generated with Route::apiResource().
Authentication is set up using Passport and is working as intended.
Now I tried to implement an Admin role with a Middleware that I attach to store, update and delete in my Controller:
$this->middleware('admin-only', ['only' => ['store', 'update', 'delete']]);
I want my application to respond with 403 Insufficient permissions if the User is not an Admin.
For GET it is working as intended, but for PUT requests Laravel is always returning a Response with 302 Found.
AdminOnly Middleware
namespace App\Http\Middleware;
use Illuminate\Http\Response;
use Closure;
use Illuminate\Support\Facades\Auth;
class AdminOnly {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next) {
$user = Auth::user();
if (!$user->admin) {
return Response::create('Insufficient permissions', 403);
}
return $next($request);
}
}
I found my Error by throwing an Exception in constructor of Symfony\Component\HttpFoundation\RedirectResponse class (thanks to #jedrzej.kurylo) and examining the produced stack trace in laravels errorlog (storage/logs/laravel.log).
The AdminOnly middleware was never called, because I forgot to onclude the id in the request (/person instead of /person/{id}). This caused my default route to trigger and redirect to the application base.
I have an admins table that has some columns like id, admin_type, name, etc. Here I have two types of admin_type: one is "admin" and the other is "hod".
Now the problem is that I want admins that login with (admin_type == "admin") to be able to access all the admin URLs, but when admin_type == "hod" I want to limit the URLs the user can access.
I am using Laravel 5.2. Can anyone help me to resolve this issue?
For example, if a user with admin_type=="hod" accesses these links
www.example.com/admin/add-user
www.example.com/admin/edit-user
www.example.com/admin/add-customer
www.example.com/admin/edit-customer
and many more URLs, I want to show some message like **You have no rights to access this link **
Here is my database structure:
I would implemented a Middleware for such a use case. Just execute php artisan make:middleware yourNameHere in your Laravel working directory and artisan generates the corresponding middleware class for you.
Then you need code like this. It's a simple if condition with an 403 abort in case that the user is no admin.
class AdminMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($request->user()->admin_type != 'admin') {
return abort(403, "No access here, sorry!");
}
return $next($request);
}
}
Your routes file (routes/web.php):
...
Route::group(["middleware" => 'admin'], function () {
//Your admin routes should be declared here
});
...
I'm building a multi languages site using Laravel 5.
I knew that in Laravel, I can define prefix for route like:
http://domain/en/users/1
http://domain/en/shop/1
And in Middleware, I can get the segment of url path to detect the language and set locale of current Request.
But I can't find anyway to add lang parameter in default for route like folowings:
http://domain/users/1?lang=en
http://domain/shop/1?lang=en
Or are there anyways to hook into route function of Framework to append default parameter ?lang=jainto all route when I call ?
(ja is current locale of application which was set in middleware before )
Thanks !
You can create a middleware that sets up a default 'lang' query parameter if the request doesn't have one. It will work for all the requests to your app, so you can get the lang parameter in every route handler.
Create a middleware LangFilter in the console (while in the project directory) :
php artisan make:middleware LangFilter
Then open up ./app/Http/Kernel.php and add :
\App\Http\Middleware\LangFilter::class
to the $middleware array. Now open up the middleware you created, i.e ./app/Http/Middleware/LangFilter.php and add the checking and setting code :
<?php
namespace App\Http\Middleware;
use Closure;
class LangFilter
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
// Checks for lang in the parameters.
if($request->input('lang') == null) {
// Adds the default one since it doesn't have one.
$request->merge(array('lang' => 'en'));
}
return $next($request);
}
}
If you want to have this kind of filtering for just a subset of all the routes you have, you need to register the middleware differently in Kernel.php.
UPDATE
For making a helper that generates routes with current locale :
Create a folder app/Support.
Create the helpers file app/Support/helpers.php
Open up helpers.php, and add this code to add the helper :
<?php
function locale_route($name, $parameters = [], $absolute = true) {
return route($name, array_merge($parameters, [
'lang' => App::getLocale()
]), $absolute);
}
?>
Add the helpers file to composer autoload in composer.json:
"autoload" : {
"files" : [
"app/Support/helpers.php"
]
}
Now run in the console :
composer dumpautoload
Now you can call locale_route with the same parameters you give to route to create urls that has the current locale added in query params.
I hope this is what you are looking for. Generating a route with a query string parameter