Looking at the laravel docs for controllers, they have an example where they authorize actions via a policy inside a Controller class:
$this->authorize('action',$model);
Yet checking the laravel doc api, I can see that the base controller class has no authorize method. How does this work?
If I take a look at a standard controller that is scaffolded by Laravel, you'll see that it extends a "base" controller in your app/Http/Controllers folder;
use App\Http\Controllers\Controller;
class YourController extends Controller
{
//...
If you go and take a look at this "base" Controller class:
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
You can see that this is using the AuthorizesRequests trait.
If you go and take a look in the AuthorizesRequests trait you'll see these authorisation methods.
One of which is:
public function authorize($ability, $arguments = [])
{
[$ability, $arguments] = $this->parseAbilityAndArguments($ability, $arguments);
return app(Gate::class)->authorize($ability, $arguments);
}
This is how the authorize method works and is provided to your controllers.
Related
in my Laravel 9 project, the model does not retrieve users' data from the table, probably because it extends authenticatable instead of Model. and when I changed that, the authentication did not work.
Here is my model:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Database\Eloquent\Casts\Attribute;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
}
?>
I tried the controller and view code on another model and it worked.
what would the problem be?
I was trying to display records of users table but it keeps giving me the error Undefined variable $users.
I'm using Route::resource
services.AddMvc(o => {
o.Filters.Add(typeof(BoolResourceFilter));
})
I have registered a resource filter globally but my app is separated in FrontEnd and BackOffice.
I would like to apply this filter to the FrontEnd Folder and all the razor pages or controllers inside it.
Is there a way to do this or i have to manually do on each page?
You can apply a filter for controllers in 3 places:
an action method
a controller
or globally
So if you want to apply them semi-globally, your best chance is to create or use an existing base controller class, apply your filter to it and then let all controllers from your "FrontOffice" inherit from it.
[CustomFilter("Foo")]
public class MyBaseController : Controller
{
}
Filters for Razor Pages on the other hand can very well be applied on a sub-folder basis:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.AddFolderApplicationModelConvention(
"/FrontOffice",
model => model.Filters.Add(new CustomFiler("Foo")));
});
}
I've tried to combine conventional and attribute routing together.
However it doesn't work as expected, probably because I've missed to do something.
What I have so far:
Routing:
builder.MapRoute("Default", "{controller=Home}/{action=Index}/{id?}");
Home Controller:
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
Attribute Mapped Controller:
[Route("Admin")]
public class AdminLockController : Controller
{
[Route("ControlCenter")]
public async Task<IActionResult> Index()
{
return View();
}
}
_Layout.cshtml
<a asp-controller="Home" asp-action="Index">
<img id="app-logo-image" src="/img/corporate_logo.png"/>
</a>
Now when when the view Home\Index.cshtml get rendered the link in _Layout.cshtml will become
(Correct).
But when the view AdminLock\Index.cshtml get rendere the link is (Wrong).
So I guess I need to do some extra configuration, but no idea what. Any hints?
UPDATE 1:
It works perfectly in a new created mvc project. So it has to be something wrong in my project... i will try to find out what the issue is...
Found the Issue.
I'm using the Smidge as a bundler and Minifier.
I registred the Smidge Middleware before the Mvc Middleware. That seems to mess up the routing. I opened an Issue on githup. See https://github.com/Shazwazza/Smidge/issues/71
Changing the order fixes the problem.
I am setting up a multi-module application, so far I have it setup like this example http://docs.phalconphp.com/en/latest/reference/applications.html.
But I was wandering if its possible to have shared base controller that both the backend and frontend controllers extend from. This is so I can have a single ACL in the base controller. How would I set that up?
According to the docs I can create a controllerbase anywhere and then just require this file directly in the bootstrap file or cause to be loaded using any autoloader. So I created a folder called apps/shared/controllers/ControllerBase.php and required this file directly in the bootstrap file but this does not work.
If I try to load a controller like so:
class AdminController extends ControllerBase
{
public function indexAction()
{
echo "<h1>Hello admin!</h1>";
}
}
I get an error ...Backend\Controllers\ControllerBase' not found in......
So how do I cause to be loaded using any autoloader as per the docs? Do I need to register it as its own namespace or something?
You not using the full namespace path for your base controller so the autoloader attempts to find it under in the same namespace of the child class.
Try something like this:
namespace MyApp\Backend\Controllers;
use MyApp\Shared\Controllers\ControllerBase;
class AdminController extends ControllerBase
{
public function indexAction()
{
echo "<h1>Hello admin!</h1>";
}
}
This answer consider that you have applied the PSR-0 and PSR-4 properly.
I have a web site in MVC4 with area "admin" inside controller named "HomeController" ,also in my project a folder controller with controller named "HomeController" : when I do a call to
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
I get error :
Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
The request for 'Home' has found the following matching controllers:
site1.co.il.Controllers.HomeController
site1.co.il.Areas.Admin.Controllers.HomeController
If you have the same controller and action in different areas, MVC4 has no way to choose one of them, unless you specify which is the desired route.
You can specify it like this:
return RedirectToAction("action", "controller", new { area = "area" });
In your case area should be "admin"
If you want to refer to the root Controller, area should be ""
You can also try to refer to the appropriate controller like this: "admin\home", but I don't know if the equivalent "\home" would work.