Closed mav2287 closed 3 years ago
@mav2287 that expands quite a lot the idea of this library to something beyond of routing and I don't think we should do this - but @nikic can surely correct me.
I usually handle this kind of thing in PSR-15 middlewares, even before sending the request to the handler. However, this requires the combination of other libraries :+1:
@lcobucci I spent sometime playing with https://github.com/middlewares and it looks pretty powerful, but I'm not sure I understand how you would attach access requirements to routes with it.
I am going to be using FastRoute to create a REST api and I want to be able to attach the access requirements to the routes themselves. My thought for this is that I will just add the access requirements to the route definitions. Then when I am dispatching, if a route is found it would check if the user has sufficient access and return access denied instead of running the handler if they don't
If I can do this with middleware I am all for it I just couldn't figure out how that would work while playing with it today. Could you please elaborate a bit on how this could be done with Middleware?
@mav2287 the idea is not to put that information in the routing configuration but to have another configuration which relates to the route. Imagine a hash map using the route name as index...
The psr15-compatibile libraries usually provide the matched routed as a request attribute.
One can combine the configuration with the matched route and perform whichever validation needed in a middleware - as long as such middleware is executed after the one that sets the matched route.
@lcobucci I have put a lot of thought into this and also dug into the solutions you have provided The one thing I keep coming back to is the value of being able to attach additional data directly to the route definition.
In my case being able to do this means that the permission data is right there with the route in the code base. This makes helps keep the data together in the code and makes it easier to read. This will help avoid mistakes and make any existing mistakes easier to spot. Outside of my specific use case I could also see several other use cases where this could be the case.
Similar to what I had originally posted I think the easiest and most effective way to do this may be the following:
addRoute($httpMethod, $route, $handler, $additionalRouteData ); // $additionalRouteData - represents data that is available later be it a string, array or other data
$additionalRouteData = $routeInfo[3]; // used to retrieve additionalRouteData set earlier
By making the 4th parameter ($additionalRouteData) optional you give have the ability to carry data through with the route without giving up or losing anything. This also means that no existing code changes would be needed for anyone using FastRoute currently. In my case I would just make it an array with all the relevant permissions data.
Since handler
is mixed
you could pass the additional data there (as a data object).
Closing here then :+1:
No need to re-open, but just wanted to put in where I ended up with this in case someone has the same needs in the future.
I'm using middleware and the place I landed for now is to have a middleware dispatcher as the handler. So for example:
$r->addRoute(['GET', 'OPTIONS'], '/user/edit',
new Dispatcher([
// handler to redirect to login page if not logged in
(new isNotLoggedInRedirectHandler),
// handler to show access denied if user doesn't have permission
(new PermissionsHandler)
->hasPermission(['editUser'),
// code for the actual edit user page
new CallableHandler( 'HandlerOnceTheseSpecificChecksHaveRun' )
])
);
Not sure if there is a better approach or way to improve on this, but it meets the requirements of what I was originally trying to do.
What would be the easiest way of defining a user capability for a specific route or group of routes when defining the route, IE something like like addRoute($httpMethod, $route, $handler, $requiredRole ). Then during dispatch being able to get back something like FastRoute\Dispatcher::Insufficient_access if the user didn't have sufficient access to the route?