zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

session.ex (3990B)


      1 defmodule Plug.Session do
      2   @moduledoc """
      3   A plug to handle session cookies and session stores.
      4 
      5   The session is accessed via functions on `Plug.Conn`. Cookies and
      6   session have to be fetched with `Plug.Conn.fetch_session/1` before the
      7   session can be accessed.
      8 
      9   The session is also lazy. Once configured, a cookie header with the
     10   session will only be sent to the client if something is written to the
     11   session in the first place.
     12 
     13   When using `Plug.Session`, also consider using `Plug.CSRFProtection`
     14   to avoid Cross Site Request Forgery attacks.
     15 
     16   ## Session stores
     17 
     18   See `Plug.Session.Store` for the specification session stores are required to
     19   implement.
     20 
     21   Plug ships with the following session stores:
     22 
     23     * `Plug.Session.ETS`
     24     * `Plug.Session.COOKIE`
     25 
     26   ## Options
     27 
     28     * `:store` - session store module (required);
     29     * `:key` - session cookie key (required);
     30     * `:domain` - see `Plug.Conn.put_resp_cookie/4`;
     31     * `:max_age` - see `Plug.Conn.put_resp_cookie/4`;
     32     * `:path` - see `Plug.Conn.put_resp_cookie/4`;
     33     * `:secure` - see `Plug.Conn.put_resp_cookie/4`;
     34     * `:http_only` - see `Plug.Conn.put_resp_cookie/4`;
     35     * `:same_site` - see `Plug.Conn.put_resp_cookie/4`;
     36     * `:extra` - see `Plug.Conn.put_resp_cookie/4`;
     37 
     38   Additional options can be given to the session store, see the store's
     39   documentation for the options it accepts.
     40 
     41   ## Examples
     42 
     43       plug Plug.Session, store: :ets, key: "_my_app_session", table: :session
     44   """
     45 
     46   alias Plug.Conn
     47   @behaviour Plug
     48 
     49   @cookie_opts [:domain, :max_age, :path, :secure, :http_only, :extra, :same_site]
     50 
     51   @impl true
     52   def init(opts) do
     53     store = Plug.Session.Store.get(Keyword.fetch!(opts, :store))
     54     key = Keyword.fetch!(opts, :key)
     55     cookie_opts = Keyword.take(opts, @cookie_opts)
     56     store_opts = Keyword.drop(opts, [:store, :key] ++ @cookie_opts)
     57     store_config = store.init(store_opts)
     58 
     59     %{
     60       store: store,
     61       store_config: store_config,
     62       key: key,
     63       cookie_opts: cookie_opts
     64     }
     65   end
     66 
     67   @impl true
     68   def call(conn, config) do
     69     Conn.put_private(conn, :plug_session_fetch, fetch_session(config))
     70   end
     71 
     72   defp fetch_session(config) do
     73     %{store: store, store_config: store_config, key: key} = config
     74 
     75     fn conn ->
     76       {sid, session} =
     77         if cookie = conn.cookies[key] do
     78           store.get(conn, cookie, store_config)
     79         else
     80           {nil, %{}}
     81         end
     82 
     83       session = Map.merge(session, Map.get(conn.private, :plug_session, %{}))
     84 
     85       conn
     86       |> Conn.put_private(:plug_session, session)
     87       |> Conn.put_private(:plug_session_fetch, :done)
     88       |> Conn.register_before_send(before_send(sid, config))
     89     end
     90   end
     91 
     92   defp before_send(sid, config) do
     93     fn conn ->
     94       case Map.get(conn.private, :plug_session_info) do
     95         :write ->
     96           value = put_session(sid, conn, config)
     97           put_cookie(value, conn, config)
     98 
     99         :drop ->
    100           drop_session(sid, conn, config)
    101 
    102         :renew ->
    103           renew_session(sid, conn, config)
    104 
    105         :ignore ->
    106           conn
    107 
    108         nil ->
    109           conn
    110       end
    111     end
    112   end
    113 
    114   defp drop_session(sid, conn, config) do
    115     if sid do
    116       delete_session(sid, conn, config)
    117       delete_cookie(conn, config)
    118     else
    119       conn
    120     end
    121   end
    122 
    123   defp renew_session(sid, conn, config) do
    124     if sid, do: delete_session(sid, conn, config)
    125     value = put_session(nil, conn, config)
    126     put_cookie(value, conn, config)
    127   end
    128 
    129   defp put_session(sid, conn, %{store: store, store_config: store_config}),
    130     do: store.put(conn, sid, conn.private[:plug_session], store_config)
    131 
    132   defp delete_session(sid, conn, %{store: store, store_config: store_config}),
    133     do: store.delete(conn, sid, store_config)
    134 
    135   defp put_cookie(value, conn, %{cookie_opts: cookie_opts, key: key}),
    136     do: Conn.put_resp_cookie(conn, key, value, cookie_opts)
    137 
    138   defp delete_cookie(conn, %{cookie_opts: cookie_opts, key: key}),
    139     do: Conn.delete_resp_cookie(conn, key, cookie_opts)
    140 end