I have index method in controller like this
public function index()
{
$this->authorize('index', Contact::class);
....
}
and index method in ContactPolicy
public function index()
{
return Auth::user()->can('view_Contact');
}
and test method like this
/** #test */
public function a_user_without_permission_can_not_see_contacts()
{
$this->login(['no_permission']);
$this->get('/contacts')
->assertStatus(403);
}
When I run my test show me this error
1) Tests\Feature\AccountTest::a_user_without_permission_can_not_see_contacts
Illuminate\Auth\Access\AuthorizationException: This action is unauthorized.
Note1:
When I change My controller to this it work correctly and show me green
public function index()
{
if(Auth::user()->can('view_Contact')){
........
}else
return response()->view('403',['msg' => 'you_not_have_not_permission'])->setStatusCode(403) ;
Note2:
In login method in test class I send user permissions parameters and it work correctly.
the authorize method throws an exception if the user is not authorized. you need to use #expectesException or similar methods to signal your test to expect an exception.
Or, you can add a condition to your Handler class to catch this kind of exception and return a 403 response
edit: more explanation
when you call authorize method and the user does not have permission, the program throws an exception.
when a user is calling the api, the exception is translated to a response with 403 status and shown to the user, but when you are calling the api from within the program itself, the exception is thrown and the program halts, hence there would be no JSON response whatsoever.
To handle this situation, you have two options:
1- if you decide not to change your program, then instead of expecting a response with a specific status, you should tell your test to expect an AuthorizationException thrown. you can read how to do this hear
2- you can change your code so that instead of delegating the task of handling the exception to Laravel, you do it yourself in the Handler class and prepare a JSON response with 403 status and then your test should be run correctly.
Related
So I have the route lsapp.test/firms/1 which isn't available if you are not logged in.
But if I go to that route without being logged in is redirecting me to the login.After I log in it redirects me back to lsapp.test/firms/1, not the dashboard, and I get an error.
I've changed $redirectTo in the controllers to /dashboard but still isn't working.
If I go to /login and login it works.
How I can fix this?
public function __construct()
{
$this->middleware('auth');
}
public function show($id)
{
$employes = Firm::find($id)->employes()->paginate(5);
return view('firms.show')->with("employes", $employes);
}
Error: Call to a member function employes() on null.
The findOrFail methods will retrieve the first result of the query; however, if no result is found, a Illuminate\Database\Eloquent\ModelNotFoundException will be thrown.
If the exception is not caught, a 404 HTTP response is automatically sent back to the user. It is not necessary to write explicit checks to return 404 responses when using these methods.
public function show($id)
{
$employes = Firm::findOrFail($id)->employes()->paginate(5);
return view('firms.show')->with("employes", $employes);
}
I have a middleware that automatically logs all incoming requests. It also sends me an email when the status is 500. However, $response->getContent() only returns "Server Error" when debugging mode is disabled.
Is there some way to get more detailed information about the cause, like
$exception->getMessage() vs. $exception->getTraceAsString()
are available for the Exception class
current code:
if($response->getStatusCode() == 500) {
ErrorHandler::sendEmail('Incoming Request Error 500', $response->getContent());
}
You can interrogate the exception in the ExceptionHandler class before reporting and rendering take place: Source Line 37.
For example:
public function report(Exception $exception)
{
logger($exception->getMessage());
parent::report($exception);
}
I have a test:
#Test
public void shouldAddCompany() throws Exception {
mockMvc.perform(post("/companies")
.param("name", "companyName"))
.andExpect(model().attribute("company",
hasProperty("name", is("companyName"))));
}
and my controller method looks like that:
#PostMapping("/companies")
public String displayCompaniesPost(#ModelAttribute Company company) {
companyService.save(company);
return "redirect:/companies";
}
How can i check company attribute in test? There is a problem because of redirect and status 302.
java.lang.AssertionError: Model attribute 'company'
Expected: hasProperty("name", is "companyName")
but: was null
I think it occurs because controller is going to GET method because of redirection. When I remove this redirection everything is ok, but I don't want to remove that redirection.
EDIT (GetMapping):
#GetMapping({"/", "/companies"})
public String displayCompanies(Model model) {
model.addAttribute("company", new Company());
List<Company> companies = companyService.findAll();
model.addAttribute("companies", companies);
return "companies";
}
I thought the problem is because of addding attribute with the same name in getMapping, but when I removed it, it still doesn't work.
You need to modify your approach. If you POST to a controller method, and it returns a Redirect you will have no ability to access any model information set by that controller, it just returns an HTTP 302 with a Location Header to the client telling it the new url to go to (in this case GET /companies). If this is a strictly Unit test, that is the extent of what you can test for this method.
I would consider instead treating this as an integration test, and change your test to have two separate steps:
POST /companies and validate that the response is the expected redirect
GET /companies and validate that the list of companies returned contains the new company you posted in step 1
I have a custom Request Class on Laravel 5 which handles form inputs (POST). the thing is, I want to use the same request class for a GET method but instead of redirecting the user back to the original request URL (which causes an infinite) loop I want to throw an exception (if the request is not valid), how is that possible?
In your custom Request class, you can override the failedValidation method that is defined in the FormRequest class.
I.e. place this method in your Request class:
protected function failedValidation(\Illuminate\Validation\Validator $validator) {
throw new \Exception('Error processing request');
}
Overriding the response() method can also be used to return a preferred response, personally I have used this to return the errors in JSON form, all that was required to do this was to return a JsonResponse with the errors and response code:
public function response(array $errors)
{
return new JsonResponse($errors, 422);
}
You can add something like this in your request method:
if (Request::isMethod('get'))
{
//Here you can add your custom exception.
}
You can see the documentation for more info about this: http://laravel.com/docs/5.0/requests#other-request-information
How do you write a controller method which can either return a View or HTTP response status code based on if its 200 then view else the response status code.
#RequestMapping(value="/",method=RequestMethod.GET)
public String showLanding()
{
return View.Landing;
}
I want to handle in case of 401, 403, 500 etc. just status code should be returned instead of view.
To return the 403- Unauthorized status code,
#RequestMapping(value="/",method=RequestMethod.GET)
public String showLanding()
{
return HttpStatus.UNAUTHORIZED;
}
See this:
http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/http/HttpStatus.html?is-external=true
How to respond with HTTP 400 error in a Spring MVC #ResponseBody method returning String?
You could also check out the #ResponseStatus annotation as well as ResponseEntity (for more dynamic scenarios)
I'm far from suggesting that you should do flow control with Exceptions - but those HTTP statuses are errors and exceptions. So you might want to throw business exceptions from your controller methods and then handle those using #ExceptionHandlers.
You can also target a subset of Controllers and assist those with Exception handling using #ControllerAdvice.