A real-time chat application using websockets written in Elixir Phoenix Web Framework
To start finished version of the sample application written in this tutorial:
- Install dependencies with 
mix deps.get - Create and migrate your database with 
mix ecto.create && mix ecto.migrate - Install Node.js dependencies with 
cd assets && npm install - Start Phoenix endpoint with 
mix phx.server 
Now you can visit localhost:4000 from your browser.
- ChatGdg - GDG Izmir 2017
- Table of Contents
 - Installing Requirements and Setting Up Development Environment
 - Creating skeleton of a phoenix application with mix
 - Editing homepage
 - Using Presence Module and Activating Channels
 - Creating the Database Schema (not Model!)
 - Generating UserController and UserView
 - CRUD Operations
 - Hash the Password
 - User Authentication
 - User Restrictions
 - Changing Layout
 - Additional Resource
 
 
Follow the instructions.
When we install Elixir using instructions from the Elixir Installation Page, we will usually get Erlang too. If Erlang was not installed along with Elixir, please see the Erlang Instructions section of the Elixir Installation Page for instructions.
Mac OS X Macports Run: sudo port install elixir
Homebrew Update your homebrew to latest: brew update Run: brew install elixir
mix archive.install https://github.com/phoenixframework/archives/raw/master/phx_new.ezInstall from the link.
Install from the link.
For Ubuntu 14.04/16.04
sudo apt-get install inotify-toolFor other distros download from here
Links taken from installation docs
mix phx.new chat_gdgPress y and enter to fetch and install dependencies
Then the output should be:
* creating chat_gdg/assets/css/app.css
* creating chat_gdg/assets/css/phoenix.css
* creating chat_gdg/assets/js/app.js
* creating chat_gdg/assets/js/socket.js
* creating chat_gdg/assets/package.json
* creating chat_gdg/assets/static/robots.txt
* creating chat_gdg/assets/static/images/phoenix.png
* creating chat_gdg/assets/static/favicon.ico
Fetch and install dependencies? [Yn] Y
* running mix deps.get
* running mix deps.compile
* running cd assets && npm install && node node_modules/brunch/bin/brunch build
We are all set! Go into your application by running:
    $ cd chat_gdg
Then configure your database in config/dev.exs and run:
    $ mix ecto.create
Start your Phoenix app with:
    $ mix phx.server
You can also run your app inside IEx (Interactive Elixir) as:
    $ iex -S mix phx.serverOpen the chat_gdg/config/dev.exs file with a text editor and set the database credentials. Example:
# Configure your database
config :chat_gdg, ChatGdg.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "postgres",
  password: "postgres",
  database: "chat_gdg_dev",
  hostname: "localhost",
  pool_size: 10Make sure database application is up and run these commands to fire up:
cd chat_gdg
mix ecto create
mix phx.serverTake a look at the application structure.
A simple hello world application is ready.
Now you can visit localhost:4000 from your browser.
Take a look at the router.ex
In lib/chat_gdg_web/router.ex
  scope "/", ChatGdgWeb do
    pipe_through :browser # Use the default browser stack
    get "/", PageController, :index
  endget "/", PageController, :index this line directs the Page Controller
Now check the Page Controller
defmodule ChatGdgWeb.PageController do
  use ChatGdgWeb, :controller
  def index(conn, _params) do
    render conn, "index.html"
  end
endIn the Page Controller the index function renders the index.html template.
Let's edit the lib/chat_gdg_web/templates/page/index.html.eex as:
<div class="row">
  <div class="col-md-12 alert alert-info">
    Hello, <span id="User"><%= @conn.params["user"] %></span>!
  </div>
  <div class="col-md-8">
    <h2>Messages:</h2>
    <ul id="MessageList" class="list-unstyled" style="height: 400px; border: 1px solid black; overflow-y: auto; padding: 10px;" ></ul>
    <input type="text" id="NewMessage" class="form-control">
  </div>
  <div  class="col-md-4">
    <h2>Who’s Online</h2>
    <ul id="UserList" class="list-unstyled">
      <li>Loading online users...</li>
    </ul>
  </div>
</div>Again visit localhost:4000 from your browser.
And http://0.0.0.0:4000/?user=joearms
In the index.html.eex Hello, <span id="User"><%= @conn.params["user"] %></span>! line the @conn.params["user"] shows us the user from the connection's query parameters.
We will use the Presence module to track users status (is online & online since)
Provides Presence tracking to processes and channels.
This behaviour provides presence features such as fetching presences for a given topic, as well as handling diffs of join and leave events as they occur in real-time. Using this module defines a supervisor and allows the calling module to implement the Phoenix.Tracker behaviour which starts a tracker process to handle presence information.
To create our presence with this command:
mix phx.gen.presenceoutput
* creating lib/chat_gdg_web/channels/presence.ex
Add your new module to your supervision tree,
in lib/chat_gdg/application.ex:
    children = [
      ...
      supervisor(ChatGdgWeb.Presence, []),
    ]
You're all set! See the Phoenix.Presence docs for more details:
http://hexdocs.pm/phoenix/Phoenix.Presence.htmlLet's activate the channel to use websockets:
Uncomment the this line in the lib/chat_gdg_web/channels/user_socket.ex
channel "room:*", ChatGdgWeb.RoomChanneland edit the connect function:
def connect(%{"user" => user}, socket) do
    {:ok, assign(socket, :user, user)}
endThen create a module to handle room channel: Create a file named room_channel.ex under lib/chat_gdg_web/channels
defmodule ChatGdg.RoomChannel do
    use ChatGdg.Web, :channel
    alias ChatGdg.Presence
    def join("room:lobby", _, socket) do
      send self(), :after_join
      {:ok, socket}
    end
    def handle_info(:after_join, socket) do
      Presence.track(socket, socket.assigns.user, %{
        online_at: :os.system_time(:milli_seconds)
      })
      push socket, "presence_state", Presence.list(socket)
      {:noreply, socket}
    end
    def connect(%{"user" => user}, socket) do
      {:ok, assign(socket, :user, user)}
    end
endModify the app.js file under the assets/js/ such as:
import "phoenix_html"
import {Socket, Presence} from "phoenix"
// get the user element from index.html
let user = document.getElementById("User").innerText
// generate a socket connection with the user parameter
let socket = new Socket("/socket", {params: {user: user}})
socket.connect()
// create an empty js object to handle presences
let presences = {}
let formatTimestamp = (timestamp) => {
  let date = new Date(timestamp)
  return date.toLocaleTimeString()
}
let listBy = (user, {metas: metas}) => {
  return {
    user: user,
    onlineAt: formatTimestamp(metas[0].online_at)
  }
}
// get the UserList element from index.html
let userList = document.getElementById("UserList")
let render = (presences) => {
  userList.innerHTML = Presence.list(presences, listBy)
    .map(presence => `
      <li>
        <b>${presence.user}</b>
        <br><small>online since ${presence.onlineAt}</small>
      </li>
    `)
    .join("")
}
// handle with the single channel
// create a connection between client and room:lobby channel and set the presences settings
let room = socket.channel("room:lobby", {})
room.on("presence_state", state => {
  presences = Presence.syncState(presences, state)
  render(presences)
})
room.on("presence_diff", diff => {
  presences = Presence.syncDiff(presences, diff)
  render(presences)
})
// join the room
room.join()
// get the NewMessage element from index.html
let messageInput = document.getElementById("NewMessage")
messageInput.addEventListener("keypress", (e) => {
  if (e.keyCode == 13 && messageInput.value != "") {
    room.push("message:new", messageInput.value)
    messageInput.value = ""
  }
})
let messageList = document.getElementById("MessageList")
let renderMessage = (message) => {
  let messageElement = document.createElement("li")
  messageElement.innerHTML = `
    <b>${message.user}</b>
    <i>${formatTimestamp(message.timestamp)}</i>
    <p>${message.body}</p>
  `
  messageList.appendChild(messageElement)
  messageList.scrollTop = messageList.scrollHeight;
}
room.on("message:new", message => renderMessage(message))mix phx.gen.schema User users email:unique encrypt_pass:stringoutput:
* creating lib/chat_gdg/user.ex
* creating priv/repo/migrations/20171201161350_create_users.exs
Remember to update your repository by running migrations:
    $ mix ecto.migratetake a look at model file and migration file:
cat priv/repo/migrations/20171201161350_create_users.exsdefmodule ChatGdg.Repo.Migrations.CreateUsers do
  use Ecto.Migration
  def change do
    create table(:users) do
      add :email, :string
      add :encrypt_pass, :string
      timestamps()
    end
    create unique_index(:users, [:email])
  end
endcat lib/chat_gdg/user.exdefmodule ChatGdg.User do
  use Ecto.Schema
  import Ecto.Changeset
  alias ChatGdg.User
  schema "users" do
    field :email, :string
    field :encrypt_pass, :string
    timestamps()
  end
  @doc false
  def changeset(%User{} = user, attrs) do
    user
    |> cast(attrs, [:email, :encrypt_pass])
    |> validate_required([:email, :encrypt_pass])
    |> unique_constraint(:email)
  end
endAdd a field line for real(!) password but not store with the functionality of virtual parameter
  schema "users" do
    field :email, :string
    field :encrypt_pass, :string
    field :password, :string, virtual: true
    timestamps()
  endand edit the changeset function as below
  def changeset(%User{} = user, attrs) do
    user
    |> cast(attrs, [:email, :password])
    |> validate_required([:email, :password])
    |> unique_constraint(:email)
  endTake a look at usage of virtual field in Ecto schema
Then apply the migration with the mix command
mix ecto.migrateoutput:
Compiling 1 file (.ex)
Generated chat_gdg app
[info] == Running ChatGdg.Repo.Migrations.CreateUsers.change/0 forward
[info] create table users
[info] create index users_email_index
[info] == Migrated in 0.0siex -S mix phx.server
Erlang/OTP 19 [erts-8.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
[info] Running ChatGdgWeb.Endpoint with Cowboy using http://0.0.0.0:4000
Interactive Elixir (1.4.0) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 19:46:54 - info: compiled 6 files into 2 files, copied 3 in 914 ms
alias ChatGdg.Repo
ChatGdg.Repo
iex(2)> alias ChatGdg.User
ChatGdg.User
iex(3)> Repo.all(User)
[debug] QUERY OK source="users" db=1.7ms queue=0.1ms
SELECT u0."id", u0."email", u0."encrypt_pass", u0."inserted_at", u0."updated_at" FROM "users" AS u0 []
[]
iex(4)> Repo.insert(%User{email: "joearms@erlang.com", encrypt_pass: "password"})
[debug] QUERY OK db=7.8ms
INSERT INTO "users" ("email","encrypt_pass","inserted_at","updated_at") VALUES ($1,$2,$3,$4) RETURNING "id" ["joearms@erlang.com", "password", {{2017, 12, 1}, {16, 49, 29, 841382}}, {{2017, 12, 1}, {16, 49, 29, 843639}}]
{:ok,
 %ChatGdg.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
  email: "joearms@erlang.com", encrypt_pass: "password", id: 1,
  inserted_at: ~N[2017-12-01 16:49:29.841382], password: nil,
  updated_at: ~N[2017-12-01 16:49:29.843639]}}To handle CRUD operations add UserController the router.ex with resources macro.
  scope "/", ChatGdgWeb do
    pipe_through :browser # Use the default browser stack
    resources "/users", UserController
    get "/", PageController, :index
  endthen check our new routes with the command:
mix phx.routes
Compiling 1 file (.ex)
user_path  GET     /users           ChatGdgWeb.UserController :index
user_path  GET     /users/:id/edit  ChatGdgWeb.UserController :edit
user_path  GET     /users/new       ChatGdgWeb.UserController :new
user_path  GET     /users/:id       ChatGdgWeb.UserController :show
user_path  POST    /users           ChatGdgWeb.UserController :create
user_path  PATCH   /users/:id       ChatGdgWeb.UserController :update
           PUT     /users/:id       ChatGdgWeb.UserController :update
user_path  DELETE  /users/:id       ChatGdgWeb.UserController :delete
page_path  GET     /                ChatGdgWeb.PageController :indexCreate the skeleton of user_controller.ex at lib/chat_gdg_web/controllers/
defmodule ChatGdgWeb.UserController do
    use ChatGdgWeb, :controller
    alias ChatGdg.User
    alias ChatGdg.Repo
    def index(conn, _params) do
        users = Repo.all(User)
        render(conn, "index.html", users: users)
    end
    def show(conn, %{"id" => id}) do
        user = Repo.get!(User, id)
        render(conn, "show.html", user: user)
    end
endAnd create the user_view.ex at lib/chat_gdg_web/views/
defmodule ChatGdgWeb.UserView do
    use ChatGdgWeb, :view
endAnd finally create the index.html.eex at lib/chat_gdg_web/templates/user/
<h2>List of users</h2>
<table class="table">
  <thead>
    <tr>
      <th>Email</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
<%= for user <- @users do %>
    <tr>
      <td><%= user.email %></td>
      <td class="text-right">
        <%= link "Profile", to: user_path(@conn, :show, user), class: "btn btn-default btn-xs" %>
        <%= link "Edit", to: user_path(@conn, :edit, user), class: "btn btn-default btn-xs" %>
        <%= link "Delete User", to: user_path(@conn, :delete, user), method: :delete, data: [confirm: "Are you sure?"], class: "btn btn-danger btn-xs" %>
      </td>
    </tr>
<% end %>
  </tbody>
</table>
<%= link "New user", to: user_path(@conn, :new) %>Now visit localhost:4000/users from your browser and try the Profile button!
If you try to click Edit or Delete User buttons you will get error because we did not define new-create, edit-update and delete functions!
To create a user we need to add new and create functions in the our controller. Add these functions to user_controller.ex
    def new(conn, _params) do
        changeset = User.changeset(%User{})
        render(conn, "new.html", changeset: changeset)
    end
    def create(conn, %{"user" => user_params}) do
        changeset = User.reg_changeset(%User{}, user_params)
        case Repo.insert(changeset) do
        {:ok, _user} ->
            conn
            |> put_flash(:info, "User created successfully.")
            |> redirect(to: user_path(conn, :index))
        {:error, changeset} ->
            render(conn, "new.html", changeset: changeset)
        end
    endThen create a new.html.eex and form.html.eex template. form.html.eex will be inherited and handle in create and edit operations.
new.html.eex
<h2>Create a new User</h2>
<%= render "form.html", changeset: @changeset,
                        action: user_path(@conn, :create) %>
<%= link "Back", to: user_path(@conn, :index) %>form.html.eex
<%= form_for @changeset, @action, fn f -> %>
  <%= if @changeset.action do %>
    <div class="alert alert-danger">
      <p>Oops, something went wrong! Please check the errors below.</p>
    </div>
  <% end %>
  <div class="form-group">
    <%= label f, :email, class: "control-label" %>
    <%= email_input f, :email, class: "form-control" %>
    <%= error_tag f, :email %>
  </div>
  <div class="form-group">
    <%= label f, :password, class: "control-label" %>
    <%= password_input f, :password, class: "form-control" %>
    <%= error_tag f, :password %>
  </div>
  <div class="form-group">
    <%= submit "Submit", class: "btn btn-primary" %>
  </div>
<% end %>Now try to create a user:
To handle update and delete operations -as usual we did- now we will implement the edit, update and delete function to the user_controller.ex
    def edit(conn, %{"id" => id}) do
        user = Repo.get!(User, id)
        changeset = User.changeset(user)
        render(conn, "edit.html", user: user, changeset: changeset)
    end
    def update(conn, %{"id" => id, "user" => user_params}) do
        user = Repo.get!(User, id)
        changeset = User.changeset(user, user_params)
        case Repo.update(changeset) do
          {:ok, user} ->
            conn
            |> put_flash(:info, "User updated successfully.")
            |> redirect(to: user_path(conn, :show, user))
          {:error, changeset} ->
            render(conn, "edit.html", user: user, changeset: changeset)
        end
    end
    def delete(conn, %{"id" => id}) do
        user = Repo.get!(User, id)
        Repo.delete!(user)
        conn
        |> put_flash(:danger, "User deleted successfully.")
        |> redirect(to: user_path(conn, :index))
    endAnd create and edit.html.eex template for editing user page.
edit.html.eex
<h2>Edit user</h2>
<%= render "form.html", changeset: @changeset,
                        action: user_path(@conn, :update, @user) %>
<%= link "Back", to: user_path(@conn, :index) %>Now we able to use create, read, update and delete functions/operations.
Do not store passwords in plain text. Are you asking why? Then check this out.
We need some functions, then we will search for a Elixir hashing library. Let's search a package from hex.pm
Search for 'hash' then inspect the results.
Let's use comeonin.
Copy the {:comeonin, "~> 3.0"} dependency and paste it to mix.exs. Your mix.exs file should be like this:
defp deps do
    [
      {:phoenix, "~> 1.3.0"},
      {:phoenix_pubsub, "~> 1.0"},
      {:phoenix_ecto, "~> 3.2"},
      {:postgrex, ">= 0.0.0"},
      {:phoenix_html, "~> 2.10"},
      {:phoenix_live_reload, "~> 1.0", only: :dev},
      {:gettext, "~> 0.11"},
      {:cowboy, "~> 1.0"},
      {:comeonin, "~> 3.0"}
    ]
  endThen, get the dependencies and compile:
mix deps.getOutput:
Resolving Hex dependencies...
Dependency resolution completed:
  comeonin 3.2.0
  connection 1.0.4
  cowboy 1.1.2
  cowlib 1.0.2
  db_connection 1.1.2
  decimal 1.4.1
  ecto 2.2.6
  file_system 0.2.2
  gettext 0.13.1
  mime 1.1.0
  phoenix 1.3.0
  phoenix_ecto 3.3.0
  phoenix_html 2.10.5
  phoenix_live_reload 1.1.3
  phoenix_pubsub 1.0.2
  plug 1.4.3
  poison 3.1.0
  poolboy 1.5.1
  postgrex 0.13.3
  ranch 1.3.2
* Getting comeonin (Hex package)
  Checking package (https://repo.hex.pm/tarballs/comeonin-4.0.3.tar)
  Fetched packagemix deps.compileOutput:
===> Compiling ranch
===> Compiling poolboy
==> comeonin
Compiling 2 files (.ex)
Generated comeonin app
===> Compiling cowlib
===> Compiling cowboyNow we can use the comeonin library in our application.
Let's and add two function which handles hashing password to the user.ex
  def reg_changeset(%User{} = user, attrs \\ %{}) do
    user
    |> changeset(attrs)
    |> cast(attrs, [:password], [])
    |> validate_required(:password, min: 5)
    |> hash_pw()
  end
  defp hash_pw(changeset) do
    case changeset do
      %Ecto.Changeset{valid?: true, changes: %{password: p}} ->
        put_change(changeset, :encrypt_pass, Comeonin.Pbkdf2.hashpwsalt(p))
      _ ->
        changeset
    end
  endThen edit create and update in the user_controller.ex to use our new reg_changeset function.
    def create(conn, %{"user" => user_params}) do
        changeset = User.reg_changeset(%User{}, user_params)
        case Repo.insert(changeset) do
        {:ok, _user} ->
            conn
            |> put_flash(:info, "User created successfully.")
            |> redirect(to: user_path(conn, :index))
        {:error, changeset} ->
            render(conn, "new.html", changeset: changeset)
        end
    end    def update(conn, %{"id" => id, "user" => user_params}) do
        user = Repo.get!(User, id)
        changeset = User.reg_changeset(user, user_params)
        case Repo.update(changeset) do
          {:ok, user} ->
            conn
            |> put_flash(:info, "User updated successfully.")
            |> redirect(to: user_path(conn, :show, user))
          {:error, changeset} ->
            render(conn, "edit.html", user: user, changeset: changeset)
        end
    endWe will use Guardian library to handle authentication in our application.
*Guardian is a token based authentication library for use with Elixir applications.
Guardian remains a functional system. It integrates with Plug, but can be used outside of it. If you're implementing a TCP/UDP protocol directly, or want to utilize your authentication via channels in Phoenix, Guardian is your friend.*
Let's add the dependency to mix.exs
  defp deps do
    [
      {:phoenix, "~> 1.3.0"},
      {:phoenix_pubsub, "~> 1.0"},
      {:phoenix_ecto, "~> 3.2"},
      {:postgrex, ">= 0.0.0"},
      {:phoenix_html, "~> 2.10"},
      {:phoenix_live_reload, "~> 1.0", only: :dev},
      {:gettext, "~> 0.11"},
      {:cowboy, "~> 1.0"},
      {:comeonin, "~> 3.0"},
      {:guardian, "~> 0.14"}
    ]
  endmix deps.getOutput:
Resolving Hex dependencies...
Dependency resolution completed:
  base64url 0.0.1
  comeonin 3.2.0
  connection 1.0.4
  cowboy 1.1.2
  cowlib 1.0.2
  db_connection 1.1.2
  decimal 1.4.1
  ecto 2.2.6
  elixir_make 0.4.0
  file_system 0.2.2
  gettext 0.13.1
  guardian 0.14.5
  jose 1.8.4
  mime 1.1.0
  phoenix 1.3.0
  phoenix_ecto 3.3.0
  phoenix_html 2.10.5
  phoenix_live_reload 1.1.3
  phoenix_pubsub 1.0.2
  plug 1.4.3
  poison 3.1.0
  poolboy 1.5.1
  postgrex 0.13.3
  ranch 1.3.2
  uuid 1.1.8
* Getting guardian (Hex package)
  Checking package (https://repo.hex.pm/tarballs/guardian-0.14.5.tar)
  Using locally cached package
* Getting jose (Hex package)
  Checking package (https://repo.hex.pm/tarballs/jose-1.8.4.tar)
  Using locally cached package
* Getting uuid (Hex package)
  Checking package (https://repo.hex.pm/tarballs/uuid-1.1.8.tar)
  Using locally cached package
* Getting base64url (Hex package)
  Checking package (https://repo.hex.pm/tarballs/base64url-0.0.1.tar)
  Using locally cached packagemix deps.compile===> Compiling base64url
==> jose
Compiling 89 files (.erl)
Compiling 8 files (.ex)
Generated jose app
===> Compiling ranch
==> poolboy (compile)
==> comeonin
make: Nothing to be done for `all'.
===> Compiling cowlib
===> Compiling cowboy
==> uuid
Compiling 1 file (.ex)
Generated uuid app
==> guardian
Compiling 21 files (.ex)
Generated guardian appThen add the configuration parameters block to config/config.exs
config :guardian, Guardian,
  allowed_algos: ["HS512"], # optional
  verify_module: Guardian.JWT, # optional
  issuer: "ChatGdg",
  ttl: {30, :days},
  allowed_drift: 2000,
  verify_issuer: true, # optional
  secret_key: "dY3otygFOMcX1zXEwQ11JFIQdZp0Z+C0xEF1lx5gOpef/mYrsWu28dW++FBvm7qi",
  serializer: ChatGdg.GuardianSerializerYou can generate a secret key with the command:
mix phx.gen.secretOuput:
dY3otygFOMcX1zXEwQ11JFIQdZp0Z+C0xEF1lx5gOpef/mYrsWu28dW++FBvm7qiPut it to secret_key parameter.
Now create a Guardian controller. Put it to chat_gdg/controller/guardian_serializer.ex
defmodule ChatGdg.GuardianSerializer do
  @behaviour Guardian.Serializer
  alias ChatGdg.Repo
  alias ChatGdg.User
  def for_token(user = %User{}), do: { :ok, "User:#{user.id}" }
  def for_token(_), do: { :error, "Unknown resource type" }
  def from_token("User:" <> id), do: { :ok, Repo.get(User, id) }
  def from_token(_), do: { :error, "Unknown resource type" }
endNow here is the Plug rocks!
Modify the router.ex to handle authentication with Guardian and sessions, then our router.ex should be like that:
defmodule ChatGdgWeb.Router do
  use ChatGdgWeb, :router
  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
    plug Guardian.Plug.VerifySession
    plug Guardian.Plug.LoadResource
  end
  # define a new pipeline (browser authentication)
  pipeline :browser_auth do
    plug Guardian.Plug.VerifySession
    plug Guardian.Plug.EnsureAuthenticated, handler: ChatGdgWeb.Token
    plug Guardian.Plug.LoadResource
  end
  pipeline :api do
    plug :accepts, ["json"]
  end
  scope "/", ChatGdgWeb do
    pipe_through :browser
    # unauthorized users can only trig the new and create functions
    resources "/users", UserController, [:new, :create]
    # let's generate create and delete operations for sessions
    resources "/sessions", SessionController, only: [:create, :delete]
    # now we redirect the root path to SessionController to check users session
    get "/", SessionController, :new
  end
  # define a new pipeline which uses both :browser and :browser_auth for authenticated users
  scope "/", ChatGdgWeb do
    pipe_through [:browser, :browser_auth]
    # authenticated users can only trig the show, onde
    resources "/users", UserController, only: [:show, :index, :update]
    # in here we direct the authenticated users to chat screen with Page Controller
    get "/chat", PageController, :index
  end
  # Other scopes may use custom stacks.
  # scope "/api", ChatGdgWeb do
  #   pipe_through :api
  # end
endLet's create token handler token.ex:
defmodule ChatGdg.Token do
    use ChatGdgWeb, :controller
    def unauthenticated(conn, _params) do
        conn
        |> put_flash(:error, "You must be signed in!")
        |> redirect(to: session_path(conn, :new))
    end
    def unauthorized(conn, _params) do
        conn
        |> put_flash(:error, "You must be signed in!")
        |> redirect(to: session_path(conn, :new))
    end
endAnd add Session View and Session Controller
Let's define a simple view, session_view.ex:
defmodule ChatGdgWeb.SessionView do
    use ChatGdgWeb, :view
endAnd our session controller, session_controller.ex:
defmodule ChatGdgWeb.SessionController do
    use ChatGdgWeb, :controller
    import ChatGdgWeb.Auth
    alias ChatGdg.Repo
    def new(conn, _params) do
        render(conn, "new.html")
    end
    def create(conn, %{"session" => %{"email" => user, "password" => password}}) do
      case login_with(conn, user, password, repo: Repo) do
        {:ok, conn} ->
          logged_user = Guardian.Plug.current_resource(conn)
          conn
          |> put_flash(:info, "logged in!")
          |> redirect(to: page_path(conn, :index))
        {:error, _reason, conn} ->
          conn
          |> put_flash(:error, "Wrong username/password")
          |> render("new.html")
      end
    end
    def delete(conn, _) do
        conn
        |> Guardian.Plug.sign_out
        |> redirect(to: "/")
    end
endFinal step for handling sessions is creating the template.
chat_gdg_web/templates/sessions/new.html.eex:
<h1>Sign In</h1>
<%= form_for @conn, session_path(@conn, :create), [as: :session], fn f -> %>
<div class="form-group">
  <%= label f, :email, class: "control-label" %>
    <%= email_input f, :email, class: "form-control" %>
    <%= error_tag f, :email %>
</div>
<div class="form-group">
    <%= label f, :password, class: "control-label" %>
    <%= password_input f, :password, class: "form-control" %>
    <%= error_tag f, :password %>
</div>
  <div class="form-group">
    <%= submit "Submit", class: "btn btn-primary" %>
  </div>
<% end %>To prevent the edit and delete operations without access we will implement user acces in the user_controller.ex
Edit the edit, update and delete functions as below:
    def edit(conn, %{"id" => id}) do
        user = Repo.get!(User, id)
        cond do
        user == Guardian.Plug.current_resource(conn) ->
            changeset = User.changeset(user)
            render(conn, "edit.html", user: user, changeset: changeset)
        :error ->
            conn
            |> put_flash(:error, "No access")
            |> redirect(to: user_path(conn, :index))
        end
    end
    def update(conn, %{"id" => id, "user" => user_params}) do
        user = Repo.get!(User, id)
        changeset = User.reg_changeset(user, user_params)
        cond do
        user == Guardian.Plug.current_resource(conn) ->
            case Repo.update(changeset) do
            {:ok, user} ->
                conn
                |> put_flash(:info, "User updated successfully.")
                |> redirect(to: user_path(conn, :show, user))
            {:error, changeset} ->
                render(conn, "edit.html", user: user, changeset: changeset)
        end
            :error ->
            conn
            |> put_flash(:error, "No access")
            |> redirect(to: user_path(conn, :index))
        end
    end
    def delete(conn, %{"id" => id}) do
        user = Repo.get!(User, id)
        cond do
        user == Guardian.Plug.current_resource(conn) ->
            Repo.delete!(user)
            conn
            |> Guardian.Plug.sign_out
            |> put_flash(:danger, "User deleted successfully.")
            |> redirect(to: session_path(conn, :new))
        :error ->
            conn
            |> put_flash(:error, "No access")
            |> redirect(to: user_path(conn, :index))
        end
    endNow let's modify the page layout according to user authentication.
Create a Helper View under the views:
defmodule ChatGdgWeb.ViewHelper do
    def current_user(conn), do: Guardian.Plug.current_resource(conn)
    def logged_in?(conn), do: Guardian.Plug.authenticated?(conn)
  endAllow access to Helper View, add the line import ChatGdgWeb.ViewHelper to lib/chat_gdg_web.ex file:
def view do
    quote do
      use Phoenix.View, root: "lib/chat_gdg_web/templates",
                        namespace: ChatGdgWeb
      # Import convenience functions from controllers
      import Phoenix.Controller, only: [get_flash: 2, view_module: 1]
      # Use all HTML functionality (forms, tags, etc)
      use Phoenix.HTML
      import ChatGdgWeb.Router.Helpers
      import ChatGdgWeb.ErrorHelpers
      import ChatGdgWeb.Gettext
      import ChatGdgWeb.ViewHelper
    end
  endAnd create a file named logged.html.eex under lib/chat_gdg_web/templates/layout:
<%= if logged_in?(@conn) do %>
  <%= link "Sign Out", to: session_path(@conn, :delete, :access),
    method: :delete, class: "btn btn-danger" %>
  <%= link "#{current_user(@conn).email}", to: user_path(@conn, :show, current_user(@conn)) %>
  <% else %>
  <%= link "Create an Account!", to: user_path(@conn, :new),
    class: "btn btn-info" %>
  <%= link "Sign in", to: session_path(@conn, :new),
      class: "btn btn-primary" %>
<% end %>And to render it, modify the app.html.eex template add it inside the header tag:
<header class="header">
  <nav role="navigation">
    <ul class="nav nav-pills pull-right">
      <li><%= render "logged.html", conn: @conn %></li>
    </ul>
  </nav>
  <span class="logo"></span>
</header>To show username (email in our design), use an embedded elixir function in the templates/page/index.html.eex file:
Change these lines:
<div class="col-md-12 alert alert-info">
  Hello, <span id="User"><%= @conn.params["user"] %></span>!
</div>with these:
<div class="col-md-12 alert alert-info">
  Hello, <span id="User"><%= "#{current_user(@conn).email}" %></span>!
</div>Now add these lines to the user index template:
templates/user/index.html.eex
<%= link "New user", to: user_path(@conn, :new), class: "btn btn-info" %>
<%= if logged_in?(@conn) do %>
  <%= link "Chat", to: page_path(@conn, :index), class: "btn btn-success" %><br><br>
  <% else %>
<% end %>