From 1e91dc596fd2f7fdd96b7fd2fc50724f93e46529 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 12 Oct 2018 14:40:21 +0200 Subject: Move and reorganize some stuff --- shardweb/config/dev.exs | 4 +- shardweb/lib/channels/chat_channel.ex | 72 +++++++ shardweb/lib/channels/user_socket.ex | 49 +++++ shardweb/lib/controllers/chat_controller.ex | 13 ++ shardweb/lib/controllers/identity_controller.ex | 44 ++++ shardweb/lib/controllers/page_controller.ex | 31 +++ shardweb/lib/endpoint.ex | 59 ++++++ shardweb/lib/gettext.ex | 24 +++ shardweb/lib/router.ex | 56 +++++ shardweb/lib/shard_web.ex | 2 +- shardweb/lib/shard_web/channels/room_channel.ex | 72 ------- shardweb/lib/shard_web/channels/user_socket.ex | 49 ----- .../shard_web/controllers/identity_controller.ex | 40 ---- .../lib/shard_web/controllers/page_controller.ex | 27 --- .../lib/shard_web/controllers/room_controller.ex | 9 - shardweb/lib/shard_web/endpoint.ex | 59 ------ shardweb/lib/shard_web/gettext.ex | 24 --- shardweb/lib/shard_web/router.ex | 53 ----- .../lib/shard_web/templates/identity/view.html.eex | 59 ------ .../lib/shard_web/templates/layout/app.html.eex | 224 -------------------- .../shard_web/templates/layout/flashes.html.eex | 24 --- .../lib/shard_web/templates/page/index.html.eex | 47 ----- .../lib/shard_web/templates/room/show.html.eex | 36 ---- shardweb/lib/shard_web/views/error_helpers.ex | 44 ---- shardweb/lib/shard_web/views/error_view.ex | 16 -- shardweb/lib/shard_web/views/identity_view.ex | 11 - shardweb/lib/shard_web/views/layout_view.ex | 7 - shardweb/lib/shard_web/views/page_view.ex | 14 -- shardweb/lib/shard_web/views/room_view.ex | 3 - shardweb/lib/templates/chat/chat.html.eex | 37 ++++ shardweb/lib/templates/identity/list.html.eex | 32 +++ shardweb/lib/templates/identity/self.html.eex | 59 ++++++ shardweb/lib/templates/layout/app.html.eex | 227 +++++++++++++++++++++ shardweb/lib/templates/layout/flashes.html.eex | 24 +++ shardweb/lib/templates/page/peer_list.html.eex | 47 +++++ shardweb/lib/templates/page/shard_list.html.eex | 46 +++++ shardweb/lib/views/chat_view.ex | 3 + shardweb/lib/views/error_helpers.ex | 44 ++++ shardweb/lib/views/error_view.ex | 16 ++ shardweb/lib/views/identity_view.ex | 21 ++ shardweb/lib/views/layout_view.ex | 7 + shardweb/lib/views/page_view.ex | 18 ++ 42 files changed, 932 insertions(+), 821 deletions(-) create mode 100644 shardweb/lib/channels/chat_channel.ex create mode 100644 shardweb/lib/channels/user_socket.ex create mode 100644 shardweb/lib/controllers/chat_controller.ex create mode 100644 shardweb/lib/controllers/identity_controller.ex create mode 100644 shardweb/lib/controllers/page_controller.ex create mode 100644 shardweb/lib/endpoint.ex create mode 100644 shardweb/lib/gettext.ex create mode 100644 shardweb/lib/router.ex delete mode 100644 shardweb/lib/shard_web/channels/room_channel.ex delete mode 100644 shardweb/lib/shard_web/channels/user_socket.ex delete mode 100644 shardweb/lib/shard_web/controllers/identity_controller.ex delete mode 100644 shardweb/lib/shard_web/controllers/page_controller.ex delete mode 100644 shardweb/lib/shard_web/controllers/room_controller.ex delete mode 100644 shardweb/lib/shard_web/endpoint.ex delete mode 100644 shardweb/lib/shard_web/gettext.ex delete mode 100644 shardweb/lib/shard_web/router.ex delete mode 100644 shardweb/lib/shard_web/templates/identity/view.html.eex delete mode 100644 shardweb/lib/shard_web/templates/layout/app.html.eex delete mode 100644 shardweb/lib/shard_web/templates/layout/flashes.html.eex delete mode 100644 shardweb/lib/shard_web/templates/page/index.html.eex delete mode 100644 shardweb/lib/shard_web/templates/room/show.html.eex delete mode 100644 shardweb/lib/shard_web/views/error_helpers.ex delete mode 100644 shardweb/lib/shard_web/views/error_view.ex delete mode 100644 shardweb/lib/shard_web/views/identity_view.ex delete mode 100644 shardweb/lib/shard_web/views/layout_view.ex delete mode 100644 shardweb/lib/shard_web/views/page_view.ex delete mode 100644 shardweb/lib/shard_web/views/room_view.ex create mode 100644 shardweb/lib/templates/chat/chat.html.eex create mode 100644 shardweb/lib/templates/identity/list.html.eex create mode 100644 shardweb/lib/templates/identity/self.html.eex create mode 100644 shardweb/lib/templates/layout/app.html.eex create mode 100644 shardweb/lib/templates/layout/flashes.html.eex create mode 100644 shardweb/lib/templates/page/peer_list.html.eex create mode 100644 shardweb/lib/templates/page/shard_list.html.eex create mode 100644 shardweb/lib/views/chat_view.ex create mode 100644 shardweb/lib/views/error_helpers.ex create mode 100644 shardweb/lib/views/error_view.ex create mode 100644 shardweb/lib/views/identity_view.ex create mode 100644 shardweb/lib/views/layout_view.ex create mode 100644 shardweb/lib/views/page_view.ex (limited to 'shardweb') diff --git a/shardweb/config/dev.exs b/shardweb/config/dev.exs index f5d95e9..a7d4356 100644 --- a/shardweb/config/dev.exs +++ b/shardweb/config/dev.exs @@ -36,8 +36,8 @@ config :shardweb, ShardWeb.Endpoint, patterns: [ ~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$}, ~r{priv/gettext/.*(po)$}, - ~r{lib/shard_web/views/.*(ex)$}, - ~r{lib/shard_web/templates/.*(eex)$} + ~r{lib/views/.*(ex)$}, + ~r{lib/templates/.*(eex)$} ] ] diff --git a/shardweb/lib/channels/chat_channel.ex b/shardweb/lib/channels/chat_channel.ex new file mode 100644 index 0000000..3e51c3a --- /dev/null +++ b/shardweb/lib/channels/chat_channel.ex @@ -0,0 +1,72 @@ +defmodule ShardWeb.ChatChannel do + use ShardWeb, :channel + + require Logger + + def join("room:" <> room_name, payload, socket) do + if authorized?(payload) do + + pid = Shard.Manager.find_or_start %SApp.Chat.Manifest{channel: room_name} + socket = assign(socket, :pid, pid) + + GenServer.cast(pid, {:subscribe, self()}) + send(self(), :after_join) + + {:ok, socket} + else + {:error, %{reason: "unauthorized"}} + end + end + + def handle_info(:after_join, socket) do + GenServer.call(socket.assigns.pid, {:read_history, nil, 100}) + |> Enum.each(fn {{pk, msgbin, _sign}, true} -> + {_ts, msg} = SData.term_unbin msgbin + nick = SApp.Identity.get_nick pk + push(socket, "shout", %{ + name: nick, + pk16: Shard.Keys.pk_display(pk), + message: msg, + }) + end) + {:noreply, socket} + end + + def handle_info({:chat_recv, _chan, {pk, msgbin, _sign}}, socket) do + {_ts, msg} = SData.term_unbin msgbin + nick = SApp.Identity.get_nick pk + Logger.info("#{inspect self()} :chat_recv #{inspect msg}") + push socket, "shout", %{"name" => nick, + "pk16" => Shard.Keys.pk_display(pk), + "message" => msg} + {:noreply, socket} + end + + def handle_info({:chat_send, _, _}, socket) do + {:noreply, socket} + end + + # Channels can be used in a request/response fashion + # by sending replies to requests from the client + def handle_in("ping", payload, socket) do + {:reply, {:ok, payload}, socket} + end + + # It is also common to receive messages from the client and + # broadcast to everyone in the current topic (room:lobby). + def handle_in("shout", payload, socket) do + pk = socket.assigns.pk + nick = SApp.Identity.get_nick pk + payload = Map.put(payload, "name", nick) + payload = Map.put(payload, "pk16", Shard.Keys.pk_display pk) + + GenServer.cast(socket.assigns.pid, {:chat_send, pk, payload["message"]}) + broadcast socket, "shout", payload + {:noreply, socket} + end + + # Add authorization logic here as required. + defp authorized?(_payload) do + true + end +end diff --git a/shardweb/lib/channels/user_socket.ex b/shardweb/lib/channels/user_socket.ex new file mode 100644 index 0000000..b4136bd --- /dev/null +++ b/shardweb/lib/channels/user_socket.ex @@ -0,0 +1,49 @@ +defmodule ShardWeb.UserSocket do + use Phoenix.Socket + + require Logger + + ## Channels + channel "room:*", ShardWeb.ChatChannel + + ## Transports + transport :websocket, Phoenix.Transports.WebSocket + # transport :longpoll, Phoenix.Transports.LongPoll + + # Socket params are passed from the client and can + # be used to verify and authenticate a user. After + # verification, you can put default assigns into + # the socket that will be set for all channels, ie + # + # {:ok, assign(socket, :user_id, verified_user_id)} + # + # To deny connection, return `:error`. + # + # See `Phoenix.Token` documentation for examples in + # performing token verification on connect. + 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: + # + # def id(socket), do: "user_socket:#{socket.assigns.user_id}" + # + # Would allow you to broadcast a "disconnect" event and terminate + # all active sockets and channels for a given user: + # + # ShardWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{}) + # + # Returning `nil` makes this socket anonymous. + def id(_socket), do: nil +end diff --git a/shardweb/lib/controllers/chat_controller.ex b/shardweb/lib/controllers/chat_controller.ex new file mode 100644 index 0000000..45b7d34 --- /dev/null +++ b/shardweb/lib/controllers/chat_controller.ex @@ -0,0 +1,13 @@ +defmodule ShardWeb.ChatController do + use ShardWeb, :controller + + def chat(conn, %{"room" => room}) do + conn = put_gon(conn, chat_room: room) + render conn, "chat.html", + room: room + end + + def privchat(_conn, %{"pk" => _pk}) do + # TODO + end +end diff --git a/shardweb/lib/controllers/identity_controller.ex b/shardweb/lib/controllers/identity_controller.ex new file mode 100644 index 0000000..fdaefd0 --- /dev/null +++ b/shardweb/lib/controllers/identity_controller.ex @@ -0,0 +1,44 @@ +defmodule ShardWeb.IdentityController do + use ShardWeb, :controller + + def list(conn, _params) do + render conn, "list.html" + end + + def self(conn, _params) do + render conn, "self.html" + end + + def update(conn, params) do + pid = SApp.Identity.find_proc(conn.assigns.pk) + info = GenServer.call(pid, :get_info) + info = %{info | nick: params["nick"]} + GenServer.call(pid, {:set_info, info}) + redirect conn, to: identity_path(conn, :view) + end + + def switch(conn, params) do + case Base.decode16(params["pk"]) do + {:ok, pk} -> + if Shard.Keys.have_sk? pk do + conn + |> put_session(:pk, pk) + |> redirect(to: identity_path(conn, :view)) + else + conn + |> put_flash(:error, "No secret key found") + |> render("view.html") + end + _ -> + conn + |> put_flash(:error, "Bad argument") + |> render("view.html") + end + end + + def create(conn, _params) do + pk = Shard.Keys.new_identity + conn = put_session(conn, :pk, pk) + redirect conn, to: identity_path(conn, :view) + end +end diff --git a/shardweb/lib/controllers/page_controller.ex b/shardweb/lib/controllers/page_controller.ex new file mode 100644 index 0000000..ebe2099 --- /dev/null +++ b/shardweb/lib/controllers/page_controller.ex @@ -0,0 +1,31 @@ +defmodule ShardWeb.PageController do + use ShardWeb, :controller + + def peer_list(conn, _params) do + render conn, "peer_list.html" + end + + def shard_list(conn, _params) do + render conn, "shard_list.html" + end + + def add_peer(conn, _params) do + try do + ip = conn.params["ip"] + port = conn.params["port"] + {:ok, ip_tuple} = case :inet.parse_address(to_charlist(ip)) do + {:ok, tup} -> {:ok, tup} + _ -> + case :inet.gethostbyname(to_charlist(ip)) do + {:ok, {:hostent, _, _, :inet, 4, [ip_tup | _]}} -> {:ok, ip_tup} + _ -> :error + end + end + {port_num, _} = Integer.parse port + SNet.Manager.add_peer({:inet, ip_tuple, port_num}) + rescue + _ -> nil + end + redirect conn, to: page_path(conn, :index) + end +end diff --git a/shardweb/lib/endpoint.ex b/shardweb/lib/endpoint.ex new file mode 100644 index 0000000..fb8a48f --- /dev/null +++ b/shardweb/lib/endpoint.ex @@ -0,0 +1,59 @@ +defmodule ShardWeb.Endpoint do + use Phoenix.Endpoint, otp_app: :shardweb + + socket "/socket", ShardWeb.UserSocket + + # Serve at "/" the static files from "priv/static" directory. + # + # You should set gzip to true if you are running phoenix.digest + # when deploying your static files in production. + plug Plug.Static, + at: "/", from: :shardweb, gzip: false, + only: ~w(css fonts font-awesome images js favicon.ico robots.txt) + + # Code reloading can be explicitly enabled under the + # :code_reloader configuration of your endpoint. + if code_reloading? do + socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket + plug Phoenix.LiveReloader + plug Phoenix.CodeReloader + end + + plug Plug.Logger + + plug Plug.Parsers, + parsers: [:urlencoded, :multipart, :json], + pass: ["*/*"], + json_decoder: Poison + + plug Plug.MethodOverride + plug Plug.Head + + # The session will be stored in the cookie and signed, + # this means its contents can be read but not tampered with. + # Set :encryption_salt if you would also like to encrypt it. + plug Plug.Session, + store: :cookie, + key: "_shardweb_key", + signing_salt: "BkoHycu8" + + + plug PhoenixGon.Pipeline + + plug ShardWeb.Router + + @doc """ + Callback invoked for dynamically configuring the endpoint. + + It receives the endpoint configuration and checks if + configuration should be loaded from the system environment. + """ + def init(_key, config) do + if config[:load_from_system_env] do + port = System.get_env("PORT") || raise "expected the PORT environment variable to be set" + {:ok, Keyword.put(config, :http, [:inet6, port: port])} + else + {:ok, config} + end + end +end diff --git a/shardweb/lib/gettext.ex b/shardweb/lib/gettext.ex new file mode 100644 index 0000000..e74cd43 --- /dev/null +++ b/shardweb/lib/gettext.ex @@ -0,0 +1,24 @@ +defmodule ShardWeb.Gettext do + @moduledoc """ + A module providing Internationalization with a gettext-based API. + + By using [Gettext](https://hexdocs.pm/gettext), + your module gains a set of macros for translations, for example: + + import ShardWeb.Gettext + + # Simple translation + gettext "Here is the string to translate" + + # Plural translation + ngettext "Here is the string to translate", + "Here are the strings to translate", + 3 + + # Domain-based translation + dgettext "errors", "Here is the error message to translate" + + See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. + """ + use Gettext, otp_app: :shardweb +end diff --git a/shardweb/lib/router.ex b/shardweb/lib/router.ex new file mode 100644 index 0000000..43de0da --- /dev/null +++ b/shardweb/lib/router.ex @@ -0,0 +1,56 @@ +defmodule ShardWeb.Router do + use ShardWeb, :router + + pipeline :browser do + plug :accepts, ["html"] + plug :fetch_session + plug :fetch_flash + plug :protect_from_forgery + plug :put_secure_browser_headers + plug Plug.Parsers, parsers: [:urlencoded] + plug :check_pk + end + + pipeline :api do + plug :accepts, ["json"] + end + + scope "/", ShardWeb do + pipe_through :browser # Use the default browser stack + + get "/", PageController, :peer_list + post "/peer/add", PageController, :add_peer + get "/dashboard", PageController, :shard_list + + get "/people", IdentityController, :list + get "/identity", IdentityController, :self + post "/identity", IdentityController, :update + post "/identity/switch", IdentityController, :switch + post "/identity/create", IdentityController, :create + + get "/chat/:room", ChatController, :chat + get "/pm/:pk", ChatController, :privchat + end + + # Other scopes may use custom stacks. + # scope "/api", ShardWeb do + # pipe_through :api + # end + + def check_pk(conn, _kv) do + pk1 = get_session(conn, :pk) + {conn, pk} = if pk1 == nil || not Shard.Keys.have_sk? pk1 do + pk = Shard.Keys.get_any_identity + conn = put_session(conn, :pk, pk) + {conn, pk} + else + {conn, pk1} + end + nick = SApp.Identity.get_nick pk + conn + |> assign(:pk, pk) + |> assign(:nick, nick) + |> PhoenixGon.Controller.put_gon(pk: (pk|>Base.encode16)) + end + +end diff --git a/shardweb/lib/shard_web.ex b/shardweb/lib/shard_web.ex index 049da29..417e47b 100644 --- a/shardweb/lib/shard_web.ex +++ b/shardweb/lib/shard_web.ex @@ -29,7 +29,7 @@ defmodule ShardWeb do def view do quote do - use Phoenix.View, root: "lib/shard_web/templates", + use Phoenix.View, root: "lib/templates", namespace: ShardWeb # Import convenience functions from controllers diff --git a/shardweb/lib/shard_web/channels/room_channel.ex b/shardweb/lib/shard_web/channels/room_channel.ex deleted file mode 100644 index 7c3a16c..0000000 --- a/shardweb/lib/shard_web/channels/room_channel.ex +++ /dev/null @@ -1,72 +0,0 @@ -defmodule ShardWeb.RoomChannel do - use ShardWeb, :channel - - require Logger - - def join("room:" <> room_name, payload, socket) do - if authorized?(payload) do - - pid = Shard.Manager.find_or_start %SApp.Chat.Manifest{channel: room_name} - socket = assign(socket, :pid, pid) - - GenServer.cast(pid, {:subscribe, self()}) - send(self(), :after_join) - - {:ok, socket} - else - {:error, %{reason: "unauthorized"}} - end - end - - def handle_info(:after_join, socket) do - GenServer.call(socket.assigns.pid, {:read_history, nil, 100}) - |> Enum.each(fn {{pk, msgbin, _sign}, true} -> - {_ts, msg} = SData.term_unbin msgbin - nick = SApp.Identity.get_nick pk - push(socket, "shout", %{ - name: nick, - pk16: Shard.Keys.pk_display(pk), - message: msg, - }) - end) - {:noreply, socket} - end - - def handle_info({:chat_recv, _chan, {pk, msgbin, _sign}}, socket) do - {_ts, msg} = SData.term_unbin msgbin - nick = SApp.Identity.get_nick pk - Logger.info("#{inspect self()} :chat_recv #{inspect msg}") - push socket, "shout", %{"name" => nick, - "pk16" => Shard.Keys.pk_display(pk), - "message" => msg} - {:noreply, socket} - end - - def handle_info({:chat_send, _, _}, socket) do - {:noreply, socket} - end - - # Channels can be used in a request/response fashion - # by sending replies to requests from the client - def handle_in("ping", payload, socket) do - {:reply, {:ok, payload}, socket} - end - - # It is also common to receive messages from the client and - # broadcast to everyone in the current topic (room:lobby). - def handle_in("shout", payload, socket) do - pk = socket.assigns.pk - nick = SApp.Identity.get_nick pk - payload = Map.put(payload, "name", nick) - payload = Map.put(payload, "pk16", Shard.Keys.pk_display pk) - - GenServer.cast(socket.assigns.pid, {:chat_send, pk, payload["message"]}) - broadcast socket, "shout", payload - {:noreply, socket} - end - - # Add authorization logic here as required. - defp authorized?(_payload) do - true - end -end diff --git a/shardweb/lib/shard_web/channels/user_socket.ex b/shardweb/lib/shard_web/channels/user_socket.ex deleted file mode 100644 index a3aa1a5..0000000 --- a/shardweb/lib/shard_web/channels/user_socket.ex +++ /dev/null @@ -1,49 +0,0 @@ -defmodule ShardWeb.UserSocket do - use Phoenix.Socket - - require Logger - - ## Channels - channel "room:*", ShardWeb.RoomChannel - - ## Transports - transport :websocket, Phoenix.Transports.WebSocket - # transport :longpoll, Phoenix.Transports.LongPoll - - # Socket params are passed from the client and can - # be used to verify and authenticate a user. After - # verification, you can put default assigns into - # the socket that will be set for all channels, ie - # - # {:ok, assign(socket, :user_id, verified_user_id)} - # - # To deny connection, return `:error`. - # - # See `Phoenix.Token` documentation for examples in - # performing token verification on connect. - 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: - # - # def id(socket), do: "user_socket:#{socket.assigns.user_id}" - # - # Would allow you to broadcast a "disconnect" event and terminate - # all active sockets and channels for a given user: - # - # ShardWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{}) - # - # Returning `nil` makes this socket anonymous. - def id(_socket), do: nil -end diff --git a/shardweb/lib/shard_web/controllers/identity_controller.ex b/shardweb/lib/shard_web/controllers/identity_controller.ex deleted file mode 100644 index a4f54e7..0000000 --- a/shardweb/lib/shard_web/controllers/identity_controller.ex +++ /dev/null @@ -1,40 +0,0 @@ -defmodule ShardWeb.IdentityController do - use ShardWeb, :controller - - def view(conn, _params) do - render conn, "view.html" - end - - def update(conn, params) do - pid = SApp.Identity.find_proc(conn.assigns.pk) - info = GenServer.call(pid, :get_info) - info = %{info | nick: params["nick"]} - GenServer.call(pid, {:set_info, info}) - redirect conn, to: identity_path(conn, :view) - end - - def switch(conn, params) do - case Base.decode16(params["pk"]) do - {:ok, pk} -> - if Shard.Keys.have_sk? pk do - conn - |> put_session(:pk, pk) - |> redirect(to: identity_path(conn, :view)) - else - conn - |> put_flash(:error, "No secret key found") - |> render("view.html") - end - _ -> - conn - |> put_flash(:error, "Bad argument") - |> render("view.html") - end - end - - def create(conn, _params) do - pk = Shard.Keys.new_identity - conn = put_session(conn, :pk, pk) - redirect conn, to: identity_path(conn, :view) - end -end diff --git a/shardweb/lib/shard_web/controllers/page_controller.ex b/shardweb/lib/shard_web/controllers/page_controller.ex deleted file mode 100644 index 261b5d6..0000000 --- a/shardweb/lib/shard_web/controllers/page_controller.ex +++ /dev/null @@ -1,27 +0,0 @@ -defmodule ShardWeb.PageController do - use ShardWeb, :controller - - def index(conn, _params) do - render conn, "index.html" - end - - def add_peer(conn, _params) do - try do - ip = conn.params["ip"] - port = conn.params["port"] - {:ok, ip_tuple} = case :inet.parse_address(to_charlist(ip)) do - {:ok, tup} -> {:ok, tup} - _ -> - case :inet.gethostbyname(to_charlist(ip)) do - {:ok, {:hostent, _, _, :inet, 4, [ip_tup | _]}} -> {:ok, ip_tup} - _ -> :error - end - end - {port_num, _} = Integer.parse port - SNet.Manager.add_peer({:inet, ip_tuple, port_num}) - rescue - _ -> nil - end - redirect conn, to: page_path(conn, :index) - end -end diff --git a/shardweb/lib/shard_web/controllers/room_controller.ex b/shardweb/lib/shard_web/controllers/room_controller.ex deleted file mode 100644 index d24649b..0000000 --- a/shardweb/lib/shard_web/controllers/room_controller.ex +++ /dev/null @@ -1,9 +0,0 @@ -defmodule ShardWeb.RoomController do - use ShardWeb, :controller - - def show(conn, %{"room" => room}) do - conn = put_gon(conn, chat_room: room) - render conn, "show.html", - room: room - end -end diff --git a/shardweb/lib/shard_web/endpoint.ex b/shardweb/lib/shard_web/endpoint.ex deleted file mode 100644 index fb8a48f..0000000 --- a/shardweb/lib/shard_web/endpoint.ex +++ /dev/null @@ -1,59 +0,0 @@ -defmodule ShardWeb.Endpoint do - use Phoenix.Endpoint, otp_app: :shardweb - - socket "/socket", ShardWeb.UserSocket - - # Serve at "/" the static files from "priv/static" directory. - # - # You should set gzip to true if you are running phoenix.digest - # when deploying your static files in production. - plug Plug.Static, - at: "/", from: :shardweb, gzip: false, - only: ~w(css fonts font-awesome images js favicon.ico robots.txt) - - # Code reloading can be explicitly enabled under the - # :code_reloader configuration of your endpoint. - if code_reloading? do - socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket - plug Phoenix.LiveReloader - plug Phoenix.CodeReloader - end - - plug Plug.Logger - - plug Plug.Parsers, - parsers: [:urlencoded, :multipart, :json], - pass: ["*/*"], - json_decoder: Poison - - plug Plug.MethodOverride - plug Plug.Head - - # The session will be stored in the cookie and signed, - # this means its contents can be read but not tampered with. - # Set :encryption_salt if you would also like to encrypt it. - plug Plug.Session, - store: :cookie, - key: "_shardweb_key", - signing_salt: "BkoHycu8" - - - plug PhoenixGon.Pipeline - - plug ShardWeb.Router - - @doc """ - Callback invoked for dynamically configuring the endpoint. - - It receives the endpoint configuration and checks if - configuration should be loaded from the system environment. - """ - def init(_key, config) do - if config[:load_from_system_env] do - port = System.get_env("PORT") || raise "expected the PORT environment variable to be set" - {:ok, Keyword.put(config, :http, [:inet6, port: port])} - else - {:ok, config} - end - end -end diff --git a/shardweb/lib/shard_web/gettext.ex b/shardweb/lib/shard_web/gettext.ex deleted file mode 100644 index e74cd43..0000000 --- a/shardweb/lib/shard_web/gettext.ex +++ /dev/null @@ -1,24 +0,0 @@ -defmodule ShardWeb.Gettext do - @moduledoc """ - A module providing Internationalization with a gettext-based API. - - By using [Gettext](https://hexdocs.pm/gettext), - your module gains a set of macros for translations, for example: - - import ShardWeb.Gettext - - # Simple translation - gettext "Here is the string to translate" - - # Plural translation - ngettext "Here is the string to translate", - "Here are the strings to translate", - 3 - - # Domain-based translation - dgettext "errors", "Here is the error message to translate" - - See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. - """ - use Gettext, otp_app: :shardweb -end diff --git a/shardweb/lib/shard_web/router.ex b/shardweb/lib/shard_web/router.ex deleted file mode 100644 index 4311a29..0000000 --- a/shardweb/lib/shard_web/router.ex +++ /dev/null @@ -1,53 +0,0 @@ -defmodule ShardWeb.Router do - use ShardWeb, :router - - pipeline :browser do - plug :accepts, ["html"] - plug :fetch_session - plug :fetch_flash - plug :protect_from_forgery - plug :put_secure_browser_headers - plug Plug.Parsers, parsers: [:urlencoded] - plug :check_pk - end - - pipeline :api do - plug :accepts, ["json"] - end - - scope "/", ShardWeb do - pipe_through :browser # Use the default browser stack - - get "/", PageController, :index - post "/peer/add", PageController, :add_peer - - get "/identity", IdentityController, :view - post "/identity", IdentityController, :update - post "/identity/switch", IdentityController, :switch - post "/identity/create", IdentityController, :create - - get "/room/:room", RoomController, :show - end - - # Other scopes may use custom stacks. - # scope "/api", ShardWeb do - # pipe_through :api - # end - - def check_pk(conn, _kv) do - pk1 = get_session(conn, :pk) - {conn, pk} = if pk1 == nil || not Shard.Keys.have_sk? pk1 do - pk = Shard.Keys.get_any_identity - conn = put_session(conn, :pk, pk) - {conn, pk} - else - {conn, pk1} - end - nick = SApp.Identity.get_nick pk - conn - |> assign(:pk, pk) - |> assign(:nick, nick) - |> PhoenixGon.Controller.put_gon(pk: (pk|>Base.encode16)) - end - -end diff --git a/shardweb/lib/shard_web/templates/identity/view.html.eex b/shardweb/lib/shard_web/templates/identity/view.html.eex deleted file mode 100644 index 5e57e02..0000000 --- a/shardweb/lib/shard_web/templates/identity/view.html.eex +++ /dev/null @@ -1,59 +0,0 @@ - -
-
-

- <%= @nick %> <%= @pk |> Base.encode16 %> -

- -
-
- - -<%= render ShardWeb.LayoutView, "flashes.html", assigns %> - - -<%= form_for @conn, identity_path(@conn, :update), [class: "form-horizontal"], fn f -> %> -
- -
- -
-
-
- <%= label :nick, "Nickname:", class: ["col-sm-2 control-label"] %> -
- <%= text_input f, :nick, [class: "form-control", value: @nick] %> -
-
-
-
- <%= submit "Update", [class: "btn btn-default"] %> -
-
-<% end %> - -

Other identities

- - - -<%= form_for @conn, identity_path(@conn, :create), [class: "form-inline"], fn _f -> %> - <%= submit "Create new identity", [class: "btn btn-danger"] %> -<% end %> diff --git a/shardweb/lib/shard_web/templates/layout/app.html.eex b/shardweb/lib/shard_web/templates/layout/app.html.eex deleted file mode 100644 index e0cb9dc..0000000 --- a/shardweb/lib/shard_web/templates/layout/app.html.eex +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - - - - - - - Shard. - - - " rel="stylesheet"> - - - " rel="stylesheet"> - - - " rel="stylesheet"> - - - " rel="stylesheet" type="text/css"> - - - - - - "> - - - - -
- - - - -
- -
- - - - <%= render @view_module, @view_template, assigns %> - -
- - -
- - -
- - - - - - - - - - - - - - <%= render_gon_script(@conn) %> - - - - - - diff --git a/shardweb/lib/shard_web/templates/layout/flashes.html.eex b/shardweb/lib/shard_web/templates/layout/flashes.html.eex deleted file mode 100644 index 5371f43..0000000 --- a/shardweb/lib/shard_web/templates/layout/flashes.html.eex +++ /dev/null @@ -1,24 +0,0 @@ - - <%= if get_flash(@conn, :info) do %> -
-
-
- - <%= get_flash(@conn, :info) %> -
-
-
- <% end %> - - - <%= if get_flash(@conn, :error) do %> -
-
-
- - <%= get_flash(@conn, :error) %> -
-
-
- <% end %> - diff --git a/shardweb/lib/shard_web/templates/page/index.html.eex b/shardweb/lib/shard_web/templates/page/index.html.eex deleted file mode 100644 index f385528..0000000 --- a/shardweb/lib/shard_web/templates/page/index.html.eex +++ /dev/null @@ -1,47 +0,0 @@ - -
-
-

- Peer list - -

- -
-
- - -<%= render ShardWeb.LayoutView, "flashes.html", assigns %> - - - - - - - - <%= for {{:inet, ip, port}, _pid, auth} <- conn_list() do %> - - - - - - <% end %> -
Peer IDAddressPort
- <%= case auth do %> - <% nil -> %>(anonymous) - <% %SNet.Auth{his_pk: his_pk} -> %> <%= Shard.Keys.pk_display(his_pk) %> - <% end %> - <%= :inet_parse.ntoa(ip) %><%= port %>
- -<%= form_for @conn, page_path(@conn, :add_peer), [class: "form-inline"], fn f -> %> - <%= text_input f, :ip, [class: "form-control", placeholder: "Hostname / IP address"] %> - <%= text_input f, :port, [class: "form-control", placeholder: "Port", value: "4044"] %> - <%= submit "Add peer", [class: "btn btn-default"] %> -<% end %> - diff --git a/shardweb/lib/shard_web/templates/room/show.html.eex b/shardweb/lib/shard_web/templates/room/show.html.eex deleted file mode 100644 index 75960b4..0000000 --- a/shardweb/lib/shard_web/templates/room/show.html.eex +++ /dev/null @@ -1,36 +0,0 @@ - -
-
-

- #<%= @room %> - -

- -
-
- - -<%= render ShardWeb.LayoutView, "flashes.html", assigns %> - - - - - - -
-
-
- <<%= @nick %>> -
-
- -
-
-
diff --git a/shardweb/lib/shard_web/views/error_helpers.ex b/shardweb/lib/shard_web/views/error_helpers.ex deleted file mode 100644 index f476548..0000000 --- a/shardweb/lib/shard_web/views/error_helpers.ex +++ /dev/null @@ -1,44 +0,0 @@ -defmodule ShardWeb.ErrorHelpers do - @moduledoc """ - Conveniences for translating and building error messages. - """ - - use Phoenix.HTML - - @doc """ - Generates tag for inlined form input errors. - """ - def error_tag(form, field) do - Enum.map(Keyword.get_values(form.errors, field), fn (error) -> - content_tag :span, translate_error(error), class: "help-block" - end) - end - - @doc """ - Translates an error message using gettext. - """ - def translate_error({msg, opts}) do - # When using gettext, we typically pass the strings we want - # to translate as a static argument: - # - # # Translate "is invalid" in the "errors" domain - # dgettext "errors", "is invalid" - # - # # Translate the number of files with plural rules - # dngettext "errors", "1 file", "%{count} files", count - # - # Because the error messages we show in our forms and APIs - # are defined inside Ecto, we need to translate them dynamically. - # This requires us to call the Gettext module passing our gettext - # backend as first argument. - # - # Note we use the "errors" domain, which means translations - # should be written to the errors.po file. The :count option is - # set by Ecto and indicates we should also apply plural rules. - if count = opts[:count] do - Gettext.dngettext(ShardWeb.Gettext, "errors", msg, msg, count, opts) - else - Gettext.dgettext(ShardWeb.Gettext, "errors", msg, opts) - end - end -end diff --git a/shardweb/lib/shard_web/views/error_view.ex b/shardweb/lib/shard_web/views/error_view.ex deleted file mode 100644 index a4b6eed..0000000 --- a/shardweb/lib/shard_web/views/error_view.ex +++ /dev/null @@ -1,16 +0,0 @@ -defmodule ShardWeb.ErrorView do - use ShardWeb, :view - - # If you want to customize a particular status code - # for a certain format, you may uncomment below. - # def render("500.html", _assigns) do - # "Internal Server Error" - # end - - # By default, Phoenix returns the status message from - # the template name. For example, "404.html" becomes - # "Not Found". - def template_not_found(template, _assigns) do - Phoenix.Controller.status_message_from_template(template) - end -end diff --git a/shardweb/lib/shard_web/views/identity_view.ex b/shardweb/lib/shard_web/views/identity_view.ex deleted file mode 100644 index 63d5a50..0000000 --- a/shardweb/lib/shard_web/views/identity_view.ex +++ /dev/null @@ -1,11 +0,0 @@ -defmodule ShardWeb.IdentityView do - use ShardWeb, :view - - def identity_list do - Shard.Keys.list_identities - end - - def get_nick(pk) do - SApp.Identity.get_nick pk - end -end diff --git a/shardweb/lib/shard_web/views/layout_view.ex b/shardweb/lib/shard_web/views/layout_view.ex deleted file mode 100644 index 2b12323..0000000 --- a/shardweb/lib/shard_web/views/layout_view.ex +++ /dev/null @@ -1,7 +0,0 @@ -defmodule ShardWeb.LayoutView do - use ShardWeb, :view - - def shard_list do - Shard.Manager.list_shards - end -end diff --git a/shardweb/lib/shard_web/views/page_view.ex b/shardweb/lib/shard_web/views/page_view.ex deleted file mode 100644 index 6bd8e4b..0000000 --- a/shardweb/lib/shard_web/views/page_view.ex +++ /dev/null @@ -1,14 +0,0 @@ -defmodule ShardWeb.PageView do - use ShardWeb, :view - - def conn_list do - SNet.Manager.list_connections - end - - def peer_id_to_str(id) do - id - |> binary_part(0, 8) - |> Base.encode16 - |> String.downcase - end -end diff --git a/shardweb/lib/shard_web/views/room_view.ex b/shardweb/lib/shard_web/views/room_view.ex deleted file mode 100644 index ebc2a60..0000000 --- a/shardweb/lib/shard_web/views/room_view.ex +++ /dev/null @@ -1,3 +0,0 @@ -defmodule ShardWeb.RoomView do - use ShardWeb, :view -end diff --git a/shardweb/lib/templates/chat/chat.html.eex b/shardweb/lib/templates/chat/chat.html.eex new file mode 100644 index 0000000..86c2fb6 --- /dev/null +++ b/shardweb/lib/templates/chat/chat.html.eex @@ -0,0 +1,37 @@ + +
+
+

+ #<%= @room %> + public chat room + +

+ +
+
+ + +<%= render ShardWeb.LayoutView, "flashes.html", assigns %> + + + + + + +
+
+
+ <<%= @nick %>> +
+
+ +
+
+
diff --git a/shardweb/lib/templates/identity/list.html.eex b/shardweb/lib/templates/identity/list.html.eex new file mode 100644 index 0000000..1354264 --- /dev/null +++ b/shardweb/lib/templates/identity/list.html.eex @@ -0,0 +1,32 @@ + +
+
+

+ People on the network + +

+ +
+
+ + +<%= render ShardWeb.LayoutView, "flashes.html", assigns %> + + + + + + + + <%= for {_id, manifest, pid} <- people_list() do %> + + + + + <% end %> +
User namePublic key
<%= GenServer.call(pid, :get_info).nick %> <%= manifest.pk |> Base.encode16 %>
+ diff --git a/shardweb/lib/templates/identity/self.html.eex b/shardweb/lib/templates/identity/self.html.eex new file mode 100644 index 0000000..5e57e02 --- /dev/null +++ b/shardweb/lib/templates/identity/self.html.eex @@ -0,0 +1,59 @@ + +
+
+

+ <%= @nick %> <%= @pk |> Base.encode16 %> +

+ +
+
+ + +<%= render ShardWeb.LayoutView, "flashes.html", assigns %> + + +<%= form_for @conn, identity_path(@conn, :update), [class: "form-horizontal"], fn f -> %> +
+ +
+ +
+
+
+ <%= label :nick, "Nickname:", class: ["col-sm-2 control-label"] %> +
+ <%= text_input f, :nick, [class: "form-control", value: @nick] %> +
+
+
+
+ <%= submit "Update", [class: "btn btn-default"] %> +
+
+<% end %> + +

Other identities

+ + + +<%= form_for @conn, identity_path(@conn, :create), [class: "form-inline"], fn _f -> %> + <%= submit "Create new identity", [class: "btn btn-danger"] %> +<% end %> diff --git a/shardweb/lib/templates/layout/app.html.eex b/shardweb/lib/templates/layout/app.html.eex new file mode 100644 index 0000000..5a087f2 --- /dev/null +++ b/shardweb/lib/templates/layout/app.html.eex @@ -0,0 +1,227 @@ + + + + + + + + + + + + Shard. + + + " rel="stylesheet"> + + + " rel="stylesheet"> + + + " rel="stylesheet"> + + + " rel="stylesheet" type="text/css"> + + + + + + "> + + + + +
+ + + + +
+ +
+ + + + <%= render @view_module, @view_template, assigns %> + +
+ + +
+ + +
+ + + + + + + + + + + + + + <%= render_gon_script(@conn) %> + + + + + + diff --git a/shardweb/lib/templates/layout/flashes.html.eex b/shardweb/lib/templates/layout/flashes.html.eex new file mode 100644 index 0000000..5371f43 --- /dev/null +++ b/shardweb/lib/templates/layout/flashes.html.eex @@ -0,0 +1,24 @@ + + <%= if get_flash(@conn, :info) do %> +
+
+
+ + <%= get_flash(@conn, :info) %> +
+
+
+ <% end %> + + + <%= if get_flash(@conn, :error) do %> +
+
+
+ + <%= get_flash(@conn, :error) %> +
+
+
+ <% end %> + diff --git a/shardweb/lib/templates/page/peer_list.html.eex b/shardweb/lib/templates/page/peer_list.html.eex new file mode 100644 index 0000000..f385528 --- /dev/null +++ b/shardweb/lib/templates/page/peer_list.html.eex @@ -0,0 +1,47 @@ + +
+
+

+ Peer list + +

+ +
+
+ + +<%= render ShardWeb.LayoutView, "flashes.html", assigns %> + + + + + + + + <%= for {{:inet, ip, port}, _pid, auth} <- conn_list() do %> + + + + + + <% end %> +
Peer IDAddressPort
+ <%= case auth do %> + <% nil -> %>(anonymous) + <% %SNet.Auth{his_pk: his_pk} -> %> <%= Shard.Keys.pk_display(his_pk) %> + <% end %> + <%= :inet_parse.ntoa(ip) %><%= port %>
+ +<%= form_for @conn, page_path(@conn, :add_peer), [class: "form-inline"], fn f -> %> + <%= text_input f, :ip, [class: "form-control", placeholder: "Hostname / IP address"] %> + <%= text_input f, :port, [class: "form-control", placeholder: "Port", value: "4044"] %> + <%= submit "Add peer", [class: "btn btn-default"] %> +<% end %> + diff --git a/shardweb/lib/templates/page/shard_list.html.eex b/shardweb/lib/templates/page/shard_list.html.eex new file mode 100644 index 0000000..a0648d3 --- /dev/null +++ b/shardweb/lib/templates/page/shard_list.html.eex @@ -0,0 +1,46 @@ + +
+
+

+ Shard list + +

+ +
+
+ + +<%= render ShardWeb.LayoutView, "flashes.html", assigns %> + + + + + + + + <%= for {id, manifest, pid} <- shard_list() do %> + + + + + + <% end %> +
ShardIdPid
+ <%= case manifest do %> + <% %SApp.Identity.Manifest{pk: pk} -> %> + <%= GenServer.call(pid, :get_info).nick %> + <%= Shard.Keys.pk_display pk %> + <% %SApp.Chat.Manifest{channel: chan} -> %> #<%= chan %> + <% %SApp.Chat.PrivChat.Manifest{pk_list: pk_list} -> %> + <%= pk_list |> Enum.map(&SApp.Identity.get_nick/1) |> Enum.join(", ") %> + <% x -> %> <%= inspect x %> + <% end %> + <%= id |> Base.encode16 %><%= inspect(pid) %>
+ diff --git a/shardweb/lib/views/chat_view.ex b/shardweb/lib/views/chat_view.ex new file mode 100644 index 0000000..fd39956 --- /dev/null +++ b/shardweb/lib/views/chat_view.ex @@ -0,0 +1,3 @@ +defmodule ShardWeb.ChatView do + use ShardWeb, :view +end diff --git a/shardweb/lib/views/error_helpers.ex b/shardweb/lib/views/error_helpers.ex new file mode 100644 index 0000000..f476548 --- /dev/null +++ b/shardweb/lib/views/error_helpers.ex @@ -0,0 +1,44 @@ +defmodule ShardWeb.ErrorHelpers do + @moduledoc """ + Conveniences for translating and building error messages. + """ + + use Phoenix.HTML + + @doc """ + Generates tag for inlined form input errors. + """ + def error_tag(form, field) do + Enum.map(Keyword.get_values(form.errors, field), fn (error) -> + content_tag :span, translate_error(error), class: "help-block" + end) + end + + @doc """ + Translates an error message using gettext. + """ + def translate_error({msg, opts}) do + # When using gettext, we typically pass the strings we want + # to translate as a static argument: + # + # # Translate "is invalid" in the "errors" domain + # dgettext "errors", "is invalid" + # + # # Translate the number of files with plural rules + # dngettext "errors", "1 file", "%{count} files", count + # + # Because the error messages we show in our forms and APIs + # are defined inside Ecto, we need to translate them dynamically. + # This requires us to call the Gettext module passing our gettext + # backend as first argument. + # + # Note we use the "errors" domain, which means translations + # should be written to the errors.po file. The :count option is + # set by Ecto and indicates we should also apply plural rules. + if count = opts[:count] do + Gettext.dngettext(ShardWeb.Gettext, "errors", msg, msg, count, opts) + else + Gettext.dgettext(ShardWeb.Gettext, "errors", msg, opts) + end + end +end diff --git a/shardweb/lib/views/error_view.ex b/shardweb/lib/views/error_view.ex new file mode 100644 index 0000000..a4b6eed --- /dev/null +++ b/shardweb/lib/views/error_view.ex @@ -0,0 +1,16 @@ +defmodule ShardWeb.ErrorView do + use ShardWeb, :view + + # If you want to customize a particular status code + # for a certain format, you may uncomment below. + # def render("500.html", _assigns) do + # "Internal Server Error" + # end + + # By default, Phoenix returns the status message from + # the template name. For example, "404.html" becomes + # "Not Found". + def template_not_found(template, _assigns) do + Phoenix.Controller.status_message_from_template(template) + end +end diff --git a/shardweb/lib/views/identity_view.ex b/shardweb/lib/views/identity_view.ex new file mode 100644 index 0000000..1844ce8 --- /dev/null +++ b/shardweb/lib/views/identity_view.ex @@ -0,0 +1,21 @@ +defmodule ShardWeb.IdentityView do + use ShardWeb, :view + + def identity_list do + Shard.Keys.list_identities + end + + def get_nick(pk) do + SApp.Identity.get_nick pk + end + + def people_list do + Shard.Manager.list_shards + |> Enum.filter(fn {_, manifest, _} -> + case manifest do + %SApp.Identity.Manifest{} -> true + _ -> false + end + end) + end +end diff --git a/shardweb/lib/views/layout_view.ex b/shardweb/lib/views/layout_view.ex new file mode 100644 index 0000000..2b12323 --- /dev/null +++ b/shardweb/lib/views/layout_view.ex @@ -0,0 +1,7 @@ +defmodule ShardWeb.LayoutView do + use ShardWeb, :view + + def shard_list do + Shard.Manager.list_shards + end +end diff --git a/shardweb/lib/views/page_view.ex b/shardweb/lib/views/page_view.ex new file mode 100644 index 0000000..eb88617 --- /dev/null +++ b/shardweb/lib/views/page_view.ex @@ -0,0 +1,18 @@ +defmodule ShardWeb.PageView do + use ShardWeb, :view + + def conn_list do + SNet.Manager.list_connections + end + + def peer_id_to_str(id) do + id + |> binary_part(0, 8) + |> Base.encode16 + |> String.downcase + end + + def shard_list do + Shard.Manager.list_shards + end +end -- cgit v1.2.3