From 0fc36524b44f231b2c334372861ac740044ff52a Mon Sep 17 00:00:00 2001 From: Graham McIntie Date: Fri, 13 Feb 2026 19:49:12 -0600 Subject: [PATCH] fix: resolve 500 errors on /activity and /changelog - Activity feed: use schema modules instead of string table names in Ecto queries to fix UUID encoding (Postgrex expected binary, got string) - Changelog parser: remove plain hyphen from separator character class to prevent splitting on date hyphens (2026-02-13) --- lib/towerops/activity_feed.ex | 36 ++++++++++++++++------------ lib/towerops_web/changelog_parser.ex | 5 ++-- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/lib/towerops/activity_feed.ex b/lib/towerops/activity_feed.ex index 4e21c716..d01284b2 100644 --- a/lib/towerops/activity_feed.ex +++ b/lib/towerops/activity_feed.ex @@ -13,6 +13,12 @@ defmodule Towerops.ActivityFeed do import Ecto.Query + alias Towerops.Alerts.Alert + alias Towerops.ConfigChanges.ConfigChangeEvent + alias Towerops.Devices.Device + alias Towerops.Devices.Event, as: DeviceEvent + alias Towerops.Preseem.SyncLog + alias Towerops.Sites.Site alias Towerops.Repo @type activity_item :: %{ @@ -109,10 +115,10 @@ defmodule Towerops.ActivityFeed do defp fetch_source(:config_change, org_id, after_dt, before_dt, limit) do query = - from(c in "config_change_events", - join: d in "devices", + from(c in ConfigChangeEvent, + join: d in Device, on: d.id == c.device_id, - left_join: s in "sites", + left_join: s in Site, on: s.id == d.site_id, where: c.organization_id == ^org_id, select: %{ @@ -155,10 +161,10 @@ defmodule Towerops.ActivityFeed do defp fetch_source(:alert_fired, org_id, after_dt, before_dt, limit) do query = - from(a in "alerts", - join: d in "devices", + from(a in Alert, + join: d in Device, on: d.id == a.device_id, - left_join: s in "sites", + left_join: s in Site, on: s.id == d.site_id, where: d.organization_id == ^org_id, where: a.alert_type == "device_down", @@ -201,10 +207,10 @@ defmodule Towerops.ActivityFeed do defp fetch_source(:alert_resolved, org_id, after_dt, before_dt, limit) do query = - from(a in "alerts", - join: d in "devices", + from(a in Alert, + join: d in Device, on: d.id == a.device_id, - left_join: s in "sites", + left_join: s in Site, on: s.id == d.site_id, where: d.organization_id == ^org_id, where: not is_nil(a.resolved_at), @@ -247,10 +253,10 @@ defmodule Towerops.ActivityFeed do defp fetch_source(:device_event, org_id, after_dt, before_dt, limit) do query = - from(e in "device_events", - join: d in "devices", + from(e in DeviceEvent, + join: d in Device, on: d.id == e.device_id, - left_join: s in "sites", + left_join: s in Site, on: s.id == d.site_id, where: d.organization_id == ^org_id, select: %{ @@ -291,7 +297,7 @@ defmodule Towerops.ActivityFeed do defp fetch_source(:sync, org_id, after_dt, before_dt, limit) do query = - from(sl in "preseem_sync_logs", + from(sl in SyncLog, where: sl.organization_id == ^org_id, select: %{ id: sl.id, @@ -331,8 +337,8 @@ defmodule Towerops.ActivityFeed do defp fetch_source(:device_added, org_id, after_dt, before_dt, limit) do query = - from(d in "devices", - left_join: s in "sites", + from(d in Device, + left_join: s in Site, on: s.id == d.site_id, where: d.organization_id == ^org_id, select: %{ diff --git a/lib/towerops_web/changelog_parser.ex b/lib/towerops_web/changelog_parser.ex index de3d0cb7..747a1e9d 100644 --- a/lib/towerops_web/changelog_parser.ex +++ b/lib/towerops_web/changelog_parser.ex @@ -17,8 +17,9 @@ defmodule ToweropsWeb.ChangelogParser do |> Enum.reduce([], fn line, acc -> cond do # Date header with title: "2026-02-13 — Title" - Regex.match?(~r/^\d{4}-\d{2}-\d{2}\s*[—–-]\s*.+/, line) -> - [date_str, title] = String.split(line, ~r/\s*[—–-]\s*/, parts: 2) + Regex.match?(~r/^\d{4}-\d{2}-\d{2}\s+[—–]\s+.+/, line) -> + [date_str | rest] = String.split(line, ~r/\s+[—–]\s+/, parts: 2) + title = List.first(rest, "") entry = %{date: Date.from_iso8601!(String.trim(date_str)), title: String.trim(title), items: []} [entry | acc]