Comments (8)
Sure. In your router.ex
you'll see that the Plugs.Veil.UserID is in the list under the :browser pipeline (near the top). If you add Plugs.Veil.User directly underneath that, then this will add the Veil.User struct to conn.assigns[:veil_user]. You should then be able to access the email/other attributes in your controller/views as required.
Example router pipeline:
pipeline :browser do
plug(:accepts, ["html"])
plug(:fetch_session)
plug(:fetch_flash)
plug(:protect_from_forgery)
plug(:put_secure_browser_headers)
plug(PhoenixExampleWeb.Plugs.Veil.UserId)
plug(PhoenixExampleWeb.Plugs.Veil.User)
end
Alternatively, if you only need the User struct to be loaded for certain specific requests (to avoid the app querying the database every single time), you could add it in the controllers instead. For example, the following controller would assign the veil_user only if the controller function being called was :new or :create.
defmodule YourAppWeb.Controller
use YourAppWeb, :controller
plug YourAppWeb.Plugs.Veil.User when action in [:new, :create]
# ...
Does that help?
from veil.
I originally tried adding HelloWeb.Plugs.Veil.User
to the authenticated pipeline (instead of adding it to browser directly because I figured I would only be able to access this user if they are authenticated).
If I add it to the browser pipeline like you have and then try to output <%= conn.assigns[:veil_user].email %>
in a template condition that only happens if a user is loggedin then I get function HelloWeb.SharedView.render/2 is undefined
and it points to the line where I'm referencing that conn variable.
It looks like this in the template:
<%= if veil_user_id = @conn.assigns[:veil_user_id] do %>
<li>
<a href="#"><%= conn.assigns[:veil_user].email %></a>
</li>
<li>
<a href="<%= session_path(@conn, :delete, @conn.assigns[:session_unique_id]) %>">Sign Out</a>
</li>
<% else %>
<li>
<a href="<%= user_path(@conn, :new) %>">Sign in</a>
</li>
<% end %>
And this in the router's browser pipeline (just as you have it):
# ...
plug(HelloWeb.Plugs.Veil.User)
from veil.
It should work fine in the authenticated pipeline too. I just quickly checked and this works for me. I think the problem is probably that in a template you will need to call @conn.assigns[:veil_user]
, does that work?
from veil.
Also you may not be able to call it as <%= @conn.assigns[:veil_user] %>
, as Phoenix won't know how to print the struct. I would recommend writing it like this:
<%= if veil_user = @conn.assigns[:veil_user] do %>
Authenticated as <%= veil_user.email %>
<% end %>
from veil.
Ok, yep it was a missing @.
But that does lead to another issue (which you may have just addressed).
If I put that pipeline in like this: pipe_through([:browser, HelloWeb.Plugs.Veil.Authenticate, HelloWeb.Plugs.Veil.User])
then I get a nil reference on the email even when logged in. It's also protected by the original <%= if veil_user_id = @conn.assigns[:veil_user_id] do %>
condition (see the snippet in the previous comment).
If I drop it into the main :browser
pipeline then it all works. I don't quite understand that.
Also, you mentioned:
(to avoid the app querying the database every single time)
At the end of the day, with this plug activated, are you saying we're performing 2 DB lookups per request now? One from step 3 in https://github.com/zanderxyz/veil#security and now again to get the user?
Edit: I do see 2 queries in the debug log output, one for the session and one for the user. Yikes.
from veil.
That surprises me too, I don't understand why that would happen. If I take the default Router block and add the Plugs.Veil.User one in like so:
# Default Routes for Veil
scope "/veil", PhoenixExampleWeb.Veil do
pipe_through([:browser, PhoenixExampleWeb.Plugs.Veil.User])
post("/users", UserController, :create)
get("/users/new", UserController, :new)
get("/sessions/new/:request_id", SessionController, :create)
get("/sessions/signout/:session_id", SessionController, :delete)
end
And then I visit http://localhost:4000/veil/users/new, I see the Authenticated as [email protected]
in the top right. Do you not?
And for question two, yes, although they are requests to different tables. The UserId plug calls {:ok, session} <- Veil.get_session(session_unique_id),
on row 15, which gets the session from the database. In theory they could be combined into a single request with a join if one needed session plus user for every single future request. Or it could be a single Plug that did the work of both steps.
from veil.
Meant to add: I'm not sure which is best but maybe the latter. I could probably refactor it pretty easily.
from veil.
Oh, I set things up a little different. I attached that plug to an authenticated pipe_through (a set of scoped roles that weren't the default routes for veil).
Feel free to close this issue if you wanted to open a separate issue for potentially refactoring the DB calls.
from veil.
Related Issues (16)
- The authenticate.ex plug has a placeholder project name HOT 2
- BUG : protocol Enumerable not implemented HOT 6
- undefined function html?/0 HOT 3
- Texting instead of emailing? HOT 6
- Advice on test startup times HOT 7
- Is there a way to trigger a cache reload? HOT 3
- Phoenix 1.4 support? HOT 3
- Umbrella support
- no function clause matching in Veil.verify/2 HOT 2
- Should Veil expect the email address along with the verification string to complete authentication?
- Clicking the Sign In link via local adapter causes Beam.smp to max out my CPU HOT 3
- Fresh install gets quite a few warnings and deprecations
- Ignoring unmatched topic "pos" in TestVailWeb.UserSocket HOT 2
- Feature request - Authorised users HOT 2
- Veil.Secure fails when a conn does not hold an user-agent header HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from veil.