Laravel 5.2 - access authenticated user in route binding - php

Is it possible to access the authenticated user in a route binding.
Route::bind('account', function($account_id)
{
dd(auth()->user()); // it's null :(
$account = App\Models\Account::where('business_id', auth()->user()->business_id)
->where('account_id', $account_id)
->first()
return !is_null($account) ? $account : App::abort(404);
});
I've tried grouping the route binding within some auth middleware, no dice - is this a thing? It would be really useful to pull off, to avoid extra validation in the controller.
Help appreciated.

As long as the bind is inside the Auth middleware you should be able to access it using Auth::user()
Route::bind('account', function($account_id)
{
dd(Auth::user()); // Here is the change
$account = App\Models\Account::where('business_id', Auth::user()->business_id)
->where('account_id', $account_id)
->first()
return !is_null($account) ? $account : App::abort(404);
});

You can use \Auth. This works for me:
RouteServiceProvider:
public function boot(Router $router) {
parent::boot($router);
$router->bind('account', function () {
dd(\Auth::user());
});
}
routes.php
Route::get('account/{account}', function () {
//test
});
prints user object

Related

Call to a member function isSuperUser() on null

I have added this method to my User model:
public function isSuperUser()
{
return $this->is_superuser;
}
is_superuser is a column of my users table which is set to Boolean type.
And then I created this middleware to check if the authenticated user is admin (super user) or not:
public function handle($request, Closure $next)
{
if($request->user()->isSuperUser()) {
return $next($request);
}
return redirect('/');
}
And I have applied this middleware to all the admin routes in RouteServiceProvider.php:
Route::middleware('auth.admin')
->namespace($this->namespace)
->prefix('admin')
->group(base_path('routes/web/admin.php'));
But now when I load one of the admin routes I get this error:
Call to a member function isSuperUser() on null
However I am already logged in to my account.
So what's going wrong here? How can I solve this issue?
You need to assume that user is not logged so you should use:
if($request->user()?->isSuperUser()) {
return $next($request);
}
or
if(optional($request->user())->isSuperUser()) {
return $next($request);
}
if you are using older PHP versions
Use this instead.
// ...
if(auth()->user()?->is_superuser)
// ...

deleting a user with query builder laravel

I'm trying to delete a user account using laravel query builder so I'm doing this
AuthRepository
class AuthRepository implements IAuthRepository
{
....
public function delete($user_id)
{
$res = User::where('id', $user_id->id)->delete();;
if ($res) {
return response('Success, user was deleted', 204);
} else {
return response()->json(error);
}
}
}
In controller
class AuthController extends Controller
{
protected $auth;
public function delete($user_id)
{
return $user_id->delete();
}
}
in api.php
Route::group(['prefix' => 'auth'], function () {
Route::group(['middleware' => 'auth:api'], function () {
// Delete user
Route::post('user/delete/{user_id}', 'AuthController#delete');
});
});
Passing user_id to ${API_URL}/auth/user/delete/{user_id} I'm facing
Call to a member function delete() in Controller on line return $user_id->delete();. Can someone please explain me why is this happening, thanks.
Take advantage of the route model binding and to this instead:
public function delete(User $user)
{
return $user->delete();
}
And your route:
Route::post('user/delete/{user}', 'AuthController#delete');
You cannot call delete() on an integer.
If you don't want to use the Route model binding as suggested by #nakov and insist on using id then you have to get the user first before deleting.
public function delete($user_id)
{
$user = User::findOrFail($user_id);
return $user->delete();
}

Error trying to edit a user on Laravel 5.4

I'm starting a project with laravel, and I'm having a problem when I try to edit a user.
It always return the "QueryException" as if I didn't pass the user ID, but I used the default layout for my Model, so my URL is something like /users/1/edit.
This is how my route is defined:
Route::get('/', function(){
return view('welcome');
});
Route::resource('users', 'CtrUsers');
This is the way I get the edit URL:
href="{{route('users.edit', $user)}}"
(the $user is set inside a foreach loop)
And this is my edit function:
public function edit(User $user)
{
return view('users.edit', compact('user'));
}
And something strange is that when I enter the URL /users/edit/1 (with de ID in the end), IT stops returning the QueryException, but returns "NotFoundHttpException".
Anyone had this problem?
change your controller
public function edit($id)
{
$user = User::findOrFail($id);
return view('users.edit', compact('user'));
}
Edited again
public function edit($id)
{
$user = User::where('usr_id',$id)->findOrFail();
return view('users.edit', compact('user'));
}
The issue is with the variable name which you have used for route model binding. Both variable names: the one which is on the route and another from the action parameter must match.
You can check the route info using php artisan route:list command.
So you have two options, either change the users variable name to user in the route like:
Route::resource('user', 'CtrUsers');
OR
You can change the variable name from user to users in the action parameter like:
public function edit(User $users)
{
return view('users.edit', compact('user'));
}
For more info:
https://laravel.com/docs/master/routing#route-model-binding
The best solution I found was rebuild my migrations changing the names of my tables ID's to just "ID", becouse I noticed that the errors were allways because the system doesn't find any column named usr_id.

Laravel: what's the better method to retrieve current logged user and why?

I know two method:
The first is using a Request object param in the controller's function
public function index(Request $request)
{
$user = $request->user();
return view('home');
}
The second is using directly the Auth facade.
public function index()
{
$user = Auth::user();
return view('home');
}
Are there any diferences? Are one method better that the other one and, if, yes, why?
This is only matter of preference, you can use:
public function index(Request $request)
{
$user = $request->user();
return view('home');
}
or
public function index()
{
$user = Auth::user();
return view('home');
}
or
public function index(Guard $auth)
{
$user = $auth->user();
return view('home');
}
or
public function index()
{
$user = auth()->user();
return view('home');
}
They will all work the same. There is no better or worse method for such simple piece of code.
In controller it doesn't make much difference but in case you write some services and you would like to test them (writing some unit tests for example), better solution would be in my opinion injecting Guard in constructor instead of running Auth facade or auth() helper.
The Auth facade provides a shortcut but the result is the same. You can always use \Auth::user() from your controller or views, on the other hand, if you want to use the $request variable, you need to pass it to your views.

Gate closure is always denied

I'm using Laravel 5.3. I've been able to create policy classes but when I try to register a gate closure, it is always denied.
Here is the boot() method in AuthServiceProvider
public function boot()
{
$this->registerPolicies();
Gate::define('view-admin-index', function ($user, $company) {
return true;
});
}
Here is the output when dumped.
dd(Gate::has('view-admin-index')); => true
dd(Gate::allows('view-admin-index', $company)); => false
UPDATE
I also get false instead of "here" if do this:
// In AuthServiceProvider
Gate::define('view-admin-index', function ($user, $company) {
dd('here');
return true;
});
// In controller, output is false
dd(Gate::allows('view-admin-index', $company));
UPDATE 2
// In controller, there is an authenticated user and output is false
dd(auth()->user()); // => User
dd(Gate::allows('view-admin-index', $company)); // => false
Looks like you aren't even getting to call the closure. This will be the behavior if you don't have a user currently authenticated. See Source Here. Are you getting any output if you call dd(Auth::user()) right before Gate::allows('view-admin-index', $company)?
If you need to manually login a user you can always do:
Auth::login(User::find($id));
I have the same problem, it looks like a big bug of Laravel 5.3.28.
It just doesn't accepts Collections as arguments.
Here is my workaround:
Code:
Gate::define('xx', function ($auth, $user) {
return 1;
});
Route::get('example', function()
{
$user = User::first();
dd( Gate::allows('xx', $user) ); //false
});
My workaround:
Route::get('example', function()
{
$user = (object)User::first()->toArray();
dd( Gate::allows('xx', $user) ); //true
});

Categories