Skip to main content

lib/kameleoon/cookie_accessor.ex

defmodule Kameleoon.CookieAccessor do
  @moduledoc """
  Behaviour for adapting framework-specific cookie containers to Kameleoon.
  """

  alias Kameleoon.Internal.Cookie

  @type state :: term()
  @type t :: {module(), state()}

  @callback get(state(), String.t()) :: String.t() | nil
  @callback set(
              state(),
              String.t(),
              String.t(),
              non_neg_integer(),
              String.t() | nil
            ) :: state()

  @request_cookie_keys [
    "kameleoonVisitorCode",
    "kameleoonSimulationFFData"
  ]

  @spec request_cookies(t()) :: %{optional(String.t()) => String.t()}
  def request_cookies({accessor, state}) when is_atom(accessor) do
    Map.new(@request_cookie_keys, fn key -> {key, accessor.get(state, key)} end)
    |> Enum.reject(fn {_key, value} -> is_nil(value) end)
    |> Map.new()
  end

  @spec apply_response_cookies(t(), Cookie.t() | nil) :: state()
  def apply_response_cookies({_accessor, state}, nil), do: state

  def apply_response_cookies({accessor, state}, %Cookie{response_cookies: response_cookies})
      when is_atom(accessor) do
    Enum.reduce(response_cookies, state, fn cookie, state ->
      accessor.set(
        state,
        cookie.key,
        cookie.value,
        cookie.max_age,
        cookie.top_level_domain
      )
    end)
  end
end