I'm using spatie/laravel-permission and when I add my permission to my api route, I'm getting
message: "This action is unauthorized.
but my user does have permission
My route
Route::get('/customer/items', [ CustomerController::class, 'getItems'])->middleware('can:customer');
My CustomerController
public function getItems()
{
$items = Item::all();
return [
'items' => $items
];
}
I was this problem because my guard was auth:api
Route::prefix('coin')->middleware(['auth:api','can:manageCoins'])->group(function () {
Route::get('', [CoinController::class, 'getAllPagination']);
});
in role table and permission table filed guard_name = web
I change all guard_name to api
fixed it middleware can work for guard api
note : run this command php artisan optimize:clear
Related
My laravel project has an API route by auth.basic middleware which is used id of the authenticated user in the controller. when I call it in postman it works well and I get 401 when the username or password is incorrect, but in laravel APITest which extends from DuskTestCase, authentication does not take place so I get 500 instead of 401 when the user's informations were incorrect. However, by correct information, I have the same error because auth() is null.
it is written like below, which is wrong?
api.php route:
Route::get('/xxxxxx/xxxxxx/xxxxxxx', 'xxxxx#xxxx')->middleware('auth.basic');
APITest:
$response = $this->withHeaders(['Authorization' => 'Basic '. base64_encode("{$username}:{$password}")])->get("/xxxxxx/xxxxxx/xxxxxxx");
You can use actingAs() method for authentication in tests.
An example from docs:
public function testApplication()
{
$user = factory(App\User::class)->create();
$this->actingAs($user)
->withSession(['foo' => 'bar'])
->visit('/')
->see('Hello, '.$user->name);
}
Another example that you can use for an API:
$user = User::factory()->create();
$response = $this->actingAs($user)->json('GET', $this->uri);
$response->assertOk();
For more information: https://laravel.com/docs/5.1/testing#sessions-and-authentication
I am trying to get a user dashboard just like Instagram or Facebook has after their domain names. Example https://facebook.com/the.hardik.sisodia.page
Routes
Route::get('{username}', [DashboardController::class, 'index'])
->name('dashboard');
Route::get('contact', [ContactController::class, 'index'])->name('contact');
Controller
$user = User::where('username', $username)->get();
if (isset($user[0])) {
$data = [
'user' => $user ? $user : abort(404),
];
return view('frontend.user.dashboard', $data);
} else {
abort(404);
}
Issue
When I attempt to view the Contact page, I cannot view it because of a 404 error page not found. I don't understand where I am going wrong. I also tried to group dashboard route using {username} as a prefix in the route group but still faced the same issue.
As you're getting a parameter in your route address, you may have route conflicts.
Try adding a unique name before your route address, something like adding profile before the route
Route::get('profile/{username}', [DashboardController::class, 'index'])->name('dashboard');
Out the test it works, I can visit the page and the controller wroks fine. I wrote the following test:
public function test_logged_user_is_not_redirected()
{
PartnerFactory::new()->create();
$request = $this->actingAs(UserFactory::new()->create())
->get('partners')
->assertRedirect('partners');
dd($request->inertiaProps());
}
I get error code 500. This is the controller:
public function index()
{
return Inertia::render('Partners/Index', [
'filters' => \Illuminate\Support\Facades\Request::all($this->getFilters()),
'contacts' => function() {
return $this->getAllContacts();
}
]);
}
This is the route in web.php
Route::get('partners', [PartnersController::class, 'index'])
->name('partners')
->middleware('auth');
Using refresh database, tried url with a '/' before, I still get 500.
edit: without exception handling i get: Trying to get property 'id' of non-object
Found the solution: The user in jetstream MUST have the personal team!
I try to use phpunit with Laravel and Spatie but i have a issue.
I have this test :
public function testBasicTest()
{
$user = User::where('id', 2)->first();
$response = $this->actingAs($user, 'api')->json('POST', '/providersList', [
'database' => 'test'
]);
$response->assertStatus(200);
}
But i have a 401 error
Expected status code 200 but received 401. Failed asserting that 200 is identical to 401.
I have this in web.php
Route::group(['middleware' => ['auth:api','role:Admin']], function() {
Route::post('/providersList', 'ProviderController#index');
});
This is a common issue when doing testing, I can assure you that the cause of this error is because of your authentication because of 401 HTTP error code, check if the acting user has role admin
To get a better error output, add this to the top of your test function
$this->withoutExceptionHandling();
It should give a better idea of what the issue is.
I am fetching menus from database based on user rights and displaying it to my web page but if i access any url whose access i don't have then too it opens that page.
For this i have created and called access_denied function which redirect user's home page.
I have called access_denied function from constructor of AuthController because AuthController gets loaded on each page.
I have used following code
AuthController
public function __construct()
{
$this->accessDenied();
}
public function accessDenied()
{
$url_segment1 = Request::segment(1);
$url_segment2 = Request::segment(2);
$url_segment = $url_segment1 . '/' . $url_segment2;
$user_data = Auth::user()->toArray();
$dadmin = array_keys($user_data['admin']);
//this is sample of array
// $user_data['admin'] => Array
// (
// [admin/roles] => 1
// )
if (!in_array($url_segment, $dadmin)) {
return redirect('/home');
}
}
But I am getting following error
Non-static method Illuminate\Http\Request::segment() should not be called statically, assuming $this from incompatible context
If i using incorrect process then please suggest me correct way to redirect unauthorised user on home page.
First, you should create a middleware. In a command prompt type:
php artisan make:middleware AccessDenyMiddleware
Then you go to app/Http/Middleware/AccessDenyMiddleware.php and fill in the handle function {your own code}
$url_segment1 = Request::segment(1);
$url_segment2 = Request::segment(2);
$url_segment = $url_segment1 . '/' . $url_segment2;
$user_data = Auth::user()->toArray();
$dadmin = array_keys($user_data['admin']);
//this is sample of array
// $user_data['admin'] => Array
// (
// [admin/roles] => 1
// )
if (!in_array($url_segment, $dadmin)) {
return redirect('/home');
}
But add the following line
return $next($request); // If passed, proceed with the route
Then, in a route, you should type:
Route::get('/yoururlhere', ['middleware' => 'AccessDenyMiddleware', function() { /* Put your work here */ } ]);
There are much better approaches. Like Authorisation if you are using Laravel 5.2
Or maybe change the default Authenticate middleware if you are using Laravel 5
You can use a middleware for thath https://laravel.com/docs/5.2/middleware#introduction.
php artisan make:middleware RoleRouteMiddleware
You should put thath code in the handle method of the middleware "App\Http\Middleware\RoleRouteMiddleware" and use the $request variable instead of the facade Request.
The middleware would filter earch request to your app.
Register a middleware, add it on app/Http/Kernel.php at routeMiddleware array
protected $routeMiddleware = [
....
'alias' => App\Http\Middleware\RoleRouteMiddleware::class,
];
and then use it on specific routes like this:
Route::get('admin/profile', ['middleware' => 'alias', function () {
//your code here
}]);
or in route gruoups:
Route::group(['middleware' => 'alias', function () {
//your filtered routes
}]);