diff --git a/apps/fg_http/lib/fg_http/devices/device.ex b/apps/fg_http/lib/fg_http/devices/device.ex index b77e71f6e..2d810d2d4 100644 --- a/apps/fg_http/lib/fg_http/devices/device.ex +++ b/apps/fg_http/lib/fg_http/devices/device.ex @@ -11,6 +11,8 @@ defmodule FgHttp.Devices.Device do schema "devices" do field :name, :string field :public_key, :string + field :server_pubkey, :string, virtual: true + field :private_key, :string, virtual: true field :ifname, :string field :last_ip, EctoNetwork.INET field :last_seen_at, :utc_datetime_usec @@ -25,5 +27,6 @@ defmodule FgHttp.Devices.Device do device |> cast(attrs, [:last_ip, :ifname, :user_id, :name, :public_key]) |> validate_required([:user_id, :ifname, :name, :public_key]) + |> unique_constraint([:name]) end end diff --git a/apps/fg_http/lib/fg_http_web/controllers/device_controller.ex b/apps/fg_http/lib/fg_http_web/controllers/device_controller.ex index 27499b230..d45210d36 100644 --- a/apps/fg_http/lib/fg_http_web/controllers/device_controller.ex +++ b/apps/fg_http/lib/fg_http_web/controllers/device_controller.ex @@ -5,7 +5,6 @@ defmodule FgHttpWeb.DeviceController do use FgHttpWeb, :controller alias FgHttp.{Devices, Devices.Device} - alias Phoenix.PubSub plug FgHttpWeb.Plugs.SessionLoader @@ -20,22 +19,17 @@ defmodule FgHttpWeb.DeviceController do end def create(conn, %{"device" => %{"public_key" => _public_key} = device_params}) do + # XXX: Get device name from browser our_params = %{ "user_id" => conn.assigns.session.id, - "name" => "Default", - "ifname" => "wg0" + "ifname" => "wg0", + "name" => "Device #{DateTime.utc_now() |> DateTime.to_unix(:microsecond)}" } all_params = Map.merge(device_params, our_params) case Devices.create_device(all_params) do - {:ok, device} -> - PubSub.broadcast( - :fg_http_pub_sub, - "config", - {:verify_device, device.public_key} - ) - + {:ok, _device} -> redirect(conn, to: Routes.device_path(conn, :index)) {:error, %Ecto.Changeset{} = changeset} -> diff --git a/apps/fg_http/lib/fg_http_web/live/new_device_live.ex b/apps/fg_http/lib/fg_http_web/live/new_device_live.ex index 181e7f495..bfa4ae962 100644 --- a/apps/fg_http/lib/fg_http_web/live/new_device_live.ex +++ b/apps/fg_http/lib/fg_http_web/live/new_device_live.ex @@ -11,32 +11,47 @@ defmodule FgHttpWeb.NewDeviceLive do @doc """ Called when the view mounts. The for a device being added goes like follows: - 1. Present QR code to user - 2. User's device connects, :device_connected is received from the FgVpn application - 3. User confirms device, :verify_device message is broadcasted - 4. FgVpn receives :verify_device and adds the device to the config file + 1. :add_device is broadcasted + 2. FgVpn picks this up and creates a new peer, adds to config, broadcasts :peer_added + 3. :peer_added is handled here which confirms the details to the user + 4. User confirms device, clicks create + # XXX: Add ttl to device creation that removes stale devices """ @impl true def mount(_params, %{"user_id" => user_id}, socket) do if connected?(socket) do # Subscribe to :device_connected events PubSub.subscribe(:fg_http_pub_sub, "view") - # :timer.send_after(@mocked_timer, self(), {:pubkey, FgCrypto.rand_string()}) end + # Fire off event to generate private key, psk, and add device to config + PubSub.broadcast(:fg_http_pub_sub, "config", {:add_device, self()}) + device = %Device{user_id: user_id} {:ok, assign(socket, :device, device)} end @doc """ - Handles device connect. + Handles device added. """ @impl true - def handle_info({:device_connected, pubkey}, socket) do - device = %{socket.assigns.device | public_key: pubkey, last_ip: "127.0.0.1"} + def handle_info({:peer_added, caller_pid, privkey, pubkey, server_pubkey}, socket) do + if caller_pid == self() do + device = %{ + socket.assigns.device + | public_key: pubkey, + private_key: privkey, + server_pubkey: server_pubkey, + last_ip: "127.0.0.1", + name: "Device #{pubkey}" + } - # Updates @device in the LiveView and causes re-render - {:noreply, assign(socket, :device, device)} + # Updates @device in the LiveView and causes re-render if the intended target is this pid + {:noreply, assign(socket, :device, device)} + else + # Noop, let the correct pid handle this broadcast + {:noreply, socket} + end end end diff --git a/apps/fg_http/lib/fg_http_web/live/new_device_live.html.leex b/apps/fg_http/lib/fg_http_web/live/new_device_live.html.leex index 19a201b34..2bad7fa08 100644 --- a/apps/fg_http/lib/fg_http_web/live/new_device_live.html.leex +++ b/apps/fg_http/lib/fg_http_web/live/new_device_live.html.leex @@ -1,46 +1,45 @@ -
-
-[Peer]
-PublicKey = <%= Application.fetch_env!(:fg_vpn, :pubkey) %>
-AllowedIPs = 0.0.0.0/0, ::/0
-Endpoint = <%= Application.fetch_env!(:fg_http, :vpn_endpoint) %>
-
-
- + <%= link "Back to Devices", to: Routes.device_path(@socket, :index) %> +
+<% else %> +
+
+ [Interface]
+ PrivateKey = <%= @device.private_key %>
-
-
- <%= unless @device.public_key do %>
-
- Waiting for device connection...
-
-
-
-
-
- When we receive a connection from your device, we'll prompt you verify it here.
+ [Peer]
+ PublicKey = <%= @device.server_pubkey %>
+ AllowedIPs = 0.0.0.0/0, ::/0
+ Endpoint = <%= Application.fetch_env!(:fg_http, :vpn_endpoint) %>
+
+
+
+
+
+ Or scan the QR code with your mobile phone:
+
+
+
-
- <%= link "Back to Devices", to: Routes.device_path(@socket, :index) %>
-
- <% else %>
- Device connected!
+
+
+
+
+ Device added!
- Device Public Key:
@@ -49,7 +48,6 @@ Endpoint = <%= Application.fetch_env!(:fg_http, :vpn_endpoint) %>
- <%= @device.last_ip %>
- <%# XXX: Use the public key sent by the actual device and not the one here %>
<%=
@@ -65,6 +63,6 @@ Endpoint = <%= Application.fetch_env!(:fg_http, :vpn_endpoint) %>
<% end %>
- <% end %>
+
-