Laravel authorization policy not being called - laravel

My authorization policy is not being called and I am receiving a 403 error. This is part of an API.
I have tried calling it from the controller by using the 'authorize' helper or via middleware. I have also tried using the auth()->guard('api')->user()->can().
DeckPolicy.php
public function view(User $user, Deck $deck)
{
dd('policy called');
if ($deck->private) {
return false;
}
return true;
}
AuthServiceProvider.php
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
'App\Deck' => 'App\Policies\DeckPolicy'
];
public function boot()
{
$this->registerPolicies();
}
}
DecksController.php
public function show(Deck $deck)
{
$this->authorize('view', $deck);
return new DeckResource($deck);
}
I expect the output to be 'policy called', but all I am receiving is a 403 error page when using Postman.
I would like to understand why the 'authorize()' helper function is not working as expected.

Related

Laravel Policies - $this->authorize not working

Task policy:
class TaskPolicy
{
use HandlesAuthorization;
public function canSeeTeam()
{
return true;
}
}
AuthServiceProvider:
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
'App\Models\Task' => 'App\Policies\TaskPolicy',
];
Task controller:
public function update(Request $request, Task $task)
{
$this->authorize('canSeeTeam');
dd('Authorized!');
}
Instead of getting Authorized! I get:
"message": "This action is unauthorized.",
"exception": "Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException",
I'm logged in, and have access to the team, not it matters because canSeeTeam always true.
You also have to pass the task object to the authorize method:
$this->authorize('canSeeTeam', $task);
Please send me error message or replace this:
public function canSeeTeam()
{
return true; => return false;
}

Call to a member function hasAccessOrFail() on null error when using backpack in Laravel

I've been using backpack in Laravel but I want to replace action-domain-responder architecture with MVC.So I've created an Action which my route refers like below:
Route::get('post',[
'as' => 'post.index',
'uses' => 'Core\Post\Actions\ApiGetListOfPostsAction',
'operation' => 'list'
]);
class ApiGetListOfPostsAction extends BaseAction implements IAction
{
private $service;
public function __construct(ApiGetListOfPostsService $service)
{
$this->service = $service;
}
public function __invoke(Request $request): mixed
{
$data = $this->service->process();
return response()->json($data);
}
}
and my service has this code:
class ApiGetListOfPostsService extends CrudController
{
use ListOperation, CreateOperation, DeleteOperation, UpdateOperation;
public function setup()
{
CRUD::setModel(\App\Models\Post::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/post');
CRUD::setEntityNameStrings('post', 'posts');
}
protected function setupListOperation()
{
CRUD::column('title');
CRUD::column('content');
}
public function process()
{
return $this->index();
}
}
I've extended CrudController in my service class but I've got this error:
Call to a member function hasAccessOrFail() on null
which related to the ListOperation Trait and this code:
public function index()
{
$this->crud->hasAccessOrFail('list');
}
I need to send all requests to the Service class. How can I pass requests to the service class?
When I deleted middleware from CrudController I have no problem.
$this->middleware(function ($request, $next) {
$this->crud = app()->make('crud');
$this->crud->setRequest($request);
$this->setupDefaults();
$this->setup();
$this->setupConfigurationForCurrentOperation();
return $next($request);
});
I think your Action is missing something.
When using inheritance from a parent class, it might help to put this line in your constructor.
public function __construct(ApiGetListOfPostsService $service)
{
parent::__construct(); // <- Subclass constructor
$this->service = $service;
}
Doc: https://www.php.net/manual/en/language.oop5.decon.php

Notification fake assertion not working on password reset test?

I was trying to make tests for my auth routes. For password reset route I am trying to make in which I am faking the notification module of laravel and asserting as per the docs.
This is my test file
public function testUserReceivesAnEmailWithAPasswordResetLink()
{
$this->withoutExceptionHandling();
Notification::fake();
$user = factory(User::class)->make();
$response = $this->post($this->passwordEmailPostRoute(), [
'email' => $user->email,
]);
$this->assertNotNull($token = DB::table('password_resets')->where('email', $user->email));
Notification::assertSentTo($user, PasswordReset::class);
}
While I am running this, I am getting notification was not sent error.
My User model is like this:
use Notifiable, HasApiTokens, SoftDeletes, Uuidable, Switchable, ResourceMapper;
public function role()
{
return $this->belongsTo('App\Models\Role');
}
public function company()
{
return $this->belongsTo('App\Models\Company');
}
public function AauthAccessToken()
{
return $this->hasMany('App\Models\OauthAccessToken');
}
public function isRole($role)
{
return $this->role->uuid == $role;
}
public function sendPasswordResetNotification($token)
{
$this->notify(new PasswordReset($token));
}
public function resource()
{
return $this->morphTo();
}
I can't figure whats the exact problem.

Problem with authenticating in laravel when using dynamic route configurations

I use JWT authentication for my laravel api middleware group. Here is my route configuration:
Route::group(['middleware' => ['api']], function() {
Route::post('login', 'AuthController#login');
Route::post('test', 'AuthController#test');
});
This code works well and I can't have unauthorized access to test method of my AuthController class:
class AuthController extends Controller
{
public function __construct()
{
$this->middleware(['jwt.auth'])->except('login');
}
public function login()
{
//...
}
public function test()
{
//...
}
}
but when I change the route config to identify controller's methods name dynamically (as you see in the following code snippet), the authentication does not work anymore and I can access test method without bearer token!
Route::group(['middleware' => ['api']], function() {
Route::post('/{controller}/{method}', function ($controller, $method) {
$controllerClass = 'App\\Http\\Controllers\\'.$controller.'Controller';
if(method_exists($controllerClass, $method))
{
$controller = App::make($controllerClass);
return $controller->callAction($method, array());
}
return abort(404);
});
});
Any idea?

Change redirection after validation failed - laravel

I am validating a user registration form
for EX: (Requests validation class)
class UserCreateAccountRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'email' => 'required|unique:users,email',
'password' => 'required|min:6|max:32'
];
}
}
If the email is already registered I want to redirect to the password reset page.
How can i achieve this using request validation class without putting the validation in to the controller?
Inside the authorize function check whether the email already exists,
public function authorize()
{
$email = Request::input('email');
$result = User::where('email',$email)
->exists();
if($result)
{
return false;
}
return true;
}
If this returns false, forbiddenResponse function will be fired, therefore you need to include that function and inside that you can redirect to the page you want. This function will only returns false if the email is already exist.
public function forbiddenResponse()
{
return redirect('password_reset');
}
That's all.For your reference following is the structure of the Request class,
<?php namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Response;
class FriendFormRequest extends FormRequest
{
public function rules()
{
return [
'first_name' => 'required',
'email_address' => 'required|email'
];
}
public function authorize()
{
// Only allow logged in users
// return \Auth::check();
// Allows all users in
return true;
}
// OPTIONAL OVERRIDE
public function forbiddenResponse()
{
// Optionally, send a custom response on authorize failure
// (default is to just redirect to initial page with errors)
//
// Can return a response, a view, a redirect, or whatever else
return Response::make('Permission denied foo!', 403);
}
// OPTIONAL OVERRIDE
public function response()
{
// If you want to customize what happens on a failed validation,
// override this method.
// See what it does natively here:
// https://github.com/laravel/framework/blob/master/src/Illuminate/Foundation/Http/FormRequest.php
}
}

Resources