diff options
| -rw-r--r-- | assets/src/components/Request.svelte | 21 | ||||
| -rw-r--r-- | assets/src/entries/request.ts | 9 | ||||
| -rw-r--r-- | assets/src/network/socket.ts | 15 | ||||
| -rw-r--r-- | assets/src/utils/getShareToken.ts | 4 | ||||
| -rw-r--r-- | lib/rook/application.ex | 3 | ||||
| -rw-r--r-- | lib/rook/request.ex | 77 | ||||
| -rw-r--r-- | lib/rook/share.ex | 7 | ||||
| -rw-r--r-- | lib/rook_web/channels/request_channel.ex | 20 | ||||
| -rw-r--r-- | lib/rook_web/channels/share_channel.ex | 4 | ||||
| -rw-r--r-- | lib/rook_web/channels/user_socket.ex | 1 | ||||
| -rw-r--r-- | lib/rook_web/controllers/app_controller.ex | 4 | ||||
| -rw-r--r-- | lib/rook_web/templates/app/request.html.eex | 8 |
12 files changed, 159 insertions, 14 deletions
diff --git a/assets/src/components/Request.svelte b/assets/src/components/Request.svelte new file mode 100644 index 0000000..134c4d5 --- /dev/null +++ b/assets/src/components/Request.svelte @@ -0,0 +1,21 @@ +<script lang="ts"> + import { getToken, joinRequestChannel } from "../network/socket"; + import getShareToken from "../utils/getShareToken"; + + const startConnection = async () => { + const token = await getToken(); + joinRequestChannel(token, getShareToken()); + }; + + startConnection(); +</script> + +<main> + <h1>Requesting</h1> +</main> + +<style> + h1 { + font-size: 4em; + } +</style> diff --git a/assets/src/entries/request.ts b/assets/src/entries/request.ts index 0d064a2..74f84da 100644 --- a/assets/src/entries/request.ts +++ b/assets/src/entries/request.ts @@ -1,3 +1,8 @@ -// Request +import Request from "../components/Request.svelte"; -export {}; +const app = new Request({ + target: document.getElementById("app"), + props: {}, +}); + +export default app; diff --git a/assets/src/network/socket.ts b/assets/src/network/socket.ts index c056b41..87f5b7c 100644 --- a/assets/src/network/socket.ts +++ b/assets/src/network/socket.ts @@ -23,11 +23,22 @@ export const getToken: () => Promise<string> = () => { export const joinShareChannel = token => { let shareChannel = socket.channel(`share:${token}`); - shareChannel.on("request", requests.addRequest); + shareChannel.on("new_request", requests.addRequest); shareChannel .join() .receive("error", err => - console.log("failed joining share channel:" + err) + console.log("Failed joining share channel: " + JSON.stringify(err)) + ); +}; + +export const joinRequestChannel = (token, share) => { + let requestChannel = socket.channel(`request:${token}`, { share }); + + requestChannel + .join() + .receive("ok", () => console.log("Connected to request!")) + .receive("error", err => + console.log("Failed joining request channel:" + JSON.stringify(err)) ); }; diff --git a/assets/src/utils/getShareToken.ts b/assets/src/utils/getShareToken.ts new file mode 100644 index 0000000..bfe6f58 --- /dev/null +++ b/assets/src/utils/getShareToken.ts @@ -0,0 +1,4 @@ +export default (): string => { + const splitPath = window.location.pathname.split("/"); + return splitPath[splitPath.length - 1]; +}; diff --git a/lib/rook/application.ex b/lib/rook/application.ex index 27879e3..537fe70 100644 --- a/lib/rook/application.ex +++ b/lib/rook/application.ex @@ -15,7 +15,8 @@ defmodule Rook.Application do RookWeb.Endpoint, # Start a worker by calling: Rook.Worker.start_link(arg) # {Rook.Worker, arg} - {Registry, keys: :unique, name: Registry.Share} + {Registry, keys: :unique, name: Registry.Share}, + {Registry, keys: :unique, name: Registry.Request} ] # See https://hexdocs.pm/elixir/Supervisor.html diff --git a/lib/rook/request.ex b/lib/rook/request.ex new file mode 100644 index 0000000..b795c5c --- /dev/null +++ b/lib/rook/request.ex @@ -0,0 +1,77 @@ +defmodule Rook.Request do + use GenServer + + defmodule State do + @type t :: %__MODULE__{ + token: String.t(), + share_token: String.t(), + channel_pid: pid() + } + + defstruct [:token, :share_token, :channel_pid] + end + + ## Client + + def init([token, share_token, channel_pid]) do + Process.flag(:trap_exit, true) + Process.link(channel_pid) + Rook.Share.new_request(share_token, token) + {:ok, %State{token: token, share_token: share_token, channel_pid: channel_pid}} + end + + def start(token, share_token) do + GenServer.start(__MODULE__, [token, share_token, self()], name: via(token)) + end + + def acknowledge_request(token) do + cast(token, {:request_acknowledged}) + end + + def close(request_token, share_token) do + Rook.Share.request_cancelled(share_token, request_token) + end + + def close(request_token) do + cast(request_token, {:share_cancelled}) + end + + def get(token) do + case Registry.lookup(Registry.Request, token) do + [{pid, _}] -> pid + _ -> nil + end + end + + def exists?(token) do + get(token) != nil + end + + ## Server + + def handle_cast({:request_acknowledged}, state) do + notify(state.token, "request_acknowledged", %{}) + {:noreply, state} + end + + def handle_cast({:share_cancelled}, state) do + notify(state.token, "share_cancelled", %{}) + {:stop, :shutdown, state} + end + + def handle_info({:EXIT, pid, reason}, state) do + if state.channel_pid == pid do + Rook.Request.close(state.token, state.share_token) + end + + {:stop, reason, state} + end + + ## Helpers + + defp via(name), do: {:via, Registry, {Registry.Request, name}} + defp cast(token, params), do: GenServer.cast(via(token), params) + + defp notify(token, event, params), + do: RookWeb.Endpoint.broadcast!("request:" <> token, event, params) +end diff --git a/lib/rook/share.ex b/lib/rook/share.ex index 17e680a..0d1d64c 100644 --- a/lib/rook/share.ex +++ b/lib/rook/share.ex @@ -27,13 +27,12 @@ defmodule Rook.Share do cast(share_token, {:new_request, request_token}) end - def cancel_request(share_token, request_token) do + def request_cancelled(share_token, request_token) do cast(share_token, {:request_cancelled, request_token}) end - def close(_requests) do - # TODO: Notify requestors - :ok + def close(requests) do + Enum.each(requests, &Rook.Request.close/1) end def get(token) do diff --git a/lib/rook_web/channels/request_channel.ex b/lib/rook_web/channels/request_channel.ex new file mode 100644 index 0000000..6290ae6 --- /dev/null +++ b/lib/rook_web/channels/request_channel.ex @@ -0,0 +1,20 @@ +defmodule RookWeb.RequestChannel do + use RookWeb, :channel + + def join("request:" <> token, %{"share" => share_token}, socket) do + if Rook.Token.match?(token, socket) do + if Rook.Share.exists?(share_token) do + Rook.Request.start(token, share_token) + {:ok, socket} + else + {:error, %{reason: "No such share exists."}} + end + else + {:error, %{reason: "Wrong token."}} + end + end + + def join("request:" <> _token, _params, _socket) do + {:error, %{reason: "No share given to request."}} + end +end diff --git a/lib/rook_web/channels/share_channel.ex b/lib/rook_web/channels/share_channel.ex index 2d99d87..0efb3ba 100644 --- a/lib/rook_web/channels/share_channel.ex +++ b/lib/rook_web/channels/share_channel.ex @@ -21,8 +21,8 @@ defmodule RookWeb.ShareChannel do {:error, %{reason: "No request given to accept."}} end - def handle_out("new_request", msg, socket) do - # TODO: Send ACK + def handle_out("new_request", %{request: request_token} = msg, socket) do + Rook.Request.acknowledge_request(request_token) push(socket, "new_request", msg) {:noreply, socket} end diff --git a/lib/rook_web/channels/user_socket.ex b/lib/rook_web/channels/user_socket.ex index ae82b6b..d6ce9c4 100644 --- a/lib/rook_web/channels/user_socket.ex +++ b/lib/rook_web/channels/user_socket.ex @@ -4,6 +4,7 @@ defmodule RookWeb.UserSocket do ## Channels channel "token", RookWeb.TokenChannel channel "share:*", RookWeb.ShareChannel + channel "request:*", RookWeb.RequestChannel # Socket params are passed from the client and can # be used to verify and authenticate a user. After diff --git a/lib/rook_web/controllers/app_controller.ex b/lib/rook_web/controllers/app_controller.ex index 9e36f3c..f252086 100644 --- a/lib/rook_web/controllers/app_controller.ex +++ b/lib/rook_web/controllers/app_controller.ex @@ -5,7 +5,7 @@ defmodule RookWeb.AppController do render(conn, "share.html") end - def request(conn, _params) do - render(conn, "request.html") + def request(conn, %{"token" => share_token}) do + render(conn, "request.html", share_token: share_token) end end diff --git a/lib/rook_web/templates/app/request.html.eex b/lib/rook_web/templates/app/request.html.eex index b7ff7bd..1e17e45 100644 --- a/lib/rook_web/templates/app/request.html.eex +++ b/lib/rook_web/templates/app/request.html.eex @@ -1 +1,7 @@ -<%= render_app(@conn, "request") %> +<%= if Rook.Share.exists?(@share_token) do %> + <%= render_app(@conn, "request") %> +<% else %> + <p> + The share you tried to request either expired or never existed. + </p> +<% end %> |
