current_user 在套接字上不可用,即使它是通过 `on_mount HealthTrackerWeb.UserLiveAuth` 分配的

问题描述 投票:0回答:1

我构建了一个简单的 CRUD 应用程序,可用于跟踪体重等健康指标。

我按照official guide从套接字访问

current_user
。 这让我可以在需要时随时联系
socket.assigns.current_user.id
。 但不幸的是,当我在“显示”模式中按“编辑”时,套接字不包含
current_user

此视图http://localhost:4000/weights/27/show/edit

这是来自日志:

[debug] HANDLE EVENT "save" in HealthTrackerWeb.WeightLive.Show
  Component: HealthTrackerWeb.WeightLive.FormComponent
  Parameters: %{"weight" => %{"weight" => "88888.1"}}
from show edit
socket:


#Phoenix.LiveView.Socket<
  id: "phx-F36nLW9MP7w9NQZk",
  endpoint: HealthTrackerWeb.Endpoint,
  view: HealthTrackerWeb.WeightLive.Show,
  parent_pid: nil,
  root_pid: #PID<0.2019.0>,
  router: HealthTrackerWeb.Router,
  assigns: %{
    __changed__: %{},
    action: :edit,
    flash: %{},
    form: %Phoenix.HTML.Form{
      source: #Ecto.Changeset<action: :validate, changes: %{}, errors: [],
       data: #HealthTracker.HealthStats.Weight<>, valid?: true>,
      impl: Phoenix.HTML.FormData.Ecto.Changeset,
      id: "weight",
      name: "weight",
      data: %HealthTracker.HealthStats.Weight{
        __meta__: #Ecto.Schema.Metadata<:loaded, "weights">,
        id: 27,
        weight: 88888.1,
        user_id: 1,
        inserted_at: ~N[2023-08-26 04:35:49],
        updated_at: ~N[2023-08-26 04:35:58]
      },
      hidden: [id: 27],
      params: %{"weight" => "88888.1"},
      errors: [],
      options: [method: "put"],
      index: nil,
      action: nil
    },
    id: 27,
    myself: %Phoenix.LiveComponent.CID{cid: 1},
    patch: "/weights/27",
    title: "Edit Weight",
    weight: %HealthTracker.HealthStats.Weight{
      __meta__: #Ecto.Schema.Metadata<:loaded, "weights">,
      id: 27,
      weight: 88888.1,
      user_id: 1,
      inserted_at: ~N[2023-08-26 04:35:49],
      updated_at: ~N[2023-08-26 04:35:58]
    }
  },
[error] GenServer #PID<0.2019.0> terminating
** (KeyError) key :current_user not found in: %{__changed__: %{}, action: :edit, flash: %{}, form: %Phoenix.HTML.Form{source: #Ecto.Changeset<action: :validate, changes: %{}, errors: [], data: #HealthTracker.Health
Stats.Weight<>, valid?: true>, impl: Phoenix.HTML.FormData.Ecto.Changeset, id: "weight", name: "weight", data: %HealthTracker.HealthStats.Weight{__meta__: #Ecto.Schema.Metadata<:loaded, "weights">, id: 27, weight:
88888.1, user_id: 1, inserted_at: ~N[2023-08-26 04:35:49], updated_at: ~N[2023-08-26 04:35:58]}, hidden: [id: 27], params: %{"weight" => "88888.1"}, errors: [], options: [method: "put"], index: nil, action: nil}, i
d: 27, myself: %Phoenix.LiveComponent.CID{cid: 1}, patch: "/weights/27", title: "Edit Weight", weight: %HealthTracker.HealthStats.Weight{__meta__: #Ecto.Schema.Metadata<:loaded, "weights">, id: 27, weight: 88888.1,
 user_id: 1, inserted_at: ~N[2023-08-26 04:35:49], updated_at: ~N[2023-08-26 04:35:58]}}
    (health_tracker 0.1.0) lib/health_tracker_web/live/weight_live/form_component.ex:57: HealthTrackerWeb.WeightLive.FormComponent.handle_event/3
    (phoenix_live_view 0.19.5) lib/phoenix_live_view/channel.ex:630: anonymous fn/4 in Phoenix.LiveView.Channel.inner_component_handle_event/4
    (telemetry 1.2.1) /Users/martins/Work/Elixir/health_tracker/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
    (phoenix_live_view 0.19.5) lib/phoenix_live_view/diff.ex:204: Phoenix.LiveView.Diff.write_component/4
    (phoenix_live_view 0.19.5) lib/phoenix_live_view/channel.ex:553: Phoenix.LiveView.Channel.component_handle_event/6
    (stdlib 4.3) gen_server.erl:1123: :gen_server.try_dispatch/4
    (stdlib 4.3) gen_server.erl:1200: :gen_server.handle_msg/6
    (stdlib 4.3) proc_lib.erl:250: :proc_lib.wake_up/3
Last message: %Phoenix.Socket.Message{topic: "lv:phx-F36nLW9MP7w9NQZk", event: "event", payload: %{"cid" => 1, "event" => "save", "type" => "form", "value" => "weight%5Bweight%5D=88888.1"}, ref: "32", join_ref: "10
"}

[debug] MOUNT HealthTrackerWeb.WeightLive.Show
  Parameters: %{"id" => "27"}
  Session: %{"_csrf_token" => "BVgDB44u3_rdNtmnVSmgDpcq", "live_socket_id" => "users_sessions:J5U-KzfYHgC1dspOxhvXVQcGVtH4DjIl19_-Tz8NXMY=", "user_token" => <<39, 149, 62, 43, 55, 216, 30, 0, 181, 118, 202, 78, 198
, 27, 215, 85, 7, 6, 86, 209, 248, 14, 50, 37, 215, 223, 254, 79, 63, 13, 92, 198>>}
[debug] QUERY OK source="users_tokens" db=0.5ms idle=815.7ms
SELECT u1."id", u1."email", u1."hashed_password", u1."confirmed_at", u1."inserted_at", u1."updated_at" FROM "users_tokens" AS u0 INNER JOIN "users" AS u1 ON u1."id" = u0."user_id" WHERE ((u0."token" = $1) AND (u0."
context" = $2)) AND (u0."inserted_at" > $3::timestamp + (-(60)::numeric * interval '1 day')) [<<39, 149, 62, 43, 55, 216, 30, 0, 181, 118, 202, 78, 198, 27, 215, 85, 7, 6, 86, 209, 248, 14, 50, 37, 215, 223, 254, 7
9, 63, 13, 92, 198>>, "session", ~U[2023-08-26 05:35:40.069525Z]]
↳ Phoenix.LiveView.Utils.assign_new/3, at: lib/phoenix_live_view/utils.ex:79



 ITS RUNNING



UserLiveAuth.on_mount/4: socket:
#Phoenix.LiveView.Socket<
  id: "phx-F36nLW9MP7w9NQZk",
  endpoint: HealthTrackerWeb.Endpoint,
  view: HealthTrackerWeb.WeightLive.Show,
  parent_pid: nil,
  root_pid: #PID<0.2032.0>,
  router: HealthTrackerWeb.Router,
  assigns: %{
    __changed__: %{current_user: true},
    current_user: #HealthTracker.Accounts.User<
      __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
      id: 1,
      email: "[email protected]",
      confirmed_at: nil,
      inserted_at: ~N[2023-08-01 06:30:14],
      updated_at: ~N[2023-08-01 06:30:14],
      ...
    >,
    flash: %{},
    live_action: :edit
  },
  transport_pid: #PID<0.2013.0>,
  ...

我不明白为什么 current_user 被

on_mount()
分配给套接字,但当我从模式触发保存时不可用。

已分配 current_user 的套接字的 ID 与未分配 current_user 的套接字的 ID 相同。

请参阅我的代码https://github.com/stabenfeldt/HealthTracker

elixir phoenix-framework phoenix-live-view
1个回答
0
投票

已生成的

user_auth.ex
文件提供了一些帮助程序,因为
user_token
存储在会话内。

...
  def on_mount(:mount_current_user, _params, session, socket) do
    {:cont, mount_current_user(socket, session)}
  end

  def on_mount(:ensure_authenticated, _params, session, socket) do
    socket = mount_current_user(socket, session)

    if socket.assigns.current_user do
      {:cont, socket}
    else
      socket =
        socket
        |> Phoenix.LiveView.put_flash(:error, "You must log in to access this page.")
        |> Phoenix.LiveView.redirect(to: ~p"/users/log_in")

      {:halt, socket}
    end
  end

...

  defp mount_current_user(socket, session) do
    Phoenix.Component.assign_new(socket, :current_user, fn ->
      if user_token = session["user_token"] do
        Accounts.get_user_by_session_token(user_token)
      end
    end)
  end
...

使用这些助手的最佳方式就在里面

router.ex

...
  scope "/", PicChatWeb do
    pipe_through [:browser, :require_authenticated_user]

    live_session :protected_messages,
      on_mount: [
        {PicChatWeb.UserAuth, :ensure_authenticated},
        {PicChatWeb.UserAuth, :require_user_owns_message}
      ] do
      live "/messages/new", MessageLive.Index, :new
      live "/messages/:id/edit", MessageLive.Index, :edit
      live "/messages/:id/show/edit", MessageLive.Show, :edit
    end
  end

  scope "/", PicChatWeb do
    pipe_through :browser

    get "/", PageController, :home

    live_session :messages, on_mount: [{PicChatWeb.UserAuth, :mount_current_user}] do
      live "/messages", MessageLive.Index, :index
      live "/messages/:id", MessageLive.Show, :show
    end
  end
...
© www.soinside.com 2019 - 2024. All rights reserved.