From 198f2c3cbcaae4a68156d1f70aa29275872518cd Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Wed, 11 Mar 2026 09:46:22 -0500 Subject: [PATCH] feat: add API key setup help to integration configuration panels Add setup_help info boxes to each integration provider showing where to create API keys, step-by-step instructions, required permissions, and example URL patterns. --- lib/towerops_web/live/org/settings_live.ex | 76 +++++++++++- .../live/org/settings_live.html.heex | 114 ++++++++++++++++-- 2 files changed, 176 insertions(+), 14 deletions(-) diff --git a/lib/towerops_web/live/org/settings_live.ex b/lib/towerops_web/live/org/settings_live.ex index fe4093b8..e67609c0 100644 --- a/lib/towerops_web/live/org/settings_live.ex +++ b/lib/towerops_web/live/org/settings_live.ex @@ -27,27 +27,67 @@ defmodule ToweropsWeb.Org.SettingsLive do name: "Gaiia", description: "Billing and subscriber management. Enables outage impact analysis, inventory reconciliation, and subscriber-aware monitoring.", - icon: "hero-user-group" + icon: "hero-user-group", + setup_help: %{ + url_pattern: "https://app.gaiia.com/{your-org}/admin/apiKeys", + steps: [ + "Log into Gaiia and go to **Admin** → **API Keys**", + "Click **Create API Key**", + "Give it a descriptive name (e.g. \"TowerOps\")", + "Copy the generated API key and paste it below" + ], + permissions: + "Read-only access. The key only needs permission to read accounts, subscriptions, and inventory data." + } }, %{ id: "sonar", name: "Sonar", description: "Billing and subscriber management. Sync accounts, network sites, and inventory from your Sonar instance.", - icon: "hero-currency-dollar" + icon: "hero-currency-dollar", + setup_help: %{ + url_pattern: "https://{your-instance}.sonar.software/admin/users/{your-user-id}", + steps: [ + "Log into Sonar and go to **Settings** → **Security** → **API Tokens** (or your user profile → API Tokens)", + "Click **Create Token**", + "Name it (e.g. \"TowerOps\") and copy the generated token" + ], + permissions: + "Requires a **read-only** personal access token. The token needs access to: Accounts, Network Sites, Inventory Items, and Address data." + } }, %{ id: "splynx", name: "Splynx", description: "ISP billing and management platform. Sync customers, internet services, and network routers from Splynx.", - icon: "hero-banknotes" + icon: "hero-banknotes", + setup_help: %{ + url_pattern: "https://{your-instance}.splynx.app/admin/administration/api-keys", + steps: [ + "Log into Splynx and go to **Administration** → **API Keys**", + "Click **Add** to create a new API key", + "Copy both the **API Key** and **API Secret**" + ], + permissions: + "Requires read access to **Customers**, **Internet Services**, and **Routers**. No write permissions needed." + } }, %{ id: "visp", name: "VISP", description: "Cloud-based ISP management. Sync subscribers, sites, equipment, and MRR data from VISP.", - icon: "hero-cloud" + icon: "hero-cloud", + setup_help: %{ + url_pattern: "https://app.visp.net/settings/api", + steps: [ + "Log into VISP and go to **Settings** → **API**", + "Click **Generate New Key**", + "Name it (e.g. \"TowerOps\") and copy the generated API key" + ], + permissions: "Requires read-only API access to **Subscribers**, **Sites**, **Equipment**, and **Billing** data." + } }, # Quality of Experience %{ @@ -55,7 +95,16 @@ defmodule ToweropsWeb.Org.SettingsLive do name: "Preseem", description: "QoE monitoring and subscriber experience analytics for wireless ISPs.", icon: "hero-signal", - category: "Quality of Experience" + category: "Quality of Experience", + setup_help: %{ + url_pattern: "https://app.preseem.com/settings/api", + steps: [ + "Log into Preseem and go to **Settings** → **API**", + "Click **Generate API Key**", + "Copy the generated key and paste it below" + ], + permissions: "Read-only access. The key needs permission to read subscriber QoE metrics and access point data." + } }, # Incident Management %{ @@ -73,7 +122,18 @@ defmodule ToweropsWeb.Org.SettingsLive do description: "Infrastructure source of truth. Sync devices, sites, IP addresses, and interfaces between TowerOps and your NetBox instance.", icon: "hero-server-stack", - category: "Infrastructure & IPAM" + category: "Infrastructure & IPAM", + setup_help: %{ + url_pattern: "https://{your-netbox-instance}/user/api-tokens/", + steps: [ + "Log into NetBox and go to your **profile** (top right) → **API Tokens**", + "Click **Add a token**", + "Optionally set an expiry date and description (e.g. \"TowerOps\")", + "Copy the generated token" + ], + permissions: + "Requires **read** permission at minimum. If you want to push data to NetBox (bidirectional sync), the token also needs **write** permission." + } } ] @@ -686,6 +746,10 @@ defmodule ToweropsWeb.Org.SettingsLive do defp get_credential(_integration, _key), do: "" + defp format_help_step(text) do + String.replace(text, ~r/\*\*(.+?)\*\*/, "\\1") + end + defp current_integration(socket) do provider = socket.assigns.configuring Map.get(socket.assigns.integrations, provider) diff --git a/lib/towerops_web/live/org/settings_live.html.heex b/lib/towerops_web/live/org/settings_live.html.heex index 50158759..257a643a 100644 --- a/lib/towerops_web/live/org/settings_live.html.heex +++ b/lib/towerops_web/live/org/settings_live.html.heex @@ -1190,10 +1190,7 @@

- {t( - "Your NetBox instance URL and API token. The token needs read permission at minimum." - )} - {t("Write permission is required if you want to push data to NetBox.")} + {t("Your NetBox instance URL and API token.")}

@@ -1223,6 +1220,31 @@ />
+
+

+ <.icon name="hero-information-circle" class="h-4 w-4" /> + {t("How to create your API token")} +

+
    + <%= for step <- provider.setup_help.steps do %> +
  1. {raw(format_help_step(step))}
  2. + <% end %> +
+

+ <.icon + name="hero-shield-check" + class="h-3.5 w-3.5 inline -mt-0.5" + /> + {raw(format_help_step(provider.setup_help.permissions))} +

+

+ <.icon + name="hero-arrow-top-right-on-square" + class="h-3 w-3 inline -mt-0.5" + /> Example URL: + {provider.setup_help.url_pattern} +

+
<%!-- Sync Direction Section --%> @@ -1577,7 +1599,7 @@

- {t("Your Sonar instance URL and API token from the Sonar admin panel.")} + {t("Your Sonar instance URL and API token.")}

@@ -1607,6 +1629,31 @@ />
+
+

+ <.icon name="hero-information-circle" class="h-4 w-4" /> + {t("How to create your API token")} +

+
    + <%= for step <- provider.setup_help.steps do %> +
  1. {raw(format_help_step(step))}
  2. + <% end %> +
+

+ <.icon + name="hero-shield-check" + class="h-3.5 w-3.5 inline -mt-0.5" + /> + {raw(format_help_step(provider.setup_help.permissions))} +

+

+ <.icon + name="hero-arrow-top-right-on-square" + class="h-3 w-3 inline -mt-0.5" + /> Example URL: + {provider.setup_help.url_pattern} +

+
@@ -1682,9 +1729,7 @@

- {t( - "Your Splynx instance URL, API key, and API secret. Find these in Splynx under Administration → API Keys." - )} + {t("Your Splynx instance URL, API key, and API secret.")}

@@ -1729,6 +1774,31 @@
+
+

+ <.icon name="hero-information-circle" class="h-4 w-4" /> + {t("How to create your API key")} +

+
    + <%= for step <- provider.setup_help.steps do %> +
  1. {raw(format_help_step(step))}
  2. + <% end %> +
+

+ <.icon + name="hero-shield-check" + class="h-3.5 w-3.5 inline -mt-0.5" + /> + {raw(format_help_step(provider.setup_help.permissions))} +

+

+ <.icon + name="hero-arrow-top-right-on-square" + class="h-3 w-3 inline -mt-0.5" + /> Example URL: + {provider.setup_help.url_pattern} +

+
@@ -1826,6 +1896,34 @@
+ <%= if Map.has_key?(provider, :setup_help) && provider.id != "pagerduty" do %> +
+

+ <.icon name="hero-information-circle" class="h-4 w-4" /> + {t("How to create your API key")} +

+
    + <%= for step <- provider.setup_help.steps do %> +
  1. {raw(format_help_step(step))}
  2. + <% end %> +
+

+ <.icon + name="hero-shield-check" + class="h-3.5 w-3.5 inline -mt-0.5" + /> + {raw(format_help_step(provider.setup_help.permissions))} +

+

+ <.icon + name="hero-arrow-top-right-on-square" + class="h-3 w-3 inline -mt-0.5" + /> Example URL: + {provider.setup_help.url_pattern} +

+
+ <% end %> + <%= if provider.id == "pagerduty" do %>