Call to a member function isAdmin() on null in laravel - php

I want to basic authenticate if User is Admin then Request next otherwise redirect to homepage
User.php:
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password','role_id','is_active','photo_id',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function role(){
return $this->belongsTo('App\Role');
}
public function photo(){
return $this->belongsTo('App\Photo');
}
public function isAdmin(){
if ($this->role()->name=="administrator"){
return true;
}
return false;
}
}
last function is isAdmin()
Admin.php (this is middleware):
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class Admin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::check()){
if (Auth::user()->isAdmin()){
return $next($request);
}
}
return redirect('/');
}
}
routes.php:
<?php
Route::get('/', function () {
return view('welcome');
});
Route::get('/admin',function(){
return view('admin.index');
});
Route::group(['middleware'=>'admin'],function(){
Route::resource('/admin/users','AdminUsersController');
});
Route::auth();
Route::get('/home', 'HomeController#index');
I get the following error:
FatalErrorException in Admin.php line 21:
Call to a member function isAdmin() on null
I also added 'admin' =>\App\Http\Middleware\Admin::class, in kernel.php and imported the class in Admin.php.

This is because of no user session. Middleware works only when user is login. So you need to login first and then check for middleware

Auth::user() return null if user is not authenticated.
to solve this issue use Illuminate/Support/Optional as follows
optional(Auth::user())->isAdmin()
if Auth::user() return null then the isAdmin() will never be called.

Please try this: change your method to static on User.php model.
static function isAdmin(){
if ($this->role()->name=="administrator"){
return true;
}
return false;
}
Next: Modify middleware it should work.
<?php
namespace App\Http\Middleware;
use Closure;
class Admin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (auth()->check()){
if (\Admin::isAdmin()){
return $next($request);
}
}
return abort(404); //redirect the user to not found page.
}
}

Because you do not have any role, first insert some data in the roles table.

Related

middleware keeps directing me to the login page

I'm working on a website where I have designed an authentication system. The client logs in through email and password. If it is correct it should proceed to the dashboard and should not be able to go back to the login page as long as he/she is logged in. However, middleware keeps directing to the login page saying that 'you have to login first'. Both middleware are registered properly in kernel.php
Kernel.php
protected $routeMiddleware = [
'alreadyLoggedIn' => \App\Http\Middleware\AlreadyLoggedIn::class,
'isLoggedIn' => \App\Http\Middleware\AuthCheck::class ];
Web.php
Route::post('/signin', [customAuthController::class,'loginClient']);
Route::get('/client',[customAuthController::class,'dashboard'])->middleware('isLoggedIn');
Route::get('/signin', [customAuthController::class, 'login'])->middleware('alreadyLoggedIn');
Route::get('/sign_up',[customAuthController::class,'registration'])>middleware('alreadyLoggedIn');
AlreadyLoggedIn (1st Middleware)
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class AlreadyLoggedIn
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* #return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
if(Session()->has('loginId')&& (url('signin')==$request->url()|| url('sign_up')==$request->url()))
return $next($request);
return back();
}
}
IsloggedIn (2nd Middleware)
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
class AuthCheck
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* #return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
if(Session()->has('loginId'))
return redirect('signin')->with('fail','You have to login first');
return $next($request);
}
}
customAuthCheck Controller
class customAuthController extends Controller
{
public function dashboard(){
$data = array();
if(Session::has('loginId')){
$data = client::where('id','=',Session::get('loginId'))->first();
}
return view('auth.client', compact('data'));
}
public function logout(){
if(Session::has('loginId')){
Session::pull('loginId');
return redirect('signin');
}
}
}
https://github.com/faaiz99/web-tech-project
In your AuthCheck class (as you named it isLoggedIn in your kernel) first condition is not what you really want to check .
you want to redict user to login if hes not already logged in .
so condition should be something like :
if(!Session()->has('loginId'))
{
return redirect('signin')->with('fail','You have to login first');
}
addition : Its really better if you use laravel auth .
i strongly suggest you to see laravel auth docs
with laravel authentication you can simply use auth facade in your middleware and that would be something like :
if(!auth()->check())
{
return redirect('signin')->with('fail','You have to login first');
}
Hope that helps .

How to pass array parameter to middleware in laravel

i don't know the syntax of php 7 i'm actually new to it
i'm trying to pass roles like ['admin','user','cmc'] to route middleware like shown below how do i do it properly
this is my route
Route::get('/dashboard','HomeController#dashboard')->name('dashboard')->middleware("roles:['admin','user']");
//how do i pass array of roles in it
//role middleware
<?php
namespace App\Http\Middleware;
use Closure;
use App\Role;
use Illuminate\Support\Facades\Log;
class Roles
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next,$role)
{
Log::info($role);
if($request->user()==null){
return response('unauthorised Access detected',401);
}
//check for any role passed from array
if($request->user()->hasAnyRole($role)){
return $next($request);
}
return response('unauthorised Access detected',401);
}
}
//usermodel
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function role(){
return $this->hasMany(Role::class);
}
public function hasANyRole($roles){
if(is_array($roles)){
foreach($roles as $role){
if($this->hasRole($role)){
return true;
}
}return false;
}else{
if($this->hasRole($roles)){
return true;
}
return false;
}
}
public function hasRole($role){
if($this->role()->where('role',$role)->first()){
return true;
}
return false;
}
public function getRole(){
return $this->role()->select('role')->get();
}
}
how do i pass role like ['admin','user','cmc'] some thing like this into the middleware of role
the problem is i can only get the first value in the array and the rest is not there
can some one get me out of this
I had a similar situation where I wanted to check if a user is an owner or admin before visiting a route; so I didn't need duplicate routes, and needed to pass an array instead of set single parameters.
I went down the route of sending a single paramter but using an | as a delimiter to explode on the middlewhere class.
In the route I had this for the route group
Route::group(['middleware' => ['checkRole:admin|owner']], function () {
and then in the middlewhere I used explode
$roles = explode('|', $permitted_roles);
Simple looped through the roles array to check if the user had one of the roles :) Hope this helps. Simple and easy for what I needed.

Laravel login will not redirect after login

Everyone. I have been stuck with Laravel redirecting after login. The connection works and after I login it redirects to a blank page but if I change the url path I can access the different web pages. Any assistance would be highly appreciated! I am using LDAP to connect and it is working.
On my AuthController I have the protected $redirectTo paths set. See picture below.
Please let me know if there is any other code I should provide.
Thank you!!!
(RedirectIfAuthenticated.php)
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
protected $auth;
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/computers/create');
}
return $next($request);
}
}
My Routes
Route::group(['middleware' => ['web']], function () {
Route::auth();
Route::get('login', 'LoginController#index');
Route::post('login', 'LoginController#check_password');
Route::patch('computers/{inventories}', 'InventoriesController#update');
Route::get('computers/search', 'InventoriesController#search');
Route::resource('computers', 'InventoriesController');
});
Route::get('/home', 'HomeController#index');
loginController.php
<?php namespace App\Http\Controllers;
/**
* #class Login
*/
use App\User;
use Illuminate\Http\Request;
class Login extends Controller
{
/**
* Show the application dashboard to the user.
*
* #return Response
*/
public function index()
{
return view('auth.login');
}
public function check_password(Request $req)
{
//die('has to stop here');
$user = User::check_password($req);
//var_dump($user); die;
if ($user)
{
return redirect('/computers/create');
}
else
{
return redirect('login')->with('message', 'Login Failed');
}
}
}
AuthController.php
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class AuthController extends Controller
{
/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
/**
* Where to redirect users after login / registration.
*
* #var string
*/
protected $redirectTo = '/computers/create';
protected $redirectAfterLogout = '/login';
/**
* Create a new authentication controller instance.
*
* #return void
*/
public function __construct()
{
//$this->auth = $auth;
//$this->registrar = $registrar;
$this->middleware($this->guestMiddleware(), ['except' => 'logout']);
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
//Using Ldap
// protected function validator(array $data)
// {
// return Validator::make($data, [
// 'name' => 'required|max:255',
// 'email' => 'required|email|max:255|unique:users',
// 'password' => 'required|min:6|confirmed',
// ]);
//}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
//Removed b/c LDAP is being usedcd
// protected function create(array $data)
// {
// return User::create([
// 'name' => $data['name'],
// 'email' => $data['email'],
// 'password' => bcrypt($data['password']),
// ]);
// }
}
InventoriesController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use DB;
use App\Inventory;
use App\Http\Requests\InventoryRequest;
class InventoriesController extends Controller
{
public function __construct()
{
//$this->middleware('auth'); //does not allow users to login, redirects back to login when using LDAP credentials
}
public function index(Request $request)
{
$location = $request->input("building");
if ($location != null) {
$inventories = Inventory::where('building', $location)->get();
} else {
$inventories = Inventory::all();
}
return view('computers.index', compact('inventories'));
}
public function show($inventories)
{
$inventories = Inventory::findOrFail($inventories);
return view::make('computers.show')
->with('inventory', $inventories);
}
public function create(){
//flash('Hello World', 'This is the message');
return view('computers.create');
}
/**
* Store a newly created resource in storage.
*
* #param inventory $request
* #return Response
*
*/
public function store(InventoryRequest $request)
{
Inventory::create($request->all());
flash('Success!', 'Inventory Successfully Updated!');
//s
// return redirect()->back(); //temporary
return back();
}
public function edit($inventories)
{
$inventories = Inventory::findOrFail($inventories);
return view('computers.edit', compact('inventories'));
}
public function update(InventoryRequest $request, Inventory $inventories){
$inventories->update($request->all());
flash('Success!', 'Inventory Successfully Updated!');
return back();
}
public function search()
{
$search = \Request::get('q'); //<-- we use global request to get the param of URI
// $search = Input::get('search');
$inventories = Inventory::where('lastName','LIKE','%'.$search.'%')
-> orwhere('firstName', 'LIKE','%'.$search.'%' )
-> orwhere('department', 'LIKE','%'.$search.'%' )
-> orwhere('building', 'LIKE','%'.$search.'%' )
-> orwhere('room', 'LIKE','%'.$search.'%' )
-> orwhere('manufacturer', 'LIKE','%'.$search.'%' )
-> orwhere('device', 'LIKE','%'.$search.'%' )
-> orwhere('model', 'LIKE','%'.$search.'%' )
-> orwhere('tag', 'LIKE','%'.$search.'%' )
-> orwhere('macAddress', 'LIKE','%'.$search.'%' )
-> orwhere('status', 'LIKE','%'.$search.'%' )
-> orwhere('comments', 'LIKE','%'.$search.'%' )
->get();
return view('computers.search',compact('inventories'));
}
}
Check the RedirectIfAuthenticated.php Middleware. It should look like this by default:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/home');
}
return $next($request);
}
}
Make sure that what is returned is the good page!! If you don't have that Middleware maybe take a look at Laravel's doc to create one!

Call model function into custom middleware file in Laravel 5.2

I am new in Laravel. I am developing an application from scratch as of now I just used laravel auth i.e (php artisan make:auth).
My requirement is to pull data for a loggedin user from a table i.e "admin" into my custom middleware but I am unable to call function which is defined in my Model i.e "Admin" file.
MODEL FILE :- app\Admin.php
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Admin extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function roles()
{
return $this->belongsToMany('App\Role', 'admin_role', 'admin_id', 'role_id');
}
public function hasAnyRole($roles)
{
if (is_array($roles)) {
foreach ($roles as $role) {
if ($this->hasRole($role)) {
return true;
}
}
} else {
if ($this->hasRole($roles)) {
return true;
}
}
return false;
}
public function hasRole($role)
{
if ($this->roles()->where('name', $role)->first()) {
return true;
}
return false;
}
public function myfunction($val)
{
echo "===>".$val; exit ;
}
}
MIDDLEWARE FILE :- app\Http\Middleware\CheckRole.php
<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$request->admin->myfunction('customvalue');
exit ;
}
}
I need to call function i.e "myfunction" which is define in Admin model into Checkrole.php middleware.
Thanks
try
auth()->user()->myfunction();
from the middleware. ( I am assuming you have an authenticated user at this point)

laravel constructor redirect

I have a method for checking if a user's role is an admin, if not, redirect them with return redirect('/')->send();. How can I check for user role and redirect the user without displaying the page and waiting for a redirect?
My Controller:
class AdminController extends Controller
{
public function __construct()
{
if (Auth::check())
{
$user = Auth::user();
if ($user->role != 'admin')
{
return redirect('/')->send();
}
}
else
{
return redirect('/')->send();
}
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return View('admin/index');
}
}
Create your own Middleware. Here is an example. In my example, I have several usergroups in a separate model. You have to change the code for your needs.
Create the Middleware via terminal/console:
php artisan make:middleware UserGroupMiddleware
The created middleware class could be find in app/Http/Middleware/UserGroupMiddleware.php
You need the following code in your middleware:
namespace App\Http\Middleware;
use Closure;
use App\User;
use App\Usergroup;
class UserGroupMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $group)
{
if($request->user() !== NULL){
$userGroupId = $request->user()->group;
$userGroup = Usergroup::find($userGroupId);
if($userGroup->slug === $group){
return $next($request);
}
}
// Redirect the user to the loginpage
return redirect('/login');
}
}
Now you have to register this middleware in app/Http/Kernel.php:
protected $routeMiddleware = [
// other middlewares
// Custom Middleware
'group' => \App\Http\Middleware\UserGroupMiddleware::class
];
Finally you need to attach the middleware to your route:
Route::group(['middleware' => 'group:admin'], function(){
// Routes for admins, e.g.
Route::get('/dashboard', 'SomeController#dashboard');
});
// Or for a single route:
Route::get('/dashboard', ['middleware' => 'group:admin'], function(){
return view('adminbereich.dashboard');
});
Remember, that you could pass in multiple middlewares with:
Route::get('/some/route', ['middleware' => ['group:admin', 'auth']], 'SomeController#methodXYZ');
import redirect by adding this to the above the class
use Illuminate\Support\Facades\Redirect;
And the make your redirect by using
return Redirect::to('login');

Categories