Repository: phoenixframework/phoenix
Pull request #3746 (2020-04-05 19:33:10)

token salt can be treated as namespace
Improves the documentation about token generation.

First time I read the documentation about `Phoenix.Token` and saw the
`salt`, I become clear to me stat salt should be some kind of
randomly generated string.

After exploring the codebase and [researching the
internet](https://elixirforum.com/t/how-is-phoenix-token-different-from-jwt/2349/5)
I found out my code readability can be improved by replacing randomly generated string with a description of the token namespace.

I think this change will help improve the usability of the `Phoenix.Token` module by hinting that salt can be namespace as well.

I found `user_salt` variable a little bit confusing because a user doesn't have salt and if it has, it'll be some randomly generated string for password hashing which is not the case for `Phoenix.Token`.

I would like to propose the change of argument naming from `salt` to
`namespace` to completely remove thoughts about `salt` as a randomly generated string.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 701d83df3..e6c8ee234 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,8 @@ Phoenix built-in guides have been restructured and revamped, providing a better
   * [ConnTest] `use Phoenix.ConnTest` is deprecated in favor of `import Plug.Conn; import Phoenix.ConnTest`
   * [Endpoint] The outdated `Phoenix.Endpoint.CowboyAdapter` for Cowboy 1 is deprecated. Please make sure `{:plug_cowboy, "~> 2.1"}` or later is listed in your `mix.exs`
   * [Endpoint] `subscribe` and `unsubscribe` via the endpoint is deprecated, please use `Phoenix.PubSub` directly instead
+  * [Endpoint] `Phoenix.Endpoint.instrument/4` is deprecated and has no effect. Use `:telemetry` instead. See `Phoenix.Logger` for more information
+  * [Endpoint] The `:pubsub` key for endpoint is deprecated. Once you start your app, you will see step-by-step instructions on how to use the new PubSub config
   * [Layout] Use `<%= @inner_content %>` instead of `<%= render @view_module, @view_template, assigns %>` for rendering the child layout
 
 ### phx.new installer
diff --git a/installer/lib/phx_new/single.ex b/installer/lib/phx_new/single.ex
index b4f37ee4e..2360573a8 100644
--- a/installer/lib/phx_new/single.ex
+++ b/installer/lib/phx_new/single.ex
@@ -50,7 +50,7 @@ defmodule Phx.New.Single do
 
   template :live, [
     {:eex, "phx_live/templates/layout/root.html.leex",       :project, "lib/:lib_web_name/templates/layout/root.html.leex"},
-    {:eex, "phx_live/templates/layout/app.html.leex",        :project, "lib/:lib_web_name/templates/layout/app.html.leex"},
+    {:eex, "phx_live/templates/layout/app.html.leex",        :project, "lib/:lib_web_name/templates/layout/app.html.eex"},
     {:eex, "phx_live/templates/layout/live.html.leex",       :project, "lib/:lib_web_name/templates/layout/live.html.leex"},
     {:eex, "phx_web/views/layout_view.ex",                   :project, "lib/:lib_web_name/views/layout_view.ex"},
     {:eex, "phx_live/live/page_live.ex",                     :project, "lib/:lib_web_name/live/page_live.ex"},
diff --git a/installer/lib/phx_new/web.ex b/installer/lib/phx_new/web.ex
index 11192f5ad..525d5318a 100644
--- a/installer/lib/phx_new/web.ex
+++ b/installer/lib/phx_new/web.ex
@@ -51,7 +51,7 @@ defmodule Phx.New.Web do
 
   template :live, [
     {:eex, "phx_live/templates/layout/root.html.leex", :web, "lib/:web_app/templates/layout/root.html.leex"},
-    {:eex, "phx_live/templates/layout/app.html.leex",  :web, "lib/:web_app/templates/layout/app.html.leex"},
+    {:eex, "phx_live/templates/layout/app.html.leex",  :web, "lib/:web_app/templates/layout/app.html.eex"},
     {:eex, "phx_live/templates/layout/live.html.leex", :web, "lib/:web_app/templates/layout/live.html.leex"},
     {:eex, "phx_web/views/layout_view.ex",             :web, "lib/:web_app/views/layout_view.ex"},
     {:eex, "phx_live/live/page_live.ex",               :web, "lib/:web_app/live/page_live.ex"},
diff --git a/installer/templates/phx_single/mix.exs b/installer/templates/phx_single/mix.exs
index e1bdba863..1d4d2565a 100644
--- a/installer/templates/phx_single/mix.exs
+++ b/installer/templates/phx_single/mix.exs
@@ -41,7 +41,7 @@ defmodule <%= app_module %>.MixProject do
       {:phoenix_ecto, "~> 4.1"},
       {:ecto_sql, "~> 3.4"},
       {<%= inspect adapter_app %>, ">= 0.0.0"},<% end %><%= if html do %><%= if live do %>
-      {:phoenix_live_view, "~> 0.10.0"},
+      {:phoenix_live_view, "~> 0.11.0"},
       {:floki, ">= 0.0.0", only: :test},<% end %><%= if dashboard do %>
       {:phoenix_live_dashboard, github: "phoenixframework/phoenix_live_dashboard"},<% end %>
       {:phoenix_html, "~> 2.11"},
diff --git a/installer/templates/phx_umbrella/apps/app_name_web/mix.exs b/installer/templates/phx_umbrella/apps/app_name_web/mix.exs
index afcce74a2..84f75607e 100644
--- a/installer/templates/phx_umbrella/apps/app_name_web/mix.exs
+++ b/installer/templates/phx_umbrella/apps/app_name_web/mix.exs
@@ -39,7 +39,7 @@ defmodule <%= web_namespace %>.MixProject do
     [
       <%= phoenix_dep %>,<%= if ecto do %>
       {:phoenix_ecto, "~> 4.0"},<% end %><%= if html do %><%= if live do %>
-      {:phoenix_live_view, "~> 0.10.0"},
+      {:phoenix_live_view, "~> 0.11.0"},
       {:floki, ">= 0.0.0", only: :test},<% end %><%= if dashboard do %>
       {:phoenix_live_dashboard, github: "phoenixframework/phoenix_live_dashboard"},<% end %>
       {:phoenix_html, "~> 2.11"},
diff --git a/lib/phoenix/controller.ex b/lib/phoenix/controller.ex
index 4a5d5b3b1..4058319c2 100644
--- a/lib/phoenix/controller.ex
+++ b/lib/phoenix/controller.ex
@@ -757,19 +757,7 @@ defmodule Phoenix.Controller do
     render(conn, view, template, [])
   end
 
-  @doc """
-  WARNING: This function is deprecated in favor of `render/3` + `put_view/2`.
-
-  A shortcut that renders the given template in the given view.
-
-  Equivalent to:
-
-      conn
-      |> put_view(view)
-      |> render(template, assigns)
-
-  """
-  @spec render(Plug.Conn.t, atom, atom | binary, Keyword.t | map) :: Plug.Conn.t
+  @doc false
   def render(conn, view, template, assigns)
       when is_atom(view) and (is_binary(template) or is_atom(template)) do
     IO.warn "#{__MODULE__}.render/4 with a view is deprecated, see the documentation for render/3 for an alternative"
diff --git a/lib/phoenix/endpoint.ex b/lib/phoenix/endpoint.ex
index 6a6cb8da0..489fea3c0 100644
--- a/lib/phoenix/endpoint.ex
+++ b/lib/phoenix/endpoint.ex
@@ -831,10 +831,8 @@ defmodule Phoenix.Endpoint do
   end
 
   @doc false
+  @deprecated "Phoenix.Endpoint.instrument/4 is deprecated and has no effect. Use :telemetry instead"
   defmacro instrument(_endpoint_or_conn_or_socket, _event, _runtime, _fun) do
-    IO.warn "Phoenix.Endpoint.instrument/4 is deprecated and has no effect. Use :telemetry instead",
-            Macro.Env.stacktrace(__CALLER__)
-
     :ok
   end
 
diff --git a/lib/phoenix/logger.ex b/lib/phoenix/logger.ex
index c8ac0bc9d..9f5ad8b57 100644
--- a/lib/phoenix/logger.ex
+++ b/lib/phoenix/logger.ex
@@ -11,15 +11,15 @@ defmodule Phoenix.Logger do
       endpoint at the beginning of every request.
       * Measurement: `%{time: System.monotonic_time}`
       * Metadata: `%{conn: Plug.Conn.t, options: Keyword.t}`
-      * Options: `%{log: Logger.level | false}`
-      * Disable logging: In your endpoint `plug Plug.Telemetry, ..., options: [log: false]`
+      * Options: `%{log: Logger.level}`
+      * Disable logging: Remove `plug Plug.Telemetry, ...` from your endpoint.ex
 
     * `[:phoenix, :endpoint, :stop]` - dispatched by `Plug.Telemetry` in your
       endpoint whenever the response is sent
       * Measurement: `%{duration: native_time}`
       * Metadata: `%{conn: Plug.Conn.t, options: Keyword.t}`
-      * Options: `%{log: Logger.level | false}`
-      * Disable logging: In your endpoint `plug Plug.Telemetry, ..., options: [log: false]`
+      * Options: `%{log: Logger.level}`
+      * Disable logging: Remove `plug Plug.Telemetry, ...` from your endpoint.ex
 
     * `[:phoenix, :router_dispatch, :start]` - dispatched by `Phoenix.Router`
       before dispatching to a matched route
diff --git a/lib/phoenix/socket.ex b/lib/phoenix/socket.ex
index 6edc0371c..a5fff3d6a 100644
--- a/lib/phoenix/socket.ex
+++ b/lib/phoenix/socket.ex
@@ -370,10 +370,9 @@ defmodule Phoenix.Socket do
   defp tear_alias(other), do: other
 
   @doc false
+  @deprecated "transport/3 in Phoenix.Socket is deprecated and has no effect"
   defmacro transport(_name, _module, _config \\ []) do
-    quote do
-      IO.warn "transport/3 in Phoenix.Socket is deprecated and has no effect"
-    end
+    :ok
   end
 
   defmacro __before_compile__(env) do
diff --git a/lib/phoenix/token.ex b/lib/phoenix/token.ex
index ff8705186..1ad231d96 100644
--- a/lib/phoenix/token.ex
+++ b/lib/phoenix/token.ex
@@ -15,8 +15,8 @@ defmodule Phoenix.Token do
   the id from a database. For example:
 
       iex> user_id = 1
-      iex> token = Phoenix.Token.sign(MyApp.Endpoint, "user salt", user_id)
-      iex> Phoenix.Token.verify(MyApp.Endpoint, "user salt", token, max_age: 86400)
+      iex> token = Phoenix.Token.sign(MyApp.Endpoint, "user auth", user_id)
+      iex> Phoenix.Token.verify(MyApp.Endpoint, "user auth", token, max_age: 86400)
       {:ok, 1}
 
   In that example we have a user's id, we generate a token and
@@ -38,8 +38,9 @@ defmodule Phoenix.Token do
 
   The second argument is a [cryptographic salt](https://en.wikipedia.org/wiki/Salt_(cryptography))
   which must be the same in both calls to `sign/4` and `verify/4`.
-  For instance, it may be called "user auth" when generating a token
-  that will be used to authenticate users on channels or on your APIs.
+  For instance, it may be called "user auth" and treated as namespace
+  when generating a token that will be used to authenticate users on
+  channels or on your APIs.
 
   The third argument can be any term (string, int, list, etc.)
   that you wish to codify into the token. Upon valid verification,
@@ -52,14 +53,14 @@ defmodule Phoenix.Token do
   One is via the meta tag:
 
       <%= tag :meta, name: "channel_token",
-                     content: Phoenix.Token.sign(@conn, "user salt", @current_user.id) %>
+                     content: Phoenix.Token.sign(@conn, "user auth", @current_user.id) %>
 
   Or an endpoint that returns it:
 
       def create(conn, params) do
         user = User.create(params)
         render(conn, "user.json",
-               %{token: Phoenix.Token.sign(conn, "user salt", user.id), user: user})
+               %{token: Phoenix.Token.sign(conn, "user auth", user.id), user: user})
       end
 
   Once the token is sent, the client may now send it back to the server
@@ -70,7 +71,7 @@ defmodule Phoenix.Token do
         use Phoenix.Socket
 
         def connect(%{"token" => token}, socket, _connect_info) do
-          case Phoenix.Token.verify(socket, "user salt", token, max_age: 86400) do
+          case Phoenix.Token.verify(socket, "user auth", token, max_age: 86400) do
             {:ok, user_id} ->
               socket = assign(socket, :user, Repo.get!(User, user_id))
               {:ok, socket}
@@ -145,8 +146,8 @@ defmodule Phoenix.Token do
 
       iex> user_id    = 99
       iex> secret     = "kjoy3o1zeidquwy1398juxzldjlksahdk3"
-      iex> user_salt  = "user salt"
-      iex> token      = Phoenix.Token.sign(secret, user_salt, user_id)
+      iex> namespace  = "user auth"
+      iex> token      = Phoenix.Token.sign(secret, namespace, user_id)
 
   The mechanism for passing the token to the client is typically through a
   cookie, a JSON response body, or HTTP header. For now, assume the client has
@@ -155,7 +156,7 @@ defmodule Phoenix.Token do
   When the server receives a request, it can use `verify/4` to determine if it
   should provide the requested resources to the client:
 
-      iex> Phoenix.Token.verify(secret, user_salt, token, max_age: 86400)
+      iex> Phoenix.Token.verify(secret, namespace, token, max_age: 86400)
       {:ok, 99}
 
   In this example, we know the client sent a valid token because `verify/4`
@@ -165,10 +166,10 @@ defmodule Phoenix.Token do
   However, if the client had sent an expired or otherwise invalid token
   `verify/4` would have returned an error instead:
 
-      iex> Phoenix.Token.verify(secret, user_salt, expired, max_age: 86400)
+      iex> Phoenix.Token.verify(secret, namespace, expired, max_age: 86400)
       {:error, :expired}
 
-      iex> Phoenix.Token.verify(secret, user_salt, invalid, max_age: 86400)
+      iex> Phoenix.Token.verify(secret, namespace, invalid, max_age: 86400)
       {:error, :invalid}
 
   ## Options
diff --git a/priv/templates/phx.gen.live/form.html.leex b/priv/templates/phx.gen.live/form.html.leex
index d7f827f3f..18b819e03 100644
--- a/priv/templates/phx.gen.live/form.html.leex
+++ b/priv/templates/phx.gen.live/form.html.leex
@@ -1,8 +1,7 @@
 <h2><%%= @title %></h2>
 
 <%%= f = form_for @changeset, "#",
-  id: "form-#{@id}",
-  phx_target: "#form-#{@id}",
+  phx_target: @myself,
   phx_change: "validate",
   phx_submit: "save" %>
 <%= for {label, input, error} <- inputs, input do %>
diff --git a/priv/templates/phx.gen.live/index.ex b/priv/templates/phx.gen.live/index.ex
index d6f65356d..abdae671b 100644
--- a/priv/templates/phx.gen.live/index.ex
+++ b/priv/templates/phx.gen.live/index.ex
@@ -5,32 +5,29 @@ defmodule <%= inspect context.web_module %>.<%= inspect Module.concat(schema.web
   alias <%= inspect schema.module %>
 
   def mount(_params, _session, socket) do
-    {:ok, socket}
+    {:ok, assign(socket, :<%= schema.plural %>, fetch_<%= schema.plural %>())}
   end
 
   def handle_params(params, _url, socket) do
-    {:noreply, handle_action(socket.assigns.live_action, params, socket)}
+    {:noreply, apply_action(socket, socket.assigns.live_action, params)}
   end
 
-  defp handle_action(:edit, %{"id" => id}, socket) do
+  defp apply_action(socket, :edit, %{"id" => id}) do
     socket
     |> assign(:page_title, "Edit <%= schema.human_singular %>")
     |> assign(:<%= schema.singular %>, <%= inspect context.alias %>.get_<%= schema.singular %>!(id))
-    |> assign_new(:<%= schema.plural %>, &fetch_<%= schema.plural %>/0)
   end
 
-  defp handle_action(:new, _params, socket) do
+  defp apply_action(socket, :new, _params) do
     socket
     |> assign(:page_title, "New <%= schema.human_singular %>")
     |> assign(:<%= schema.singular %>, %<%= inspect schema.alias %>{})
-    |> assign_new(:<%= schema.plural %>, &fetch_<%= schema.plural %>/0)
   end
 
-  defp handle_action(:index, _params, socket) do
+  defp apply_action(socket, :index, _params) do
     socket
     |> assign(:page_title, "Listing <%= schema.human_plural %>")
     |> assign(:<%= schema.singular %>, nil)
-    |> assign(:<%= schema.plural %>, fetch_<%= schema.plural %>())
   end
 
   def handle_event("delete", %{"id" => id}, socket) do
diff --git a/priv/templates/phx.gen.live/index.html.leex b/priv/templates/phx.gen.live/index.html.leex
index b209b4821..0c76852ca 100644
--- a/priv/templates/phx.gen.live/index.html.leex
+++ b/priv/templates/phx.gen.live/index.html.leex
@@ -17,9 +17,9 @@
       <th></th>
     </tr>
   </thead>
-  <tbody>
+  <tbody id="<%= schema.plural %>">
     <%%= for <%= schema.singular %> <- @<%= schema.plural %> do %>
-      <tr>
+      <tr id="<%= schema.singular %>-<%%= <%= schema.singular %>.id %>">
 <%= for {k, _} <- schema.attrs do %>        <td><%%= <%= schema.singular %>.<%= k %> %></td>
 <% end %>
         <td>
diff --git a/priv/templates/phx.gen.live/show.html.leex b/priv/templates/phx.gen.live/show.html.leex
index 254adef73..172b30e0c 100644
--- a/priv/templates/phx.gen.live/show.html.leex
+++ b/priv/templates/phx.gen.live/show.html.leex
@@ -18,5 +18,5 @@
 <% end %>
 </ul>
 
-<span><%%= live_patch "Edit", to: Routes.<%= schema.singular %>_show_path(@socket, :edit, @<%= schema.singular %>), class: "button", phx_disable_with: "loading..." %></span>
+<span><%%= live_patch "Edit", to: Routes.<%= schema.singular %>_show_path(@socket, :edit, @<%= schema.singular %>), class: "button" %></span>
 <span><%%= live_redirect "Back", to: Routes.<%= schema.singular %>_index_path(@socket, :index) %></span>


Test patch:
diff --git a/installer/templates/phx_test/live/page_live_test.exs b/installer/templates/phx_test/live/page_live_test.exs
index 08df863c7..75cf111d4 100644
--- a/installer/templates/phx_test/live/page_live_test.exs
+++ b/installer/templates/phx_test/live/page_live_test.exs
@@ -4,8 +4,8 @@ defmodule <%= web_namespace %>.PageLiveTest do
   import Phoenix.LiveViewTest
 
   test "disconnected and connected render", %{conn: conn} do
-    {:ok, page_live, disconneted_html} = live(conn, "/")
-    assert disconneted_html =~ "Welcome to Phoenix!"
+    {:ok, page_live, disconnected_html} = live(conn, "/")
+    assert disconnected_html =~ "Welcome to Phoenix!"
     assert render(page_live) =~ "Welcome to Phoenix!"
   end
 end
diff --git a/lib/phoenix/test/channel_test.ex b/lib/phoenix/test/channel_test.ex
index 042e27e60..6875928f1 100644
--- a/lib/phoenix/test/channel_test.ex
+++ b/lib/phoenix/test/channel_test.ex
@@ -241,14 +241,14 @@ defmodule Phoenix.ChannelTest do
   end
 
   @doc false
+  @deprecated "Phoenix.ChannelTest.socket/0 is deprecated, please call socket/1 instead"
   defmacro socket() do
-    IO.warn "Phoenix.ChannelTest.socket/0 is deprecated, please call socket/1 instead"
     build_socket(nil, nil, [], __CALLER__)
   end
 
   @doc false
+  @deprecated "Phoenix.ChannelTest.socket/2 is deprecated, please call socket/3 instead"
   defmacro socket(id, assigns) do
-    IO.warn "Phoenix.ChannelTest.socket/2 is deprecated, please call socket/3 instead"
     build_socket(nil, id, assigns, __CALLER__)
   end