aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2018-09-26 15:59:22 +0200
committerAlex Auvolat <alex@adnab.me>2018-09-26 15:59:22 +0200
commit1a13285971ef728109011a93e676e26248b30242 (patch)
treef03467bc07ff84961f8c3eb88497adaf36b5f009
parent7d0009d83c9b5c747d4adb535817924762429f30 (diff)
downloadshard-1a13285971ef728109011a93e676e26248b30242.tar.gz
shard-1a13285971ef728109011a93e676e26248b30242.zip
Fixes
-rw-r--r--shard/lib/app/chat.ex10
-rw-r--r--shard/lib/app/pagestore.ex14
-rw-r--r--shard/lib/keys.ex9
-rw-r--r--shardweb/assets/js/socket.js3
-rw-r--r--shardweb/lib/shard_web/channels/room_channel.ex1
-rw-r--r--shardweb/lib/shard_web/channels/user_socket.ex16
-rw-r--r--shardweb/lib/shard_web/controllers/room_controller.ex10
7 files changed, 53 insertions, 10 deletions
diff --git a/shard/lib/app/chat.ex b/shard/lib/app/chat.ex
index c7df62e..52ad920 100644
--- a/shard/lib/app/chat.ex
+++ b/shard/lib/app/chat.ex
@@ -51,9 +51,17 @@ defmodule SApp.Chat do
:ok ->
Shard.Manager.dispatch_to(id, nil, self())
{:ok, page_store} = SApp.PageStore.start_link(id, :page_store)
+ root = Shard.Manager.load_state id
+ root = cond do
+ root == nil -> nil
+ GenServer.call(page_store, {:have_rec, root}) -> root
+ true ->
+ Logger.warn "Not all pages for saved root were saved, restarting from an empty state!"
+ nil
+ end
mst = %MST{store: %SApp.PageStore{pid: page_store},
cmp: &msg_cmp/2,
- root: Shard.Manager.load_state(id)}
+ root: root}
GenServer.cast(self(), :init_pull)
{:ok,
%{channel: channel,
diff --git a/shard/lib/app/pagestore.ex b/shard/lib/app/pagestore.ex
index 7962084..f093ed4 100644
--- a/shard/lib/app/pagestore.ex
+++ b/shard/lib/app/pagestore.ex
@@ -66,6 +66,10 @@ defmodule SApp.PageStore do
{:reply, hash, state}
end
+ def handle_call({:have_rec, root}, _from, state) do
+ {:reply, have_rec(state, root), state}
+ end
+
defp add_request(state, key, from) do
reqs_key = case state.reqs[key] do
nil ->
@@ -89,6 +93,16 @@ defmodule SApp.PageStore do
end
end
+ defp have_rec(state, root) do
+ case :dets.lookup state.store, root do
+ [{_, _, bin}] ->
+ pg = SData.term_unbin bin
+ pg |> SData.Page.refs |> Enum.map(&(have_rec(state, &1))) |> Enum.all?
+ _ ->
+ false
+ end
+ end
+
defp init_rec_pull(state, key, why, prefer_ask) do
case prefer_ask do
[_|_] ->
diff --git a/shard/lib/keys.ex b/shard/lib/keys.ex
index de054e1..b6ff461 100644
--- a/shard/lib/keys.ex
+++ b/shard/lib/keys.ex
@@ -72,7 +72,7 @@ defmodule Shard.Keys do
List the public keys of all identities for which we have a secret key
"""
def list_identities() do
- for [{pk, _sk}] <- :dets.match(@key_db, :"$1"), do: pk
+ for [pk, _sk] <- :dets.match(@key_db, {:"$1", :"$2"}), do: pk
end
@doc"""
@@ -103,6 +103,13 @@ defmodule Shard.Keys do
end
end
+ def have_sk?(pk) do
+ case :dets.lookup @key_db, pk do
+ [{^pk, _sk}] -> true
+ _ -> false
+ end
+ end
+
@doc"""
Lookup the secret key for a pk and generate a detached signature for a message.
diff --git a/shardweb/assets/js/socket.js b/shardweb/assets/js/socket.js
index 5088721..4c340f0 100644
--- a/shardweb/assets/js/socket.js
+++ b/shardweb/assets/js/socket.js
@@ -5,7 +5,8 @@
// and connect at the socket path in "lib/web/endpoint.ex":
import {Socket} from "phoenix"
-let socket = new Socket("/socket", {params: {token: window.userToken}})
+let pk = window.Gon.getAsset('pk');
+let socket = new Socket("/socket", {params: {token: window.userToken, pk: pk}})
// When you connect, you'll often need to authenticate the client.
// For example, imagine you have an authentication plug, `MyAuth`,
diff --git a/shardweb/lib/shard_web/channels/room_channel.ex b/shardweb/lib/shard_web/channels/room_channel.ex
index 2935c45..f582e06 100644
--- a/shardweb/lib/shard_web/channels/room_channel.ex
+++ b/shardweb/lib/shard_web/channels/room_channel.ex
@@ -16,7 +16,6 @@ defmodule ShardWeb.RoomChannel do
pid
end
socket = assign(socket, :pid, pid)
- socket = assign(socket, :pk, Shard.Keys.get_any_identity) # TODO same as in session!
GenServer.cast(pid, {:subscribe, self()})
send(self(), :after_join)
diff --git a/shardweb/lib/shard_web/channels/user_socket.ex b/shardweb/lib/shard_web/channels/user_socket.ex
index 4fb76dc..a3aa1a5 100644
--- a/shardweb/lib/shard_web/channels/user_socket.ex
+++ b/shardweb/lib/shard_web/channels/user_socket.ex
@@ -1,6 +1,8 @@
defmodule ShardWeb.UserSocket do
use Phoenix.Socket
+ require Logger
+
## Channels
channel "room:*", ShardWeb.RoomChannel
@@ -19,8 +21,18 @@ defmodule ShardWeb.UserSocket do
#
# See `Phoenix.Token` documentation for examples in
# performing token verification on connect.
- def connect(_params, socket) do
- {:ok, socket}
+ def connect(params, socket) do
+ case Base.decode16(params["pk"]) do
+ {:ok, pk} ->
+ if Shard.Keys.have_sk? pk do
+ socket = assign(socket, :pk, pk)
+ {:ok, socket}
+ else
+ Logger.warn("Invalid pk at user_socket.connect... #{params["pk"]}")
+ :error
+ end
+ _ -> :error
+ end
end
# Socket id's are topics that allow you to identify all sockets for a given user:
diff --git a/shardweb/lib/shard_web/controllers/room_controller.ex b/shardweb/lib/shard_web/controllers/room_controller.ex
index 48ba2a4..8c98aa6 100644
--- a/shardweb/lib/shard_web/controllers/room_controller.ex
+++ b/shardweb/lib/shard_web/controllers/room_controller.ex
@@ -5,18 +5,20 @@ defmodule ShardWeb.RoomController do
import PhoenixGon.Controller
def show(conn, %{"room" => room}) do
- {pk, conn} = case get_session(conn, :pk) do
- nil ->
+ pk = get_session(conn, :pk)
+ {pk, conn} = cond do
+ pk == nil || not Shard.Keys.have_sk? pk ->
pk = Shard.Keys.get_any_identity
conn = put_session(conn, :pk, pk)
{pk, conn}
- x ->
- {x, conn}
+ true ->
+ {pk, conn}
end
name = SApp.Identity.get_nick pk
conn = put_gon(conn, chat_room: room)
+ conn = put_gon(conn, pk: (pk|>Base.encode16))
render conn, "show.html",
room: room,
pk: pk,