This action is unauthorized in laravel 8 - laravel

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

How can write test for laravel api route with auth.basic middleware

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

Username in URL after domain

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');

Laravel Jetstream Route Test With Inertia Returns Error Code 500

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!

Use phpunit with Laravel and Spatie

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.

How to call function in __constructor using laravel 5?

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
}]);

Resources