diff --git a/web/channels/user_socket.ex b/web/channels/user_socket.ex --- a/web/channels/user_socket.ex +++ b/web/channels/user_socket.ex @@ -1,6 +1,9 @@ defmodule KolabChat.UserSocket do use Phoenix.Socket + alias KolabChat.Repo + alias KolabChat.User + ## Channels # channel "room:*", KolabChat.RoomChannel @@ -12,15 +15,16 @@ # 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 - {:ok, socket} + def connect(%{"token" => token}, socket) do + case Phoenix.Token.verify(socket, "user", token, max_age: 86400) do + {:ok, user_id} -> + socket = assign(socket, :user, Repo.get!(User, user_id)) + {:ok, socket} + {:error, _} -> + :error + end end # Socket id's are topics that allow you to identify all sockets for a given user: diff --git a/web/controllers/auth_controller.ex b/web/controllers/auth_controller.ex --- a/web/controllers/auth_controller.ex +++ b/web/controllers/auth_controller.ex @@ -1,8 +1,6 @@ defmodule KolabChat.AuthController do use KolabChat.Web, :controller - alias KolabChat.User - @doc """ Handler for the default logon form """ diff --git a/web/static/js/api.js b/web/static/js/api.js new file mode 100644 --- /dev/null +++ b/web/static/js/api.js @@ -0,0 +1,39 @@ + +import {Socket} from "phoenix" + +class KolabChat +{ + constructor(config) + { + this.config = config || {}; + } + + init(config) + { + if (config) + this.config = KolabChat.extend(this.config, config); + + var params = { + token: this.config.token, + logger: ((kind, msg, data) => { console.log(`${kind}: ${msg}`, data) }) + }; + + // FIXME: for some reason full URL did not work here + // We may need it for integration with external systems + + this.socket = new Socket("/socket", {params: params}); + this.socket.connect(); + + this.socket.onOpen(e => console.log("OPEN", e)) + this.socket.onError(e => console.log("ERROR", e)) + this.socket.onClose(e => console.log("CLOSE", e)) + } + + static extend(obj, src) + { + Object.keys(src).forEach(function(key) { obj[key] = src[key]; }); + return obj; + } +} + +export default KolabChat diff --git a/web/static/js/app.js b/web/static/js/app.js --- a/web/static/js/app.js +++ b/web/static/js/app.js @@ -18,4 +18,10 @@ // Local files can be imported directly using relative // paths "./socket" or full ones "web/static/js/socket". -// import socket from "./socket" +import KolabChat from "./api" + +let chat = new KolabChat(); + +if (window.userToken) { + chat.init({token: window.userToken}); +} diff --git a/web/static/js/socket.js b/web/static/js/socket.js deleted file mode 100644 --- a/web/static/js/socket.js +++ /dev/null @@ -1,62 +0,0 @@ -// NOTE: The contents of this file will only be executed if -// you uncomment its entry in "web/static/js/app.js". - -// To use Phoenix channels, the first step is to import Socket -// and connect at the socket path in "lib/my_app/endpoint.ex": -import {Socket} from "phoenix" - -let socket = new Socket("/socket", {params: {token: window.userToken}}) - -// When you connect, you'll often need to authenticate the client. -// For example, imagine you have an authentication plug, `MyAuth`, -// which authenticates the session and assigns a `:current_user`. -// If the current user exists you can assign the user's token in -// the connection for use in the layout. -// -// In your "web/router.ex": -// -// pipeline :browser do -// ... -// plug MyAuth -// plug :put_user_token -// end -// -// defp put_user_token(conn, _) do -// if current_user = conn.assigns[:current_user] do -// token = Phoenix.Token.sign(conn, "user socket", current_user.id) -// assign(conn, :user_token, token) -// else -// conn -// end -// end -// -// Now you need to pass this token to JavaScript. You can do so -// inside a script tag in "web/templates/layout/app.html.eex": -// -// -// -// You will need to verify the user token in the "connect/2" function -// in "web/channels/user_socket.ex": -// -// def connect(%{"token" => token}, socket) do -// # max_age: 1209600 is equivalent to two weeks in seconds -// case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do -// {:ok, user_id} -> -// {:ok, assign(socket, :user, user_id)} -// {:error, reason} -> -// :error -// end -// end -// -// Finally, pass the token on connect as below. Or remove it -// from connect if you don't care about authentication. - -socket.connect() - -// Now that you are connected, you can join channels with a topic: -let channel = socket.channel("topic:subtopic", {}) -channel.join() - .receive("ok", resp => { console.log("Joined successfully", resp) }) - .receive("error", resp => { console.log("Unable to join", resp) }) - -export default socket diff --git a/web/templates/layout/app.html.eex b/web/templates/layout/app.html.eex --- a/web/templates/layout/app.html.eex +++ b/web/templates/layout/app.html.eex @@ -20,6 +20,7 @@
  • <%= link gettext("Logout"), to: "/auth/logout" %>
  • + <% else %> <%= form_for @conn, "/auth/default/callback", [as: :logon], fn f -> %> <%= text_input f, :username, placeholder: gettext("Username") %> diff --git a/web/web.ex b/web/web.ex --- a/web/web.ex +++ b/web/web.ex @@ -31,6 +31,8 @@ use Phoenix.Controller alias KolabChat.Repo + alias KolabChat.User + import Ecto import Ecto.Query