89 lines
2.5 KiB
Elixir
89 lines
2.5 KiB
Elixir
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
|