Sanjibukai
Hi everybody,
I wanted to know if we can have constraints in the route level. I mean defining a route with some constraints (based e.g. on the request sessions data).
Sorry if I do a parallel with rails, but in rails (as explained from here in the guides) we can have constraints on the routes.
The constraints I’m particularly interested in are those based on lambdas.
Let me give you an example use case I had in rails..
I have different kind of users (regular, admins, etc.) where I have its type stored in a session variable once logged in.
Then I can do the following:
constraints lambda { |req| req.session[:user_type] == 'Admin' } do
get '/dashboard', to: 'admin_dashboard#show', as: 'dashboard'
...
end
constraints lambda { |req| req.session[:user_type] == 'User' } do
get '/dashboard', to: 'user_dashboard#show', as: 'dashboard'
...
end
This example is a little extract and might not tell all the story but as you might noticed it’s somehow an authorization mechanism.
I can now have some resources controllers scoped to the type of users and I know that, thanks to the constraints at the route level, I will never have some authorization mishaps.
In more complex situations I can have only the show action for a user while having the whole resources actions for an admin.
Doing it like this let me not bother at all at the controller level and hence I don’t have the need to import any authorization package or code a complex custom authorization handler.
In the Router doc page, there is no mention at all of the word constraint.
So, do you know how I can do this?
Note: elixir being functional and Phoenix being based on plugs, I’m pretty sure that I can easily achieve this kind of constraint based routes, thanks to plugs, pipelines, forwarding routes and pattern matching, right? I just need some guidance.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming











Showing Posts 1 to 8- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
NobbZ
Routes are solely based on the request path.
Any additional constraints can be checked by addtional plugs in the controller or the actions logic itself.
In my opinion having an
/adminscope is more clean than routing the same path to different controllers.Sanjibukai
Does the
connobject available at that moment? Where I suppose session data can be accessed?This is exactly what I wanted to avoid.
In fact on my rails project I’m actually doing scoping but only for the controllers and not for the path.
Having the exact same path for the resources really simplify the whole. And then all the actions for a specific kind of user can perform only its related actions defined in its controller.
In my use-cases I had 6 types of users with some other resources. And I have several combinations of what a kind of user can do (view/edit/delete) to other users and other resources.
Trust me, filtering right at the route level simplified so much the whole codebase and everything worked very well without using any kind of authorization library.
So in conclusion, is it simply impossible to have constraints at the route level with Plug/Phoenix?
In the meantime I came across the following SO question where the OP asked something similar about constraint based routes. Unfortunately, there isn’t any solution in his question..
LostKobrakai
The phoenix router can be so fast, because it works by harnessing elixir’s pattern matching. Therefore a certain url either matches to a path registered in the router or not. If you have multiple routes matching the first one will win. For the pattern match the only variables to match on are the path, host and method.
Given those constraints you cannot handle the logic you’re looking for in a phoenix router. This is not to say that you cannot nest your plug hierarchy more to get to the same resulting functionality. You could have one router match the path
/dashboard, which forwards to a plug, which depending on your constraints decides which controller to call.Sanjibukai
As a noob myself, can you provide me some details about how to do that (with very little snippet of code)?
Particularly how I can load a plug from a route and how I can call a controller/action from a plug?
Looking at the docs, I can only go so far (which is completely guesstimating some arbitrary code)
In the main
router.exfileThen in a dedicated Plug Module (but I’m not sure at all if the following can work or even compile at all)
Now I can have dedicated Router modules that routes only to authorized and dedicated controllers/actions.
For example for the admin:
And for a user:
Again this is a little example, but in my use case I can have very complex inter-related authorized actions, and as you can notice having scoped controllers give me the ability to have completely different behavior for each kind of user.
Thank you for any guiding about how I can achieve this.
LostKobrakai
I was thinking about something akin to this.
But if you can have separate routers per user type that’s even simpler and imho the even cleaner solution.
Sanjibukai
In my attempt above (and in my rails project) it’s the case.
Indeed, put in other words I wanted to know if I can apply a whole Router module in a particular case (in my attempt I used
forwardbut it’s not working)..The problem in your example is that it work only for a given list of routes (first extract part of the router).
It would have been great to be able to apply a whole Router module so that in each case the whole routes can be different and dedicated.
Don’t know if this explanation is clear or not, but I’m a bit disappointed to learn that I cannot do what it’s easy in rails about constraints in routes..
LostKobrakai
Phoenix might be constraint in what you can do directly on the router level, but on the otherhand as everything is a plug you can quite easily nest/switch out stuff.
Sanjibukai
This!
calling the router was the missing part and now it seems that I’ll be able to mimic somehow what I was doing with rails.Thank you!