tusker_push/lib/tusker_push_web/controllers/push_controller.ex

88 lines
2.4 KiB
Elixir
Raw Normal View History

2024-04-05 22:26:10 +00:00
defmodule TuskerPushWeb.PushController do
2024-04-06 19:02:18 +00:00
alias TuskerPush.Forwarder
2024-04-05 22:26:10 +00:00
use TuskerPushWeb, :controller
require Logger
def push(conn, %{"id" => id}) do
with {:registration, registration} when not is_nil(registration) <-
{:registration, TuskerPush.get_registration(id)},
:ok <- TuskerPush.check_registration_expired(registration),
2024-04-06 19:02:18 +00:00
{: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),
{:forward, :ok} <- {:forward, Forwarder.forward(registration, body, salt, key)} do
2024-04-05 22:26:10 +00:00
send_resp(conn, 200, "ok")
else
{:registration, nil} ->
send_resp(conn, 400, "unregistered")
{:expired, registration} ->
TuskerPush.unregister(registration)
send_resp(conn, 400, "expired")
2024-04-05 22:26:10 +00:00
2024-04-06 19:02:18 +00:00
{:encoding, encoding} ->
Logger.warning("Unexpected encoding: #{inspect(encoding)}")
send_resp(conn, 400, "bad encoding")
2024-04-05 22:26:10 +00:00
2024-04-06 19:02:18 +00:00
{:body, {:more, _, conn}} ->
Logger.error("Didn't finish reading")
2024-04-05 22:26:10 +00:00
send_resp(conn, 500, "failed to read body")
2024-04-06 19:02:18 +00:00
{:body, {:error, reason}} ->
2024-04-05 22:26:10 +00:00
Logger.error("Reading body: #{inspect(reason)}")
send_resp(conn, 500, "failed to read body")
2024-04-06 19:02:18 +00:00
{: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")
2024-04-06 19:02:18 +00:00
{: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}
2024-04-05 22:26:10 +00:00
end
end
end