Laravel policy issue, 403 not found for show page - php

Im having some trouble with Laravel policies and cant work out why this isnt working?
I have a policy attached to a model with all the regular methods (index, create, show etc)
The index page is working fine, but i keep getting a 403 page not found when going to the view page?
As you can see in the policy i have returned true whether the check is succesfull or not and it still returns a 403
ShippingController
/**
* Display the specified resource.
*
* #param int $id
* #param ShippingModel $shippingModel
* #return \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\View\View
* #throws \Illuminate\Auth\Access\AuthorizationException
*/
public function show($id, ShippingModel $shippingModel)
{
$this->authorize('view', ShippingModel::class);
return view('pages.warehouse.shipping.show');
}
ShippingModelPolicy
/**
* Determine whether the user can view the model.
*
* #param \App\Models\User $user
* #param \App\Models\ShippingModel $shippingModel
* #return \Illuminate\Auth\Access\Response|bool
*/
public function view(User $user, ShippingModel $shippingModel)
{
if ($user->isSuperAdmin() || $user->hasPermissionTo(205, 'web')) {
return true;
}
return true;
}
I have added the authorize in the method even though i have the authorizeController defined as well but it still does not work
public function __construct()
{
$this->authorizeResource(ShippingModel::class, 'shippingModel');
}

Your view policy method is dependent on a model, but the check on the controller doesn't account for a model. Delete the second argument and only leave User $user

Related

Laravel error handling for APIs

I am building a web app + REST server with Laravel 5.5 so that the users can either access the services online with a web interface or indirectly use the APIs via the mobile app.
Now the objective would be to have the same controllers capable of handling both API and direct requests leveraging on Laravel built-in double routing and automatic JSON responses for FormRequests.
The main problems I am figuring are:
How to handle JSON (for API access) and HTML view (for web visitors) responses on the same controller function?
How to manage "Resource not found" errors in the controller and subsequently reply to the user in the desired way?
A possible approach to the second issue would be to use "findOrFail" and then catch the exception, looking whether the request has got an "Accpet" header and reply accordingly but it looks quite bulky.
Here is a brief overview of a controller I am working on; I haven't implemented any checks on the retrieved data yet.
class UsersController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$users = User::all();
return UserResource::collection($users);
}
/**
* Store a newly created resource in storage.
*
* #param \Washery\Http\Request\StoreUser $request
* #return \Illuminate\Http\Response
*/
public function store(StoreUser $request)
{
User::create($request->all());
return response()->json(['message' => 'success'], 200);
}
/**
* Display the specified resource.
*
* #return \Illuminate\Http\Response
*/
public function show($id)
{
$user = User::find($id);
return new UserResource($user);
}
/**
* Update the specified resource in storage.
*
* #param \Washery\Http\Request\UpdateUser $request
* #return \Illuminate\Http\Response
*/
public function update(UpdateUser $request)
{
User::update($request->all());
return response()->json(['message' => 'success'], 200);
}
/**
* Remove the specified resource from storage.
*
* #param \Washery\User $user
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
User::find($id)->delete();
return response()->json(['message' => 'success'], 200);
}
}
An approach would be to know where the request is coming from. If it comes from the mobile (API request), then return JSON, else, return a view.
if ($request->expectsJson()) {
return response()->json(['message' => 'success']); // No need to put 200 here.
} else {
return view('view.path');
}
You can learn more about the request api here: https://laravel.com/api/5.5/Illuminate/Http/Request.html

Sessions being overridden

I have developed a Laravel 4 application a few years ago which hasn't broken since. All of a sudden users were seeing others users information. Basically what happens is I use Auth::attempt to check the user and, if valid, I use Auth::user() to get the user. What is happening is there is only one session being written to the storage/sessions folder and whenever a new user logs in, this session is overridden with the new values. Hence, it will show the last persons data. I have used EXACTLY the same solution on another server and it makes a new session whenever someone tries to login.
My question is why is it only creating one session? How can I fix this please?
It is on a shared hosting platform and I am assuming that with a PHP update or something, something has broken. As mentioned it worked for years and now has stopped which means that it probably is a configuration. Please can you help me?
Source Code:
class SessionsController extends BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
if (Auth::check()) return Redirect::to('/dashboard');
return View::make('login');
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
if (Auth::attempt(array('email'=>Input::get('email'),'password'=>Input::get('password'),'usertype_id'=>'2'))){
return Redirect::to('/dashboard');
}
return Redirect::back()->withInput()->with('flash_error', 'Login credentials are incorrect.');
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy()
{
Auth::logout();
return Redirect::to('/login');
}
}
Then I use it as follows in other Controllers:
$student = User::find(Auth::user()->id)->student;

Laravel - 404 for destroy launching GET on Vagrant

I'm bulding API Laravel 5 application with RESTful controllers. I have method destroy defined this way in controller:
public function destroy($id)
{
App::abort(404);
}
because at the moment I don't want to handle it. The strange thing is when I use such code, I get 404 header but also get output from my show method:
public function show($id)
{
die('show method');
}
so when using DELETE method for my resource I get 404 code with output show method.
I'm 100% sure I'm launching destroy method, because if I put in my destroy method:
public function destroy($id)
{
die('destroy');
}
I will have displayed destroy with 200 status code
I'v tested it in PhpStorm but also with this Firefox addon and in both cases result is the same.
The question is - what is going here and how to return just 404 code without data or with empty data?
EDIT
I've investigated this issue further and what I discovered. If I run my app on localhost with:
DELETE http://lara404/test/1
I get pure 404 error as it should be.
I copied exact same code and run it in Vagrant. I run url:
DELETE http://lara404.app/test/1
and now I'm getting 404 code with abcdef message.
The only things I changed in default installation is:
1) adding at the beginning of routes.php
$router->resource('test','TestController');
2) Putting into TestController the following code:
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App;
class TestController extends Controller {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
//
dd('xxx');
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
return "abcdef";
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
App::abort(404);
}
}
3) Commenting in Kernel.php line:
'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken'
I've just checked it also with fresh installation of Laravel 5 (not using any specific commit) and exactly same happens - the same code launched on localhost works fine and the same code running on Vagrant goes to show method also
You need this if using json -
public function destroy($id)
{
return Response::json(null, 404);
}
Or this if not using json -
public function destroy($id)
{
return Response::make("", 404);
}

Laravel Undefined Offset: 1 - cause by routing

I get the error when trying to make a post call to /api/subject/search
I assume it's a simple syntax error I'm missing
I have my api routes defined below
Route::group(array('prefix' => 'api'), function()
{
Route::post('resource/search', 'ResourceController');
Route::resource('resource', 'ResourceController');
Route::post('subject/search', 'SubjectController');
Route::resource('subject', 'SubjectController');
Route::resource('user', 'UserController');
Route::controller('/session', 'SessionController');
Route::post('/login', array('as' => 'session', 'uses' => 'SessionController#Store'));
});
And my controller is mostly empty
class SubjectController extends \BaseController
{
public function search()
{
$subjects = [];
if((int)Input::get('grade_id') < 13 && (int)Input::get('grade_id') > 8)
$subjects = Subject::where('name', 'like', '%HS%')->get();
else
$subjects = Subject::where('name', 'not like', '%HS%')->get();
return Response::json([
'success' => true,
'subjects' => $subjects->toArray()
]);
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
}
}
You need to specify the method.
try
Route::post('subject/search', 'SubjectController#search');
See the named route example:
Laravel Docs
In your case I think search is not resolved by the controller to load the search() method. You are also sending a POST for search functionality and I guess it's better to do a GET request since POST and PUT are for storing data.
Conventions
When creating API's it's a good thing to stick to naming conventions and patterns.
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
Solution
Your route could be simpler like this: api.yourdomain.com/api/subject?search=term1,term2. Doing this with a GET query makes it going to the index() method. There you can check the GET params and do your search stuff and return.
Check this for the cleanest and truely RESTful way to make an API in Laravel:
How do I create a RESTful API in Laravel to use in my BackboneJS app
I got same error when accessing object at index of an empty array in view blade php file.

Laravel 4. default controller route wont accept arguments

I have a RESTful controller for my users to handle the viewing of a users profile.
The problem is this:
I want the url to look like this www.example.com/user/1
This would show the user with the id of 1. The problem is that when i define the getIndex method in the UserController it wont accept the id as an argument.
Here is my routes.php portion:
Route::controller('user', 'UserController');
Now, it is my understanding that getIndex is sort of the default route if nothing else is supplied in the url, and so this:
public function getIndex() {
}
within the UserController will accept routes,
"www.example.com/user/index"
and
"www.example.com/user"
and it does!
However, if I include an argument that it should take from the url, it no longer works:
public function getIndex($id) {
//retrieve user info for user with $id
}
This will only respond to
"www.example.com/user/index/1"
and not
"www.example.com/user/1"
How can i make the latter work? I really do not want to clutter up the url with the word "index" if it is not necessary.
If you are planning to do this, the best way is to use RESTful controllers.
Change your route to this one,
Route::resource('user', 'UserController');
Then generate a controller using php artisan command,
php artisan controller:make UserController
This will generate your controller with all RESTful functions,
<?php
class UserController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index() // url - GET /user (see all users)
{
//
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store() // url - POST /user (save new user)
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id) // url - GET /user/1 (edit the specific user)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id) // url - PUT /user/1 (update specific user)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id) // url - DELETE /user/1 (delete specific user)
{
//
}
}
For more info, see this one Laravel RESTful controller parameters
To display www.example.com/user/1 on address bar you should use show method. In Laravel, restful controller by default create 7 routes. Show is one of them.
in your controller create a method like the following:
public function show($id)
{
// do something with id
$user = User::find($id);
dd($user);
}
Now, Browse http://example.com/user/1.

Categories