Chrichton

Chrichton

Programming Phoenix LiveView: B03 (page 56-57) auth exercise

Dear Sophie.
I tried to do the “Authorization” exercise and have two questions:

  1. When trying to plug in an email-service, I found the function “&Routes.user_confirmation_url(conn, :confirm, &1)” in “user_confirmation_controller.ex”.
    I wasn’t able to find this function.
    Where is it located or how is it created dynamically?

  2. I added the “username” field without problem, but when I set it to unique and made it safe with “unsafe_validate_unique(:username, Pento.Repo)” some tests failed. I tried to fix them via modifying the fixture()-Function, but still two test concerning the uniqueness of the “email” failed.
    Is there an easy way to get the generated tests running, when adding a second unique field?

Thanks for your superb book.
I learned a lot from this exercise, especially the sending of the confirmation-email via Bamboo and Sendgrid.

Best wishes from Heiko

Most Liked

SophieDeBenedetto

SophieDeBenedetto

Author of Programming Phoenix LiveView

Hi again @Chrichton!

So the Routes.user_confirmation_url/3 isn’t defined as such in your router. It’s defined under the hood of Phoenix by virtue of the user_confirmation_path routes that were added to your router.ex file by the Phoenix Auth generator. The function itself is passed as an argument to the Accounts.deliver_user_confirmation_instructions/3 function in the UserConfirmationController controller. In that Accounts function, the Routes.user_confirmation_url/3 is finally invoked to return the user confirmation URL, with the correct user token, to be rendered in the email sent to the user. I would trace the code flow in the Accounts.deliver_user_confirmation_instructions/3 to get a better understanding of how the Routes.user_confirmation_url/3 function is being used.

Re: your exercise solution:

It looks like your solution will ensure that a user is redirected to the "/guess" route when the complete the log in process. But the challenge is actually asking you to ensure that if a user who is logged in visits /, that they get automatically redirected to /guess. You can solve this a few different ways.

  • Add a function plug to the :browser pipeline in the router.ex to redirect the user from / to /guess if they are logged in. Like this:
#router.ex
defmodule PentoWeb.Router do
  use PentoWeb, :router
  import Phoenix.Controller
  ...
  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_live_flash
    plug :put_root_layout, {PentoWeb.LayoutView, :root}
    plug :protect_from_forgery
    plug :put_secure_browser_headers
    plug :fetch_current_user
    plug :redirect_if_logged_in # add me!
  end
  
  ...
  
  def redirect_if_logged_in(conn, _opts) do
    if conn.assigns.current_user && conn.request_path == "/" do
      redirect(conn, to: "/guess")
    end
    conn
  end
end

This requires importing the Phoenix.Controller module into the router to get the redirect/2 function, which I don’t love.

You could also add some logic to the PageLive live view’s mount function to do a redirect if there is a logged in user. This is the live view that handles the / route. It would look something like this:

# lib/pento_web/live/page_live.ex
 def mount(_params, %{"user_token" => _}, socket) do
    {:ok, redirect(socket, to: "/guess")}
  end

  def mount(_params, session, socket) do
    {:ok, assign(socket, query: "", results: %{})}
  end

Here, you are checking to see if there is a logged in user based on whether or not the session argument given to mount has a "user_token"key present. If so, there is a logged in user and you can use theredirect` function to do a redirect.

Where Next?

Popular Pragmatic Bookshelf topics Top

abtin
page 20: … protoc command… I had to additionally run the following go get commands in order to be able to compile protobuf code using go...
New
GilWright
Working through the steps (checking that the Info,plist matches exactly), run the demo game and what appears is grey but does not fill th...
New
simonpeter
When I try the command to create a pair of migration files I get an error. user=> (create-migration "guestbook") Execution error (Ill...
New
gilesdotcodes
In case this helps anyone, I’ve had issues setting up the rails source code. Here were the solutions: In Gemfile, change gem 'rails' t...
New
jskubick
I think I might have found a problem involving SwitchCompat, thumbTint, and trackTint. As entered, the SwitchCompat changes color to hol...
New
jskubick
I found an issue in Chapter 7 regarding android:backgroundTint vs app:backgroundTint. How to replicate: load chapter-7 from zipfile i...
New
brunogirin
When installing Cards as an editable package, I get the following error: ERROR: File “setup.py” not found. Directory cannot be installe...
New
dsmith42
Hey there, I’m enjoying this book and have learned a few things alredayd. However, in Chapter 4 I believe we are meant to see the “>...
New
akraut
The markup used to display the uploaded image results in a Phoenix.LiveView.HTMLTokenizer.ParseError error. lib/pento_web/live/product_l...
New
AufHe
I’m a newbie to Rails 7 and have hit an issue with the bin/Dev script mentioned on pages 112-113. Iteration A1 - Seeing the list of prod...
New

Other popular topics Top

PragmaticBookshelf
Machine learning can be intimidating, with its reliance on math and algorithms that most programmers don't encounter in their regular wor...
New
DevotionGeo
I know that -t flag is used along with -i flag for getting an interactive shell. But I cannot digest what the man page for docker run com...
New
AstonJ
Continuing the discussion from Thinking about learning Crystal, let’s discuss - I was wondering which languages don’t GC - maybe we can c...
New
PragmaticBookshelf
Build efficient applications that exploit the unique benefits of a pure functional language, learning from an engineer who uses Haskell t...
New
PragmaticBookshelf
Author Spotlight Jamis Buck @jamis This month, we have the pleasure of spotlighting author Jamis Buck, who has written Mazes for Prog...
New
PragmaticBookshelf
Author Spotlight Mike Riley @mriley This month, we turn the spotlight on Mike Riley, author of Portable Python Projects. Mike’s book ...
New
New
PragmaticBookshelf
Overarching tutorial for Python beginner and intermediate developers that teaches web development with the Flask framework. Miguel Gr...
New
PragmaticBookshelf
Escape callback hell and ship fast, clean code that reads as smoothly as it runs. Squash bugs and stamp out memory leaks with an intuitiv...
New
Fl4m3Ph03n1x
Background Lately I am in a quest to find a good quality TTS ai generation tool to run locally in order to create audio for some videos I...
New

Sub Categories: