neiam
/apollos_crib
It's Apollo's Crib
public · Issues · Pulls 1 · Labels · Forks · Compare · Actions failure · Badges · Packages
⭐
Log in to mark this repository.
Keryx: the keryx pages only reach the user's own
3994bbf · Gabe Morell · 2026-11-04 22:12
Message
{commit_body(@commit)}
Files changed
modified
apps/room_sanctum/lib/room_sanctum/configuration.ex
+3
−0
@@ -1213,6 +1213,9 @@ defmodule RoomSanctum.Configuration do
| 1213 | 1213 | """ |
| 1214 | 1214 | def get_keryx!(id), do: Repo.get!(Keryx, id) |
| 1215 | 1215 | |
| 1216 | + # Someone else's keryx raises the not-found a missing one does. | |
| 1217 | + def get_keryx!({:user, uid}, id), do: Repo.get_by!(Keryx, id: id, user_id: uid) | |
| 1218 | + | |
| 1216 | 1219 | @doc """ |
| 1217 | 1220 | Creates a keryx. |
| 1218 | 1221 |
modified
apps/room_sanctum/lib/room_sanctum_web/live/keryx_live/index.ex
+5
−2
@@ -20,7 +20,7 @@ defmodule RoomSanctumWeb.KeryxLive.Index do
| 20 | 20 | defp apply_action(socket, :edit, %{"id" => id}) do |
| 21 | 21 | socket |
| 22 | 22 | |> assign(:page_title, "Edit Keryx") |
| 23 | − |> assign(:keryx, Configuration.get_keryx!(id)) | |
| 23 | + |> assign(:keryx, Configuration.get_keryx!(owner(socket), id)) | |
| 24 | 24 | end |
| 25 | 25 | |
| 26 | 26 | defp apply_action(socket, :new, _params) do |
@@ -42,7 +42,7 @@ defmodule RoomSanctumWeb.KeryxLive.Index do
| 42 | 42 | |
| 43 | 43 | @impl true |
| 44 | 44 | def handle_event("delete", %{"id" => id}, socket) do |
| 45 | − keryx = Configuration.get_keryx!(id) | |
| 45 | + keryx = Configuration.get_keryx!(owner(socket), id) | |
| 46 | 46 | {:ok, _} = Configuration.delete_keryx(keryx) |
| 47 | 47 | |
| 48 | 48 | {:noreply, stream_delete(socket, :keryxiae, keryx)} |
@@ -51,4 +51,7 @@ defmodule RoomSanctumWeb.KeryxLive.Index do
| 51 | 51 | def handle_event("info", _params, socket) do |
| 52 | 52 | {:noreply, socket |> assign(:show_info, !socket.assigns.show_info)} |
| 53 | 53 | end |
| 54 | + | |
| 55 | + # Ids from the URL or the client are looked up among the user's own. | |
| 56 | + defp owner(socket), do: {:user, socket.assigns.current_user.id} | |
| 54 | 57 | end |
modified
apps/room_sanctum/lib/room_sanctum_web/live/keryx_live/show.ex
+8
−2
@@ -10,12 +10,13 @@ defmodule RoomSanctumWeb.KeryxLive.Show do
| 10 | 10 | # Set up periodic refresh of cached items |
| 11 | 11 | Process.send_after(self(), :refresh_cache, 1000) |
| 12 | 12 | end |
| 13 | + | |
| 13 | 14 | {:ok, socket} |
| 14 | 15 | end |
| 15 | 16 | |
| 16 | 17 | @impl true |
| 17 | 18 | def handle_params(%{"id" => id}, _, socket) do |
| 18 | − keryx = Configuration.get_keryx!(id) | |
| 19 | + keryx = Configuration.get_keryx!(owner(socket), id) | |
| 19 | 20 | queries = Configuration.get_queries!(keryx.query_ids) |
| 20 | 21 | cached_items = fetch_cached_items(keryx.id) |
| 21 | 22 |
@@ -73,7 +74,9 @@ defmodule RoomSanctumWeb.KeryxLive.Show do
| 73 | 74 | _ -> |
| 74 | 75 | # If Jason encoding fails, use inspect as fallback |
| 75 | 76 | inspected = inspect(data, pretty: true, limit: 2048) |
| 76 | − String.slice(inspected, 0..2048) <> if String.length(inspected) > 2048, do: "...", else: "" | |
| 77 | + | |
| 78 | + String.slice(inspected, 0..2048) <> | |
| 79 | + if String.length(inspected) > 2048, do: "...", else: "" | |
| 77 | 80 | end |
| 78 | 81 | end |
| 79 | 82 |
@@ -118,4 +121,7 @@ defmodule RoomSanctumWeb.KeryxLive.Show do
| 118 | 121 | # RabbitMQ shows an MQTT client the routing key with its dots as slashes. |
| 119 | 122 | defp mqtt_base(keryx), |
| 120 | 123 | do: keryx.id |> Keryx.topic() |> Keryx.mqtt_topic() |
| 124 | + | |
| 125 | + # The keryx comes from the URL, so it is looked up among the user's own. | |
| 126 | + defp owner(socket), do: {:user, socket.assigns.current_user.id} | |
| 121 | 127 | end |
modified
apps/room_sanctum/test/room_sanctum_web/live/ownership_test.exs
+34
−0
@@ -469,4 +469,38 @@ defmodule RoomSanctumWeb.OwnershipTest do
| 469 | 469 | assert Repo.reload(theirs) |
| 470 | 470 | end |
| 471 | 471 | end |
| 472 | + | |
| 473 | + describe "the keryx pages" do | |
| 474 | + setup ctx do | |
| 475 | + {:ok, theirs} = | |
| 476 | + Configuration.create_keryx(%{ | |
| 477 | + name: "their herald", | |
| 478 | + ttl: 60, | |
| 479 | + query_ids: [query_for(ctx.them).id], | |
| 480 | + user_id: ctx.them.id | |
| 481 | + }) | |
| 482 | + | |
| 483 | + %{theirs: theirs} | |
| 484 | + end | |
| 485 | + | |
| 486 | + test "will not show another user's keryx", ctx do | |
| 487 | + assert_raise Ecto.NoResultsError, fn -> | |
| 488 | + live(ctx.conn, Routes.keryx_show_path(ctx.conn, :show, ctx.theirs)) | |
| 489 | + end | |
| 490 | + end | |
| 491 | + | |
| 492 | + test "will not open another user's keryx for editing", ctx do | |
| 493 | + assert_raise Ecto.NoResultsError, fn -> | |
| 494 | + live(ctx.conn, Routes.keryx_index_path(ctx.conn, :edit, ctx.theirs)) | |
| 495 | + end | |
| 496 | + end | |
| 497 | + | |
| 498 | + test "will not delete another user's keryx", ctx do | |
| 499 | + {:ok, live, _html} = live(ctx.conn, Routes.keryx_index_path(ctx.conn, :index)) | |
| 500 | + | |
| 501 | + forge(live, "delete", %{"id" => to_string(ctx.theirs.id)}) | |
| 502 | + | |
| 503 | + assert Repo.reload(ctx.theirs) | |
| 504 | + end | |
| 505 | + end | |
| 472 | 506 | end |
Parents: d3734b5