Problem in my test function trying to access group of routes - php

What I'm trying to test is to access some routes but these routes are in laratrust role middleware this role is the auth user must be super admin to go in this routes my problem is I don't know how to write this function.
I tried to make the user super admin in the test function like this
public function Test()
{
$user = factory(User::class)->create();
$user->attachRole('superadministrator');
$this->actingAs($user, 'api');
$response = $this->json('GET', 'api/users');
$response->assertStatus(200);
}
but it didn't work even I checked the data base this user is superadministrator and the test give like I'm not super admin
This is my api routes:
Route::group(['middleware' => ['auth:api', 'role:superadministrator']],
function()
{
Route::apiResource('users', 'UserController');
}
This is my index function in UserController:
public function index()
{
return Response()->json(User::all, 200);
}
What I'm expect is a function can access this route because there is more routes in this group and the rest of the tests depends on this function

I've never used Laratrust, but after a quick look at its source code, it looks like the issue is that you need to specify the api guard on your role middleware check. Add ,guard:api to your role middleware:
Route::group(['middleware' => ['auth:api', 'role:superadministrator,guard:api']], function() {
Route::apiResource('users', 'UserController');
}
In the role middleware check, if you don't specify the guard, it will use the default guard defined in your auth config (which is web if you haven't changed it). So, the middleware will be looking for the user from the web auth guard, which doesn't exist.
The good news is, your test worked! It found a bug in your route definition.

Related

Laravel Routes using Middleware with an OR in list of Middleware or other method

I am using the Spatie permission and roles package for Laravel. I wanted to try and check the permission and roles in my web routes.php file in Route Groups, but that doesn't seem to work because the Auth::user() does't have the Spatie functions attached in the routes. That must happen somewhere else. I say that because I get a call to member function on NULL.
What I am currently doing is something like this:
Route::group(['middleware' => ['auth:sanctum', 'verified']], function () {
Route::post('/Reports/getallhl7_reports', [ReportsController::class, 'getallhl7_reports'])->name('getallhl7_reports');
Route::post('emailReport', [UtilitiesController::class, 'emailReport'])->name('emailReport');
});
and then in the Controllers checking the permissions and roles like:
protected function getallhl7_reports(Request $request) {
if (Auth::user()->can('provider_data') || Auth::user()->can('staff_data')) {
return Reports::getallhl7_reports($request->input('StudyInstanceUID'));
}
}
What I might want to do is to check the permissions in the routes or routes groups instead of in the Controller, but like I said the Spatie functions are not available in the Route Groups (After the Group, but before the Route) for some reason, and using an OR in the Middleware seems to be problematic. You can check for permissions in the Group, but I think that is an AND and not an OR, like:
Route::group(['middleware' => ['auth:sanctum','verified', 'permission:provider_data', 'permission:staff_data']], function () {
It isn't clear to me how I could check permissions using this format:
Route::post('emailReport', [UtilitiesController::class, 'emailReport'])->name('emailReport');
by modifying it with something to verify some set of permissions before invoking the Controller.

Check if any middleware grant access in laravel

I have two types of user roles. Admin and manager. An admin can to to all the routes, but a manager can only access some of them. Most of my routes are resource route. Currently I have this route group for admin:
Route::middleware(['auth', 'admin'])->prefix('admin')->group(function () {
Route::resource('post','PostController')
}
Here is my 'admin' middleware if you need to check:
if (!Auth::user()->isAdmin())
{
return redirect('/home');
}
return $next($request);
Here, all the routes are accessible by the admin. But I want to allow access some of the routes such as post.index, post.show, post.edit for the manager.
What should I do now?
Below I am explaining my question elaborately with and example
I have three middleware, auth, manager, admin. As the name suggests, auth middleware checks if a user is authenticated, manager middleware checks if the user is manager and certainly admin middleware checks if the user is admin.
Now, for Route::resource('post','PostController') route,
auth has access to post.index, post.view
manager has access to post.index, post.view, post.edit
admin has access to all the routes.
What is the best way to apply middleware to solve the problem?
Laravel allows for multiple routes in your controllers
Follow the following steps:
Remove the 'admin' middleware from your route group, leaving just 'auth'.
Route::middleware(['auth'])->prefix('admin')->group(function()
{
Route::resource('post','PostController');
}
In your 'manager.php' route file now, you can use and point to the same PostController
Route::middleware(['auth'])->prefix('manager')->group(function()
{
Route::resource('post','PostController');
}
then add a __construct() method at the top of the PostController like this
class PostController extends Controller
{
public function __construct()
{
$this->middleware('admin')->except(['index', 'show', 'edit']);
$this->middleware('manager');
}
}
You can define partial ressource routes.
https://laravel.com/docs/7.x/controllers#restful-partial-resource-routes
So you can define some of them in your middleware group and the other ones outside of it.
Route::middleware(['auth'])->group(function(){
Route::middleware(['admin'])->prefix('admin')->group(function () {
Route::resource('post','PostController')->except([
'index', 'show', 'edit'
]);
}
Route::middleware(['manager'])->prefix('manager')->group(function () {
Route::resource('post','PostController')->only([
'index', 'show', 'edit'
]);
}
}

how to block Url to all user except super admin

it should forbid that the user grabs this url:
?main_title=banner
?main_title=law
?main_title=faq
with this
if(\Auth::user()->hasRole(['super_admin']))
I am going to assume that you are using spatie/laravel-permission based on your example code.
Laravel Permission comes with built-in role middlewares
One of the ways you could use them is by grouping the routes you want to be accessible only by super admins
Route::group(['middleware' => ['role:super_admin']], function () {
// YOUR ROUTES HERE
});
It's always good to using the middlewares ,
So in your case first create a Trait for roles
public function isSuperadmin(){
return Auth::user()->role->role=='superadmin';
}
After that create a middlewar like superadmin for the superuser and in that first include your trait
use App\Traits\Roles;
after that
use Roles;
public function handle($request, Closure $next)
{
if(!$this->isSuperadmin())
{
return back();
}
return $next($request);
}
and just register the middleware in the app/http/kernal.php in protected $routeMiddleware function
'superadmin' => \App\Http\Middleware\superadmin::class,
so it's make your life very easy now you don't need to check the url or role every time , for any url you want to block for other users just use
Route::get('/?main_title=law', 'HomeController#function')->middleware('superadmin')->name('admin-dashboard-home');
so if the user role is superadmin then he is allow to assess the url you can redirect the other users or show the error message :)

Check the user's auth in all controllers' actions

I use Laravel 5.3 and I have the following problem.
[UPDATE]
My initial trouble was the appearance of an error when performing actions on the site when the user was not logged in the system.
This happened when the browser is started, where cached information is displayed by default on the page. Site interface displayed for logged users, and in his system was not. At the same time, producing some action, I get an error that the user is not authorized.
I also have group auth middleware for all my routes. When I reboot page of the site, the middleware is activated and redirectedme to the login page. The main problem is the browser shows the cached information.
So, in addition to middleware for routes I decided to make auth check in controllers.
[/UPDATE]
I want to check user's auth in every controller's action. Making the auth check in every controllers' action manually isn't a solution, because there are many controllers and actions.
So I decided to make it globally.
As all controllers extends Main Controller (App\Http\Controllers\Controller.php), I decided write the
auth()->check() in constructor:
function __construct()
{
if(auth()->check()) dd('success');
}
But... nothing happened((( Then I found the callAction method in BaseController which Main Controller extends and made checking here:
public function callAction($method, $parameters)
{
if(auth()->check()) dd('success');
return call_user_func_array([$this, $method], $parameters);
}
This time everything's OK, but I don't like this solution, because editing the core files isn't good.
Finally, I redeclared callAction method in Main Controller with auth checking, but I don't like this way too.
Is any solution?
You should use middleware:
Route::get('profile', ['middleware' => 'auth', 'uses' => 'UserController#showProfile']);
Or:
Route::get('profile', 'UserController#show')->middleware('auth');
Or using middleware groups:
Route::group(['middleware' => ['auth']], function () {
// Controllers here.
});
Or using controller's construct:
public function __construct()
{
$this->middleware('auth');
}
You can use auth middleware in your controller
public function __construct()
{
$this->middleware('auth');
}
check here : https://laravel.com/docs/5.3/authentication
if there is a group of routes this would be the easiest way
Route::group(['middleware' => ['auth']], function()
{
// here all of the routes that requires auth to be checked like this
Route::resource('user','UsersController');
}
another ways
function __construct()
{
$this->middleware('auth');
}
another way is specified on controller routes
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'UserController#showProfile'
]);
see documentation
https://laravel.com/docs/5.0/controllers#controller-middleware

How to ensure user is authenticated before he publishes an article in Laravel in the below scenario?

I am developing a simple web blogging application in Laravel 5.1. The application contains two controllers, a UsersController and an ArticlesController.
The authenticate() and check() functions that validate whether the user is authorized to carry out the operation are in the UsersController, and the store(), update() etc. features related to articles are in the ArticlesController.
How am I supposed to call the authenticate() or check() function from ArticlesController before say, store()ing an article to the database?
Laravel uses middleware, in your controller you need to put this
public function __construct(){
$this->middleware('auth'); //Requires auth
}
and in your routes you need to add the code for use middleware in your needed controllers like this
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});
Read the documentation of Laravel about Middleware you can create more middleware http://laravel.com/docs/master/middleware
You're question is not very clear, but I suppose that you want check if an user is authenticated before storing an article. There are many ways to do it:
Set a middleware in the routing rules of your ArticleController.
Check the authentication in the store method using the "standard" Auth class.
Example:
function store()
{
if (Auth::check())
{
// The user is logged in...
}
}

Categories