我正在开发的 Phoenix 应用程序创建对文档更改的订阅,只要该文档是“公共的”。但是,如果有人将他们的文档更改为“私人”,我不希望这些订阅继续接收更新。
我知道如何防止在私人文档上创建新订阅,但我不确定如何从服务器端禁用预先存在的订阅?
我正在开发的 Phoenix 应用程序创建对文档更改的订阅,只要该文档是“公共的”。但是,如果有人将他们的文档更改为“私人”,我不希望这些订阅继续接收更新。
我知道如何防止在私人文档上创建新订阅,但我不确定如何从服务器端禁用预先存在的订阅?
您需要为与特定用户对应的每个套接字分配一个 ID。然后你可以这样做:
MyAppWeb.Endpoint.broadcast(socket_id, "disconnect", %{})
要将 ID 分配给套接字,请找到执行此操作的模块:
use Absinthe.Phoenix.Socket,
schema: MyAppWeb.Schema
大概在lib/my_app_web/channels/user_socket.ex
.
在那个“socket”模块中,你可以像这样编写你的 ID 回调:
@impl true
def id(%{
assigns: %{
absinthe: %{
opts: [
context: %{current_user: current_user}
]
}
}
}),
do: socket_id_for_user(current_user)
def id(_socket), do: nil
def socket_id_for_user(%{id: id}), do: "user_socket:#{id}"
现在您只需要确保此current_user
分配在您的套接字上。
首先,转到您的路由器并将这条线放在任何需要它的管道中(通常只是:api
管道,有时是:browser
管道):
plug :fetch_current_user
在您的路由器中(或在您喜欢的导入模块中),编写此函数:
def fetch_current_user(conn, _opts) do
# I don't know how you do auth so get your user your own way.
# For me, it usually involves finding their session token in the DB.
user = get_user_from_conn(conn)
context = if is_nil(user), do: %{}, else: %{current_user: user}
conn
|> Absinthe.Plug.assign_context(context)
end
你可能想在这个函数中做其他事情。例如,如果您使用phx_gen_auth
,您可能会将 user_token 放在私有分配中。
您现在遇到的主要问题是,如果您通过此套接字发送注销突变,您将在发送响应之前关闭它。很有趣的问题。
正如这里所讨论的:https ://elixirforum.com/t/is-there-a-way-to-force-disconnect-an-absinthe-graphql-subscription-from-the-server-side/41042 我的方法不允许您终止特定描述。我所描述的是一种终止整个套接字的方法。使用这种方法,如果需要,客户端将不得不创建一个新的“未经身份验证的”套接字。