laravel api gate check - php

im using laravel 7
and im using gates and policies
i have api controller called Journal_entries_controller
and i have index function
public function index()
{
$journal_entries = Journal_entry::with('get_journal_entry_lines')->get();
return response()->json($journal_entries,200);
}
like this everything working so good ..
to check gate i did this ..
public function index()
{
$auth = auth('api')->user();
if(!Gate::allows('journal_entries.view',$auth))
return 'not auth';
$journal_entries = Journal_entry::with('get_journal_entry_lines')->get();
return response()->json($journal_entries,200);
}
like that i get not auth the code stop there
and if i dd($auth) i gat the logged user like this ..
public function index()
{
$auth = auth('api')->user();
dd($auth);
}
any help here thanks ..

In the if statement:
if(!Gate::allows('journal_entries.view',$auth))
return 'not auth';
The Gate::allows is returning false by adding the ! we make the response true which is why the not auth code is returning.
The first thing to do is make sure the journal_entries.view is a gate in the App\Providers\AuthServiceProvider.
If it is a valid gate please post the contents of the gate so we know the intended functionality.
In the mean time you may want to try changing
if(!Gate::allows('journal_entries.view',$auth)) to if(Gate::denies('journal_entries.view',$auth)) or
if(Gate::allows('journal_entries.view',$auth))
The docs for gates can be found here https://laravel.com/docs/7.x/authorization#authorizing-actions-via-gates

Related

Controller doesnt have the alter request from the middleware

I have a custom middleware that edits requests like this:
public function handle($request, Closure $next)
{
$profileLocal = ProfileLocal::where(
'id', JWTHelper::tokenExtractProfileLocalID($request->token)
)->with('status')->first();
if (empty($profileLocal) || $profileLocal->status->email_verified == 0 || $profileLocal->status->blocked == 1) {
return $this->respondError('You dont have access to this store', 336);
}
$request->profileLocal = $profileLocal;
return $next($request);
}
However, when i try to access $request->profileLocal In my controller:
public function deviceSet(DeviceRequest $request)
{
dd($request->profileLocal);
}
I get null returned even though in my DeviceRequest if i try to dd(request()->profileLocal) it works fine?
Does anyone know what i may be doing wrong here?
I have noticed that if i use request()->profileLocal in my controller it works as expected
If you want to add add a value to the request and be able to access it as a property you can add it to the underlying request property:
$request->request->add([
'profileLocal' => $profileLocal
]);
// or $request->request->add(compact('profileLocal'))
Then you'll be able to access the value in your controller with:
$request->profileLocal
This value will also be included when you call methods like all() or input().
I was told that if I use:
$request->attributes->add(['profileLocal' => $profileLocal]);
In my middleware and then access it using:
$request->attributes->get('profileLocal')
It works, I dont know if this is the correct way though.

Creating custom redirect logic in Laravel 5.3; can't log users in

I wanted to do custom redirect logic upon logging in to my site. So I wrote this code
public function login()
{
$user = //what do I put here?
$this->guard()->login($user);
$id = Auth::id();
//dd($id);
$rfid = DB::table('users')->where('id', $id)->value('reference_id');
if ($rfid == null){
dd($id);
return redirect()->action('RedirectController#client');
}
else {
//dd($rfid);
return redirect()->action('RedirectController#employee');
}
}
However my problem is that all it does is redirect. Which makes sense. The code I have there only manages the redirect, there is nothing there to actually log anyone in. So I did some researching and found
$this->guard()->login($user);
As a way to log the user in. However I don't know what to define the variable $user as. I know this should work because I use it in a different place on my site, but it the $user variable that I use there wouldn't work here. So under the scenario of simply login in the user, what do put there in order to authorize the user as in our database, and then log them in?
If you look at Laravel 5.3 AuthenticatesUsers traits , you will understand how login works behind the scene.
you need to change your login method to use attempt instead of login as follows to work it accordingly.
public function login(Request $request)
{
$user = //what do I put here?
$this->guard()->attempt($this->credentials($request), $request->has('remember'));
$id = Auth::id();
//dd($id);
$rfid = DB::table('users')->where('id', $id)->value('reference_id');
if ($rfid == null){
dd($id);
return redirect()->action('RedirectController#client');
}
else {
//dd($rfid);
return redirect()->action('RedirectController#employee');
}}
I recommend you to use it as I mentioned. If you still want to get $user value you can try out
$user = $this->guard()->user();
Though I haven't used it like that.

Laravel: How to restrict route to admin and groupmates

I am currently developing a website using Laravel.
A user belongs to 1 and only 1 group.
How do I restrict the route
Route::('/view/profile/{id}', 'ProfileController#showProfile');
to be only accessible by other users belonging to the same group. I would also like to allow the admin to access this route. However the admin does not belong to any group.
I know there are two ways to solve your problem.
You can create a custom middleware and bind it to your route.
Or you can do a simple check in your controller method.
I will give an example of the second method since it is the easiest.
Example:
// YourController.php
public function yourMethod()
{
// Get the user from authentication
$user = Auth::user();
// Check user and redirect to login when NULL
// This also can be done with auth middleware (check link in method 1)
if (!$user) return Response::redirect('yourLoginRoute');
// Check if has not group throw forbidden
if ($user->group->id != theGroupId) return App::abort(403);
}
Edit after comment #PaulLucero
So if I understand correctly only users of the same group can visit eachothers profile page (view/profile/{id}). Also you want to use a middleware to solve this problem but are unable to retrieve the route parameter {id}.
You can retrieve a parameter in Laravel 4 outside a route by using Route::input('yourParameter'). Check this and scroll down to Accessing A Route Parameter Value.
Example:
class YourMiddleware
{
public function handle($request, Closure $next)
{
// Get id from route and get user model
$user_id = Route::input('id');
$user = User::find($user_id);
// Do some checks
....
// Get user from auth
$auth_user = Auth::user();
// Do some checks
....
// If groups don't match throw 403
if ($user->group_id != $auth_user->group_id) return App::abort(403);
return $next($request);
}
}
I think this should do the trick.
create a custom middleware try like this
public function yourMethod()
{
$user = Auth::user();
if ($user->group_id == 1) {
return Response::redirect('yourRouteToGroupID-1');
else if(if ($user->group_id == 2) {)
return Response::redirect('yourRouteToGroupID-2');
else{
return App::abort(403);
}
}

Laravel 5.1 Session not working

i have Session in my Controller store
public function store(Request $request)
{
\Session::push('store_pos.items',$request->all());
print_r(\Session::get('store_pos.items')); // This is show array
exit;
}
public function create()
{
$items = \Session::get('store_pos.items');
print_r($items); // in this syntax not show array
}
why session in function create not show ?
I've been using the session put but still does not appear
Thanks
You can do this if you want to return the input if anything error when you submit the form:
$trans = new Transaction();
// Do all the input stuff
if($trans->save()){
// your code if the transaction successfully save
}
return back()->withInput(); // this will return back to the page with input
//or if you prefer facade
return Redirect::back()->withInput();
Is your controller under "web" middleware?
Any routes not placed within the web middleware group will not have access to sessions and CSRF protection, so make sure any routes that need these features are placed within the group.

Error when trying to return Redirect in Laravel

When I submit a form in Laravel, the following controller method handles it:
public function update($id)
{
//handle input
return View::make('generic.success', ["message" => 'Data submitted successfully!']);
}
This works fine. However, instead of returning a view like above I'd like to return a redirect, because when I return the view directly, reloading the page resubmits the form.
So I tried to do this:
public function update($id)
{
//handle input
return Redirect::to('/success', ['message' => 'Data submitted successfully!']);
}
In my routes file I defined the success route:
Route::get('success', 'NotificationsController#success');
And set up a notification controller to display the view:
class NotificationsController extends BaseController {
public function success($message)
{
return View::make('generic.success', ["message" => $message]);
}
When I run the above code, I get the following error from Laravel:
InvalidArgumentException
The HTTP status code "1" is not valid.
I have no idea what this is supposed to tell me, and neither does Google apparently.
Can someone shed some light on this issue?
P.S.
Incidentally, being new to Laravel, I've noticed so far that Laravel's error reporting is very user-unfriendly, in that instead of telling me I have an issue with my router, or controller, or permissions, it displays these generic errors with no humane explanation of their cause. Is there a better way to troubleshoot problems in Laravel than relying on this?
For example, in the above incident, the error report points to this line of code...
public function setStatusCode($code, $text = null)
{
$this->statusCode = $code = (int) $code;
if ($this->isInvalid()) {
throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code));
}
...which is completely useless, as all it does is show me the code that printed the error itself.
The second parameter of the redirector's to() method is the HTTP status code that will be returned by the response, not data that will be passed along. Passing data when redirecting to GET routes can be done either via the query string or the session. The recommended solution here is to pass data via the current session using the with() method which passes that data for the next request. So in your case this would be the approach needed:
public function update($id)
{
return Redirect::to('/success')->with('message', 'Data submitted successfully!');
}
Then in your success method you can have this:
public function success($message)
{
return View::make('generic.success', ["message" => Session::get('message')]);
}
When in doubt always try checking the documentation first. The solution to this is explicitly stated in the Laravel Response Redirects Documentation.
Thanks a lot -Bogdan I found in the documentation that you post answer to my problem. In my case the solution was redirect to an action in a controller, like this...
return
\Redirect::action(
'PqrController#solicitud',
array($id)
)
->with(
'message',
'¡El estado de la solicitud ha sido actualizado correctamente!'
)
;
I redirect to a method in a controller, with one parameter array($id) and I put too in the session a message using ->with('message','Mensaje')

Categories