2

I have an app where I broadcast some submissions for forms in the submission_controller, like this:

Formerer.Endpoint.broadcast("forms:#{form.id}", "new_submission", payload)

However, what I try to do now, is to make sure that only the current_user has access to the submissions broadcasted for its forms. (eg, current_user will have no way to see the submission for "forms:2" if form 2 belongs to another user).

I manage to do this in the channel join action by filtering the forms only for the user id which I assigned to the channel in the connect action:

user = Repo.get(Formerer.User, socket.assigns.user_id)

But for the broadcast I have no socket available.

My questions:

  1. Is there a way to find somehow the socket by the channel topic? something like:

    %Phoenix.Socket{assigns: %{user_id: user_id}, topic: "forms:1"} = ALL_OPEN_SOCKETS?!
    

After that I could just see if user_id == submission.user_id, and broadcast if true

  1. If that is not possible, what would be a best practice to do this, and to ensure only the current_user has access to their form submissions?
Soviut
  • 88,194
  • 49
  • 192
  • 260
iacobSon
  • 133
  • 10
  • Why you don't verify your submission from the client since you have already used `Endpoint.broadcast/3`.Like you can submit your `user_id` along with your `payload` in your submission_controller and then you verify it when broadcast the `payload` to the `form_channel` is listening `new_submission` event. – TheAnh Jul 17 '16 at 12:14
  • That means that the submission info will still be broadcasted. My dilema is how to stop them to be broadcasted at all if not the correct user. – iacobSon Jul 17 '16 at 20:28

1 Answers1

0

use the intercept api and create a handle_out function for the event. In the handle_out function you will have the socket. You can verify the user_id stored there. It its correct, push socket, event, message, otherwise do nothing except {:ok, socket}.

Edit

Here is a code example:

defmodule MyApp.Web.UserChannel do
  Use MyApp.Web, :channel

  intercept ["new_submission"]

  def handle_out("new_submission", msg, socket) do
    if msg[:user_id] == socket.assigns[:user_id] do
      push socket, "new_submission, msg
    end
    {:noreply, socket}
  end
end

Then you can just broadcast on the new_submission event anywhere and the socket will channel will take care of pushing the event out only three user defined in the payload.

Community
  • 1
  • 1
Steve Pallen
  • 4,417
  • 16
  • 33