# Session

Builtin to Phoenix, session\_opts defined in `endpoint.ex`

You can put and get things from the session then pass it into the render or I guess return it on api call

* put\_session(conn, key, value)
* configure\_session(conn, renew: true)
* configure\_session(conn, drop: true)
* fetch\_session(conn, opts \\\ \[])
* get\_session(conn) => all OR get\_session(conn, key)

router.ex

```elixir
#...
    get "/login", SessionController, :new
    get "/logout", SessionController, :delete
    resources "/sessions", SessionController, only: [:new, :create, :delete], singleton: true
#...
```

controllers/session\_controller.ex

```elixir
defmodule DiscussWeb.SessionController do
  use DiscussWeb, :controller

  alias Discuss.Accounts

  def new(conn, _) do
    render(conn, "new.html")
  end

  def delete(conn, _) do
    conn
    |> configure_session(drop: true)
    |> put_flash(:success, "Successfully signed out")
    |> redirect(to: "/")
  end

  def create(conn, %{"user" => %{"email" => email, "password" => password}}) do
    case Accounts.authenticate_by_email_password(email, password) do #write this ft in Accounts
      {:ok, user} ->
        conn
        |> put_flash(:info, "Welcome back!")
        |> put_session(:user_id, user.id) #Use an Auth Plug to lookup user
        |> configure_session(renew: true)
        |> redirect(to: "/")
      {:error, :unauthorized} ->
        conn
        |> put_flash(:info, "Bad email/password")
        |> redirect(to: Routes.session_path(conn, :new))
      {:error, :not_found} ->
        conn
        |> put_flash(:info, "Account not found!")
        |> redirect(to: Routes.session_path(conn, :new))
    end
  end
end
```

## Plug

router.ex

```elixir
  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
    plug Discuss.Auth
  end
```

lib/discuss\_web/plugs/auth.ex

```elixir
defmodule Discuss.Auth do
  import Plug.Conn
  import Phoenix.Controller
  alias DiscussWeb.Router.Helpers

  def init(opts), do: opts

  def call(conn, _opts) do
    user_id = get_session(conn, :user_id)
    user = user_id && Discuss.Accounts.get_user!(user_id)
    assign(conn, :current_user, user)
  end

  def logged_in_user(conn = %{assigns: %{current_user: %{}}}, _), do: conn

  def logged_in_user(conn, _opts) do
    conn 
    |> put_flash(:error, "You must be logged in to access that page")
    |> redirect(to: Helpers.page_path(conn, :index))
    |> halt()
  end
end
```

User\_controller.ex

```elixir
defmodule DiscussWeb.UserController do
  use DiscussWeb, :controller

  alias Discuss.Accounts
  alias Discuss.Accounts.User
  import Discuss.Auth, only: [logged_in_user: 2]
  plug :logged_in_user when action not in [:new, :create]
```

app.html.eex

```markup
User ID: <%= @current_user && @current_user.id %>
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://openai.gitbook.io/code-cheatsheets/all/elixir/phoenix/session.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
