defmodule TuskerPushWeb.PushController do alias TuskerPush.Forwarder use TuskerPushWeb, :controller require Logger def push(conn, %{"id" => id} = params) do with {:registration, registration} when not is_nil(registration) <- {:registration, TuskerPush.get_registration(id)}, :ok <- TuskerPush.check_registration_expired(registration), {:encoding, ["aesgcm"]} <- {:encoding, get_req_header(conn, "content-encoding")}, {:body, {:ok, body, conn}} <- {:body, read_body(conn)}, {:salt, salt} when not is_nil(salt) <- get_salt(conn), {:key, key} when not is_nil(key) <- get_key(conn), context <- Map.get(params, "context"), {:forward, :ok} <- {:forward, Forwarder.forward(registration, body, salt, key, context)} do send_resp(conn, 200, "ok") else {:registration, nil} -> send_resp(conn, 400, "unregistered") {:expired, registration} -> TuskerPush.unregister(registration) send_resp(conn, 400, "expired") {:encoding, encoding} -> Logger.warning("Unexpected encoding: #{inspect(encoding)}") send_resp(conn, 400, "bad encoding") {:body, {:more, _, conn}} -> Logger.error("Didn't finish reading") send_resp(conn, 500, "failed to read body") {:body, {:error, reason}} -> Logger.error("Reading body: #{inspect(reason)}") send_resp(conn, 500, "failed to read body") {:salt, nil} -> Logger.warning("Missing salt") send_resp(conn, 400, "missing salt") {:key, nil} -> Logger.warning("Missing key") send_resp(conn, 400, "missing key") {:forward, {:error, :device_token_unregistered}} -> Logger.debug("APNS device token unregistered, removing registration") TuskerPush.unregister(id) send_resp(conn, 400, "apns unregistered") {:forward, {:error, reason}} -> Logger.error("Sending notification: #{inspect(reason)}") send_resp(conn, 500, "failed to send") end end defp get_salt(conn) do conn |> get_req_header("encryption") |> case do ["salt=" <> salt] -> {:salt, salt} _ -> {:salt, nil} end end defp get_key(conn) do conn |> get_req_header("crypto-key") |> case do [value] -> dh = value |> String.split(";") |> Enum.find_value(fn "dh=" <> val -> val _ -> false end) {:key, dh} _ -> {:key, nil} end end end