Reputation: 27
I have a problem for activate a middlware on a route group on laravel 5.7. It's a simple middlware for filter post (centre in my case) which is or not to the logged user .
I activate the middleware on a group of 4 routes (edit, delete, show and destroy) and it's ok for all but not for update. For update nobody can do it.
I have this middlware in Centrepolicy
<?php
namespace App\Policies;
use Illuminate\Support\Facades\Auth;
use App\Models\Auth\User;
use App\models\Centre;
use Illuminate\Auth\Access\HandlesAuthorization;
class CentrePolicy
{
use HandlesAuthorization;
public function manage(User $user, Centre $centre)
{
if(!Auth::user()->hasRole('administrator')) {
return $user->id === $centre->user_id;
}
return true;
}
My route
/*
* All route names are prefixed with 'admin.auth'.
*/
Route::group([
'prefix' => 'auth',
'as' => 'auth.',
'namespace' => 'Auth',
'middleware' => ['permission:voir liste centre']
], function () {
Route::group(['namespace' => 'Centre'], function () {
Route::get('centres/create', 'CentreController@create')->name('centre.create');
Route::get('centres', 'CentreController@index')->name('centre.index');
Route::post('centres/store', 'CentreController@store')->name('centre.store');
});
Route::group(['prefix' => 'centres/{centre}', 'namespace' => 'Centre', 'middleware' => ['can:manage,centre']], function () {
Route::get('/edit', 'CentreController@edit')->name('centre.edit');
Route::get('/show', 'CentreController@show')->name('centre.show');
Route::put('/update', 'CentreController@update')->name('centre.update');
Route::get('/delete', 'CentreController@destroy')->name('centre.destroy');
});
my controller
<?php
namespace App\Http\Controllers\Backend\Auth\Centre;
use Illuminate\Http\Request;
use App\Models\Centre;
use App\Models\Auth\user;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class CentreController extends Controller
{
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index(Guard $auth)
{
/// $centres = centre::get()->paginate(5);
$centres = DB::table('centres')->paginate(10 );
if(!Auth::user()->hasRole('administrator')) {
$centres = $auth->user()->centre()->paginate(10);
}
return view('backend.centre.index', compact('centres'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
$centre = new Centre;
return view('backend.centre.createcentre', ['centre' => $centre ]);
/// return view('backend.centre.createcentre');
}
/**
* Store a newly created resource in storage.
*
* @return Response
*/
public function store(Request $request)
{
$centres = new Centre($request->all());
$centres->user_id = Auth::user()->id;
$centres->save();
return redirect()->route('admin.auth.centre.index');
}
/**
* Display the specified resource.
*
* @param int $id
* @return Response
*/
public function show(Centre $centre)
{
return view('backend.centre.show', compact('centre'));
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return Response
*/
public function edit(Centre $centre)
{
return view('backend.centre.editcentre', compact('centre'));
}
/**
* Update the specified resource in storage.
*
* @param int $id
* @return Response
*/
public function update($id, Request $request)
{
$centres = Centre::find($id);
$centres->update($request->all());
return redirect()->route('admin.auth.centre.index');
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return Response
*/
public function destroy(Centre $centre)
{
$centre->delete();
return redirect()->route('admin.auth.centre.index');
}
}
And my model
<?php
namespace App\Models;
use App\Models\Auth\user;
use Illuminate\Database\Eloquent\Model;
use Spatie\Permission\Traits\HasRoles;
class Centre extends Model
{
protected $fillable = ['titre', 'description', 'enligne', 'user_id', 'capacite', 'slug'];
/*
public function setSlugAttribute($value)
{
if (empty($slug)) {
$this->attributes['slug'] = str_slug($this->titre);
}
}
*/
public function user()
{
return $this->belongsTo(User::class);
}
My form for edit route is
<?php
///dd($centre);
if($centre->id){
$options = ['method' =>'put', 'route' =>['admin.auth.centre.update', $centre]];
} else {
$options = ['method' =>'post', 'route' => ['admin.auth.centre.store']];
}
?>
{!! Form::model($centre, $options) !!}
<div class="form-group">
{{ Form::label('Titre', 'Titre', ['class' => 'control-label']) }}
{!! Form::text('titre', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{{ Form::label('description', 'description', ['class' => 'control-label']) }}
{!! Form::textarea('description', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{{ Form::label('capacité maximum', 'capacite', ['class' => 'control-label']) }}
{!! Form::textarea('capacite', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::hidden('enligne', '0') !!}
{!! Form::checkbox('enligne', '1' , null) !!}
</div>
{!!Form::submit("Envoyer", ['class' => 'btn btn-primary'])!!}
{!! Form::close() !!}
When i arrive on the update page on admin/auth/centres/13/update i'm on a 403 error and in the debug bar i have 3 gate, 2 first are ok and last :
success
array:4 [▼
"ability" => "view backend"
"result" => true
"user" => 1
"arguments" => "[]"
]
success
array:4 [▼
"ability" => "voir liste centre"
"result" => true
"user" => 1
"arguments" => "[]"
]
error
array:4 [▼
"ability" => "manage"
"result" => null
"user" => 1
"arguments" => "[0 => 13]"
]
I think there is a problem with argument but this route is the same than delete/show/destroy so i don't understand
edit today i try to write the middleware like that :
public function manage(User $user, Centre $centre)
{
return true;
}
But nothing to do, don't work. What action can desactive this middleware only on the update route because it's active and ok on 3 another routes?
Upvotes: 0
Views: 986
Reputation: 3543
I think the problem is you are trying to access id
as a first parameter in the function and Request
as second. The way it is supposed to work with Laravel
is that, if you need Request
inside the function, it always must be first parameter inside the function
and then all the other parameters can follow, if for some reason you don't need Request
and you don't include it as a function parameter
then you can use other parameter as first one
, but as soon as you add Request
as one of parameters, it needs to be the first parameter
.
So a simple fix I think would be:
...
public function update(Request $request, $id) {
...
EDIT: After you've updated your answer with showing us how u are sending the id
of the model yo u are updating, it seems to me you are sending it wrong. It should be something along these lines:
...
$options = ['method' =>'put', 'route' => ['admin.auth.centre.update', $centre->id]];
...
EDIT: Another thing that came to my mind is why are you using Auth::user()
from inside the Policy
when you already got the Authenticated user
within $user
variable?
Try changing your if statement
code to this:
...
if(!$user->hasRole('administrator')) {
return $user->id === $centre->user_id;
}
...
Upvotes: 1