neiam
/oh-my-ex-oh-ircd
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
less angry
da770be · gmorell · 2026-06-11 17:04
Files changed
modified
lib/oh_my_ex_oh_ircd_web/controllers/scrobble_controller.ex
+5
−8
@@ -51,15 +51,12 @@ defmodule OhMyExOhIrcdWeb.ScrobbleController do
| 51 | 51 | defp respond(conn, {:error, _}), |
| 52 | 52 | do: conn |> put_status(:service_unavailable) |> json(%{error: "service_unavailable"}) |
| 53 | 53 | |
| 54 | − ## Validation — only who/artist/track/album, non-blank strings, capped, | |
| 55 | − ## with control chars stripped so nothing can forge an IRC line. | |
| 54 | + ## Validation — pick out artist/track/album (non-blank strings, capped, | |
| 55 | + ## with control chars stripped so nothing can forge an IRC line). Any | |
| 56 | + ## other keys in the body (including a client-supplied `who`, which is | |
| 57 | + ## token-bound) are ignored. | |
| 56 | 58 | |
| 57 | − defp validate(params) when is_map(params) do | |
| 58 | − case Map.keys(params) -- @allowed do | |
| 59 | − [] -> validate_fields(params) | |
| 60 | − extra -> {:error, "unexpected fields: #{Enum.join(extra, ", ")}"} | |
| 61 | − end | |
| 62 | − end | |
| 59 | + defp validate(params) when is_map(params), do: validate_fields(params) | |
| 63 | 60 | |
| 64 | 61 | defp validate(_), do: {:error, "body must be a JSON object"} |
| 65 | 62 |
modified
test/oh_my_ex_oh_ircd_web/controllers/scrobble_controller_test.exs
+15
−13
@@ -43,26 +43,28 @@ defmodule OhMyExOhIrcdWeb.ScrobbleControllerTest do
| 43 | 43 | assert body["error"] == "invalid_payload" |
| 44 | 44 | end |
| 45 | 45 | |
| 46 | − test "rejects a client-supplied who with 422 (who is token-bound)", %{conn: conn, token: token} do | |
| 47 | − body = | |
| 48 | − conn | |
| 49 | − |> auth(token) | |
| 50 | − |> post(~p"/api/v1/scrobble", Map.put(payload(), "who", "someone-else")) | |
| 51 | − |> json_response(422) | |
| 46 | + test "ignores a client-supplied who (who is token-bound)", %{conn: conn, token: token, chan: chan} do | |
| 47 | + {:ok, _} = Scrobbles.ensure_config(chan) | |
| 48 | + {:ok, _} = Scrobbles.set_joined(chan, true) | |
| 52 | 49 | |
| 53 | − assert body["error"] == "invalid_payload" | |
| 54 | − assert body["detail"] =~ "who" | |
| 50 | + conn = conn |> auth(token) |> post(~p"/api/v1/scrobble", Map.put(payload(), "who", "someone-else")) | |
| 51 | + assert json_response(conn, 200) == %{"status" => "ok"} | |
| 52 | + | |
| 53 | + assert [scrobble] = Scrobbles.recent(chan, 5) | |
| 54 | + assert scrobble.who == "gmp" | |
| 55 | 55 | end |
| 56 | 56 | |
| 57 | − test "rejects unexpected fields with 422", %{conn: conn, token: token} do | |
| 58 | − body = | |
| 57 | + test "ignores unexpected fields", %{conn: conn, token: token, chan: chan} do | |
| 58 | + {:ok, _} = Scrobbles.ensure_config(chan) | |
| 59 | + {:ok, _} = Scrobbles.set_joined(chan, true) | |
| 60 | + | |
| 61 | + conn = | |
| 59 | 62 | conn |
| 60 | 63 | |> auth(token) |
| 61 | 64 | |> post(~p"/api/v1/scrobble", Map.put(payload(), "evil", "\r\nPRIVMSG #x :hax")) |
| 62 | − |> json_response(422) | |
| 63 | 65 | |
| 64 | − assert body["error"] == "invalid_payload" | |
| 65 | − assert body["detail"] =~ "evil" | |
| 66 | + assert json_response(conn, 200) == %{"status" => "ok"} | |
| 67 | + assert [_scrobble] = Scrobbles.recent(chan, 5) | |
| 66 | 68 | end |
| 67 | 69 | |
| 68 | 70 | test "valid token but ScrobbleServ not joined returns 404", %{conn: conn, token: token} do |
Parents: ca8ee06