feat: migrate equipment features to gettext and fix sudo mode tests
Migrates all equipment-related flash messages to gettext for internationalization: - DeviceLive.Index: device discovery, reordering, error messages - DeviceLive.Show: backup messages, permission errors - DeviceLive.Form: device CRUD operations - AlertLive.Index: alert acknowledgment messages - SiteLive.Show: site discovery messages - SiteLive.Form: site CRUD and SNMP/agent propagation Fixes sudo mode test suite issues: - Updates Accounts.sudo_mode?/2 test to check last_sudo_at instead of authenticated_at - Adds register_and_log_in_user_with_sudo/1 helper to ConnCase - Fixes UserAuth sudo mode tests to use session-based authentication - Updates MyData tests to use sudo mode (now required per router config) - Removes obsolete UserSettingsLive "without sudo mode" test - Fixes grant_sudo_mode/1 DateTime truncation to seconds All equipment module tests passing. Ready for Phase 3 (Admin Features).
This commit is contained in:
parent
f6195cd5c6
commit
89a076fb67
18 changed files with 558 additions and 140 deletions
|
|
@ -675,7 +675,7 @@ defmodule Towerops.Accounts do
|
|||
{:ok, %User{last_sudo_at: ~U[2026-02-01 12:00:00Z]}}
|
||||
"""
|
||||
def grant_sudo_mode(%User{} = user) do
|
||||
now = DateTime.utc_now()
|
||||
now = DateTime.truncate(DateTime.utc_now(), :second)
|
||||
|
||||
with {:ok, updated_user} <-
|
||||
user
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ defmodule ToweropsWeb.AlertLive.Index do
|
|||
|
||||
case Alerts.get_alert(id) do
|
||||
nil ->
|
||||
{:noreply, put_flash(socket, :error, "Alert not found")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("Alert not found"))}
|
||||
|
||||
alert ->
|
||||
# Preload device and site to check organization access
|
||||
|
|
@ -49,7 +49,7 @@ defmodule ToweropsWeb.AlertLive.Index do
|
|||
if alert.device.site.organization_id == organization.id do
|
||||
perform_acknowledge_alert(socket, alert, user_id, organization.id)
|
||||
else
|
||||
{:noreply, put_flash(socket, :error, "You don't have access to this alert")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("You don't have access to this alert"))}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -59,11 +59,11 @@ defmodule ToweropsWeb.AlertLive.Index do
|
|||
{:ok, _alert} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Alert acknowledged")
|
||||
|> put_flash(:info, t_equipment("Alert acknowledged"))
|
||||
|> load_alerts(organization_id)}
|
||||
|
||||
{:error, _changeset} ->
|
||||
{:noreply, put_flash(socket, :error, "Unable to acknowledge alert")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("Unable to acknowledge alert"))}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ defmodule ToweropsWeb.DeviceLive.Form do
|
|||
if Enum.empty?(sites) do
|
||||
{:ok,
|
||||
socket
|
||||
|> put_flash(:info, "Please create a site before adding a device.")
|
||||
|> put_flash(:info, t_equipment("Please create a site before adding a device."))
|
||||
|> push_navigate(to: ~p"/sites/new")}
|
||||
else
|
||||
{:ok,
|
||||
|
|
@ -107,7 +107,7 @@ defmodule ToweropsWeb.DeviceLive.Form do
|
|||
case Devices.get_device(id) do
|
||||
nil ->
|
||||
socket
|
||||
|> put_flash(:error, "Device not found")
|
||||
|> put_flash(:error, t_equipment("Device not found"))
|
||||
|> push_navigate(to: ~p"/devices")
|
||||
|
||||
device ->
|
||||
|
|
@ -119,7 +119,7 @@ defmodule ToweropsWeb.DeviceLive.Form do
|
|||
apply_edit_action(socket, device)
|
||||
else
|
||||
socket
|
||||
|> put_flash(:error, "You don't have access to this device")
|
||||
|> put_flash(:error, t_equipment("You don't have access to this device"))
|
||||
|> push_navigate(to: ~p"/devices")
|
||||
end
|
||||
end
|
||||
|
|
@ -255,11 +255,11 @@ defmodule ToweropsWeb.DeviceLive.Form do
|
|||
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Device deleted successfully")
|
||||
|> put_flash(:info, t_equipment("Device deleted successfully"))
|
||||
|> push_navigate(to: ~p"/devices")}
|
||||
|
||||
{:error, _} ->
|
||||
{:noreply, put_flash(socket, :error, "Unable to delete device")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("Unable to delete device"))}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -295,10 +295,10 @@ defmodule ToweropsWeb.DeviceLive.Form do
|
|||
# Navigate to device show page where live updates will appear
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Discovery started...")
|
||||
|> put_flash(:info, t_equipment("Discovery started..."))
|
||||
|> push_navigate(to: ~p"/devices/#{device.id}")}
|
||||
else
|
||||
{:noreply, put_flash(socket, :error, "SNMP is not enabled for this device")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("SNMP is not enabled for this device"))}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -400,9 +400,9 @@ defmodule ToweropsWeb.DeviceLive.Form do
|
|||
|
||||
base_message =
|
||||
if device.snmp_enabled do
|
||||
"Device created. SNMP discovery started. "
|
||||
t_equipment("Device created. SNMP discovery started. ")
|
||||
else
|
||||
"Device created. "
|
||||
t_equipment("Device created. ")
|
||||
end
|
||||
|
||||
_ =
|
||||
|
|
@ -420,9 +420,9 @@ defmodule ToweropsWeb.DeviceLive.Form do
|
|||
defp handle_device_update(old_device, device) do
|
||||
if should_trigger_snmp_discovery?(old_device, device) do
|
||||
_ = enqueue_discovery(device.id)
|
||||
"Device updated successfully. SNMP discovery started in background."
|
||||
t_equipment("Device updated successfully. SNMP discovery started in background.")
|
||||
else
|
||||
"Device updated successfully"
|
||||
t_equipment("Device updated successfully")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ defmodule ToweropsWeb.DeviceLive.Index do
|
|||
|
||||
{:ok,
|
||||
socket
|
||||
|> assign(:page_title, "Devices")
|
||||
|> assign(:page_title, t_equipment("Devices"))
|
||||
|> assign(:timezone, socket.assigns.current_scope.timezone)
|
||||
|> assign(:device, device)
|
||||
|> assign(:grouped_devices, grouped_devices)
|
||||
|
|
@ -82,15 +82,16 @@ defmodule ToweropsWeb.DeviceLive.Index do
|
|||
snmp_devices = Enum.filter(devices, & &1.snmp_enabled)
|
||||
|
||||
if Enum.empty?(snmp_devices) do
|
||||
{:noreply, put_flash(socket, :error, "No SNMP-enabled devices found")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("No SNMP-enabled devices found"))}
|
||||
else
|
||||
Enum.each(snmp_devices, fn device ->
|
||||
enqueue_discovery(device.id)
|
||||
end)
|
||||
|
||||
count = length(snmp_devices)
|
||||
message = t_equipment("Discovery started for %{count} device", count: count) <> if count == 1, do: "", else: "s"
|
||||
|
||||
{:noreply, put_flash(socket, :info, "Discovery started for #{count} device#{if count == 1, do: "", else: "s"}")}
|
||||
{:noreply, put_flash(socket, :info, message)}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -101,13 +102,13 @@ defmodule ToweropsWeb.DeviceLive.Index do
|
|||
# Verify site belongs to current organization
|
||||
case Sites.get_site(site_id) do
|
||||
nil ->
|
||||
{:noreply, put_flash(socket, :error, "Site not found")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("Site not found"))}
|
||||
|
||||
site ->
|
||||
if site.organization_id == organization.id do
|
||||
perform_site_reorder(socket, site_id, new_position, organization.id)
|
||||
else
|
||||
{:noreply, put_flash(socket, :error, "You don't have access to this site")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("You don't have access to this site"))}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -119,7 +120,7 @@ defmodule ToweropsWeb.DeviceLive.Index do
|
|||
# Verify device belongs to current organization
|
||||
case Devices.get_device(device_id) do
|
||||
nil ->
|
||||
{:noreply, put_flash(socket, :error, "Device not found")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("Device not found"))}
|
||||
|
||||
device ->
|
||||
# Preload site to check organization access
|
||||
|
|
@ -128,7 +129,7 @@ defmodule ToweropsWeb.DeviceLive.Index do
|
|||
if device.site.organization_id == organization.id do
|
||||
perform_device_reorder(socket, device_id, new_position, organization.id)
|
||||
else
|
||||
{:noreply, put_flash(socket, :error, "You don't have access to this device")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("You don't have access to this device"))}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -153,7 +154,7 @@ defmodule ToweropsWeb.DeviceLive.Index do
|
|||
socket
|
||||
|> assign(:device, devices)
|
||||
|> assign(:grouped_devices, grouped_devices)
|
||||
|> put_flash(:info, "Order reset to alphabetical")}
|
||||
|> put_flash(:info, t_equipment("Order reset to alphabetical"))}
|
||||
end
|
||||
|
||||
def handle_event("add_discovered_device", params, socket) do
|
||||
|
|
@ -183,10 +184,10 @@ defmodule ToweropsWeb.DeviceLive.Index do
|
|||
socket
|
||||
|> assign(:device, devices)
|
||||
|> assign(:grouped_devices, grouped_devices)
|
||||
|> put_flash(:info, "Site order updated")}
|
||||
|> put_flash(:info, t_equipment("Site order updated"))}
|
||||
|
||||
{:error, _changeset} ->
|
||||
{:noreply, put_flash(socket, :error, "Failed to reorder site")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("Failed to reorder site"))}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -204,10 +205,10 @@ defmodule ToweropsWeb.DeviceLive.Index do
|
|||
socket
|
||||
|> assign(:device, devices)
|
||||
|> assign(:grouped_devices, grouped_devices)
|
||||
|> put_flash(:info, "Device order updated")}
|
||||
|> put_flash(:info, t_equipment("Device order updated"))}
|
||||
|
||||
{:error, _changeset} ->
|
||||
{:noreply, put_flash(socket, :error, "Failed to reorder device")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("Failed to reorder device"))}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
nil ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:error, "Device not found")
|
||||
|> put_flash(:error, t_equipment("Device not found"))
|
||||
|> push_navigate(to: ~p"/devices")}
|
||||
|
||||
device ->
|
||||
|
|
@ -70,7 +70,7 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
else
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:error, "You don't have access to this device")
|
||||
|> put_flash(:error, t_equipment("You don't have access to this device"))
|
||||
|> push_navigate(to: ~p"/devices")}
|
||||
end
|
||||
end
|
||||
|
|
@ -84,7 +84,7 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
# Device was deleted, don't schedule another refresh
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:error, "Device no longer exists")
|
||||
|> put_flash(:error, t_equipment("Device no longer exists"))
|
||||
|> push_navigate(to: ~p"/devices")}
|
||||
|
||||
_device ->
|
||||
|
|
@ -103,7 +103,7 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
{:noreply,
|
||||
socket
|
||||
|> load_equipment_data(socket.assigns.device.id)
|
||||
|> put_flash(:info, "Discovery completed")}
|
||||
|> put_flash(:info, t_equipment("Discovery completed"))}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
|
@ -956,7 +956,7 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
|
||||
{:noreply, push_event(socket, "download", %{content: config_text, filename: filename, mime_type: "text/plain"})}
|
||||
else
|
||||
{:noreply, put_flash(socket, :error, "You don't have permission to access this backup")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("You don't have permission to access this backup"))}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -967,7 +967,7 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
|
||||
case MikrotikBackups.get_latest_backup(device_id) do
|
||||
nil ->
|
||||
{:noreply, put_flash(socket, :error, "No other backups available for comparison")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("No other backups available for comparison"))}
|
||||
|
||||
latest when latest.id == backup.id ->
|
||||
# Compare with second-latest
|
||||
|
|
@ -979,7 +979,7 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
)}
|
||||
|
||||
_ ->
|
||||
{:noreply, put_flash(socket, :error, "No other backups available for comparison")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("No other backups available for comparison"))}
|
||||
end
|
||||
|
||||
latest ->
|
||||
|
|
@ -997,10 +997,11 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
|
||||
cond do
|
||||
is_nil(agent_token_id) ->
|
||||
{:noreply, put_flash(socket, :error, "Device has no agent assigned. Assign an agent to create backups.")}
|
||||
{:noreply,
|
||||
put_flash(socket, :error, t_equipment("Device has no agent assigned. Assign an agent to create backups."))}
|
||||
|
||||
!device.mikrotik_enabled ->
|
||||
{:noreply, put_flash(socket, :error, "MikroTik API is not enabled for this device.")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("MikroTik API is not enabled for this device."))}
|
||||
|
||||
true ->
|
||||
trigger_manual_backup(socket, device, agent_token_id)
|
||||
|
|
@ -1045,11 +1046,11 @@ defmodule ToweropsWeb.DeviceLive.Show do
|
|||
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Manual backup requested. Results will appear shortly.")
|
||||
|> put_flash(:info, t_equipment("Manual backup requested. Results will appear shortly."))
|
||||
|> load_equipment_data(device.id)}
|
||||
|
||||
{:error, _reason} ->
|
||||
{:noreply, put_flash(socket, :error, "Failed to create backup request. Please try again.")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("Failed to create backup request. Please try again."))}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -85,11 +85,11 @@ defmodule ToweropsWeb.SiteLive.Form do
|
|||
{:ok, _} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Site deleted successfully")
|
||||
|> put_flash(:info, t_equipment("Site deleted successfully"))
|
||||
|> push_navigate(to: ~p"/sites")}
|
||||
|
||||
{:error, _} ->
|
||||
{:noreply, put_flash(socket, :error, "Unable to delete site")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("Unable to delete site"))}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -97,14 +97,20 @@ defmodule ToweropsWeb.SiteLive.Form do
|
|||
def handle_event("apply_snmp_to_all", _params, socket) do
|
||||
{count, _} = Sites.apply_snmp_config_to_all_equipment(socket.assigns.site.id)
|
||||
|
||||
{:noreply, put_flash(socket, :info, "Applied SNMP configuration to #{count} device records at this site")}
|
||||
{:noreply,
|
||||
put_flash(
|
||||
socket,
|
||||
:info,
|
||||
t_equipment("Applied SNMP configuration to %{count} device records at this site", count: count)
|
||||
)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("apply_agent_to_all", _params, socket) do
|
||||
{count, _} = Sites.apply_agent_to_all_equipment(socket.assigns.site.id)
|
||||
|
||||
{:noreply, put_flash(socket, :info, "Applied agent to #{count} device records at this site")}
|
||||
{:noreply,
|
||||
put_flash(socket, :info, t_equipment("Applied agent to %{count} device records at this site", count: count))}
|
||||
end
|
||||
|
||||
defp save_site(socket, :new, site_params) do
|
||||
|
|
@ -114,7 +120,7 @@ defmodule ToweropsWeb.SiteLive.Form do
|
|||
{:ok, site} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Site created successfully! Now add your first device.")
|
||||
|> put_flash(:info, t_equipment("Site created successfully! Now add your first device."))
|
||||
|> push_navigate(to: ~p"/sites/#{site.id}")}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
|
|
@ -127,7 +133,7 @@ defmodule ToweropsWeb.SiteLive.Form do
|
|||
{:ok, _site} ->
|
||||
{:noreply,
|
||||
socket
|
||||
|> put_flash(:info, "Site updated successfully")
|
||||
|> put_flash(:info, t_equipment("Site updated successfully"))
|
||||
|> push_navigate(to: ~p"/sites")}
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ defmodule ToweropsWeb.SiteLive.Show do
|
|||
snmp_devices = Enum.filter(devices, & &1.snmp_enabled)
|
||||
|
||||
if Enum.empty?(snmp_devices) do
|
||||
{:noreply, put_flash(socket, :error, "No SNMP-enabled devices at this site")}
|
||||
{:noreply, put_flash(socket, :error, t_equipment("No SNMP-enabled devices at this site"))}
|
||||
else
|
||||
# Enqueue discovery for all SNMP-enabled devices
|
||||
Enum.each(snmp_devices, fn device ->
|
||||
|
|
@ -42,13 +42,9 @@ defmodule ToweropsWeb.SiteLive.Show do
|
|||
end)
|
||||
|
||||
count = length(snmp_devices)
|
||||
message = t_equipment("Discovery started for %{count} device", count: count) <> if count == 1, do: "", else: "s"
|
||||
|
||||
{:noreply,
|
||||
put_flash(
|
||||
socket,
|
||||
:info,
|
||||
"Discovery started for #{count} device#{if count == 1, do: "", else: "s"}"
|
||||
)}
|
||||
{:noreply, put_flash(socket, :info, message)}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Language: en\n"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:115
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:133
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Accept invitation and create account"
|
||||
msgstr ""
|
||||
|
|
@ -35,12 +35,12 @@ msgstr ""
|
|||
msgid "Confirm new password"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:115
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:134
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Create an account"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:114
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:128
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Creating account..."
|
||||
msgstr ""
|
||||
|
|
@ -50,10 +50,10 @@ msgstr ""
|
|||
msgid "Don't have an account?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:52
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:55
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:17
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:50
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:94
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:55
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
|
@ -68,7 +68,7 @@ msgstr ""
|
|||
msgid "Enter your new password below."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:67
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:72
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Forgot password?"
|
||||
msgstr ""
|
||||
|
|
@ -78,13 +78,13 @@ msgstr ""
|
|||
msgid "Forgot your password?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:31
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Free tier includes:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:89
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:107
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:92
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I agree to the %{link}"
|
||||
msgstr ""
|
||||
|
|
@ -96,12 +96,12 @@ msgstr ""
|
|||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:16
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:5
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:72
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:77
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Log in"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:71
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:74
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "My Company"
|
||||
msgstr ""
|
||||
|
|
@ -111,18 +111,18 @@ msgstr ""
|
|||
msgid "New password"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:70
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:73
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Organization Name"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:60
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:58
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:63
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:63
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:89
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:95
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy Policy"
|
||||
msgstr ""
|
||||
|
|
@ -138,7 +138,7 @@ msgstr ""
|
|||
msgid "Reset password"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:99
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:104
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Send me a login link instead"
|
||||
msgstr ""
|
||||
|
|
@ -153,7 +153,7 @@ msgstr ""
|
|||
msgid "Sign up"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:107
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Terms of Service"
|
||||
msgstr ""
|
||||
|
|
@ -183,7 +183,7 @@ msgstr ""
|
|||
msgid "for an account now."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:37
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:40
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "the mailbox page"
|
||||
msgstr ""
|
||||
|
|
@ -193,22 +193,22 @@ msgstr ""
|
|||
msgid "to your account now."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:34
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Monitor up to 10 devices"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:37
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:40
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ No credit card required"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:36
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:39
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Performance charts and historical data"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:35
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Real-time alerts and notifications"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ msgstr ""
|
|||
msgid "close"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:83
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ msgstr ""
|
|||
"Language: en\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:115
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:133
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Accept invitation and create account"
|
||||
msgstr "Accept invitation and create account"
|
||||
|
|
@ -32,12 +32,12 @@ msgstr "Back to log in"
|
|||
msgid "Confirm new password"
|
||||
msgstr "Confirm new password"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:115
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:134
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Create an account"
|
||||
msgstr "Create an account"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:114
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:128
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Creating account..."
|
||||
msgstr "Creating account..."
|
||||
|
|
@ -47,10 +47,10 @@ msgstr "Creating account..."
|
|||
msgid "Don't have an account?"
|
||||
msgstr "Don't have an account?"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:52
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:55
|
||||
#: lib/towerops_web/controllers/user_reset_password_html/new.html.heex:17
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:50
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:94
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:55
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Email"
|
||||
msgstr "Email"
|
||||
|
|
@ -65,7 +65,7 @@ msgstr "Enter your email address and we'll send you a link to reset your passwor
|
|||
msgid "Enter your new password below."
|
||||
msgstr "Enter your new password below."
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:67
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:72
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Forgot password?"
|
||||
msgstr "Forgot password?"
|
||||
|
|
@ -75,13 +75,13 @@ msgstr "Forgot password?"
|
|||
msgid "Forgot your password?"
|
||||
msgstr "Forgot your password?"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:31
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Free tier includes:"
|
||||
msgstr "Free tier includes:"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:89
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:107
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:92
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I agree to the %{link}"
|
||||
msgstr "I agree to the %{link}"
|
||||
|
|
@ -93,12 +93,12 @@ msgstr "Join %{organization}"
|
|||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:16
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:5
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:72
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:77
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Log in"
|
||||
msgstr "Log in"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:71
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:74
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "My Company"
|
||||
msgstr "My Company"
|
||||
|
|
@ -108,18 +108,18 @@ msgstr "My Company"
|
|||
msgid "New password"
|
||||
msgstr "New password"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:70
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:73
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Organization Name"
|
||||
msgstr "Organization Name"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:60
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:58
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:63
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:63
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Password"
|
||||
msgstr "Password"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:89
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:95
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy Policy"
|
||||
msgstr "Privacy Policy"
|
||||
|
|
@ -135,7 +135,7 @@ msgstr "Register for an account"
|
|||
msgid "Reset password"
|
||||
msgstr "Reset password"
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:99
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:104
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Send me a login link instead"
|
||||
msgstr "Send me a login link instead"
|
||||
|
|
@ -150,7 +150,7 @@ msgstr "Send reset instructions"
|
|||
msgid "Sign up"
|
||||
msgstr "Sign up"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:107
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Terms of Service"
|
||||
msgstr "Terms of Service"
|
||||
|
|
@ -180,7 +180,7 @@ msgstr "You've been invited to join %{organization} as a %{role}."
|
|||
msgid "for an account now."
|
||||
msgstr "for an account now."
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:37
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:40
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "the mailbox page"
|
||||
msgstr "the mailbox page"
|
||||
|
|
@ -190,22 +190,22 @@ msgstr "the mailbox page"
|
|||
msgid "to your account now."
|
||||
msgstr "to your account now."
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:34
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Monitor up to 10 devices"
|
||||
msgstr "✓ Monitor up to 10 devices"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:37
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:40
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ No credit card required"
|
||||
msgstr "✓ No credit card required"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:36
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:39
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Performance charts and historical data"
|
||||
msgstr "✓ Performance charts and historical data"
|
||||
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:35
|
||||
#: lib/towerops_web/controllers/user_registration_html/new.html.heex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "✓ Real-time alerts and notifications"
|
||||
msgstr "✓ Real-time alerts and notifications"
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ msgstr "We can't find the internet"
|
|||
msgid "close"
|
||||
msgstr "close"
|
||||
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:83
|
||||
#: lib/towerops_web/controllers/user_session_html/new.html.heex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "or"
|
||||
msgstr "or"
|
||||
|
|
|
|||
|
|
@ -10,3 +10,209 @@ msgid ""
|
|||
msgstr ""
|
||||
"Language: en\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:405
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device created. "
|
||||
msgstr "Device created. "
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:403
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device created. SNMP discovery started. "
|
||||
msgstr "Device created. SNMP discovery started. "
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:258
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device deleted successfully"
|
||||
msgstr "Device deleted successfully"
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:1001
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device has no agent assigned. Assign an agent to create backups."
|
||||
msgstr "Device has no agent assigned. Assign an agent to create backups."
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:87
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device no longer exists"
|
||||
msgstr "Device no longer exists"
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:110
|
||||
#: lib/towerops_web/live/device_live/index.ex:123
|
||||
#: lib/towerops_web/live/device_live/show.ex:54
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device not found"
|
||||
msgstr "Device not found"
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:208
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device order updated"
|
||||
msgstr "Device order updated"
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:425
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device updated successfully"
|
||||
msgstr "Device updated successfully"
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:423
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device updated successfully. SNMP discovery started in background."
|
||||
msgstr "Device updated successfully. SNMP discovery started in background."
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Devices"
|
||||
msgstr "Devices"
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:106
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Discovery completed"
|
||||
msgstr "Discovery completed"
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:92
|
||||
#: lib/towerops_web/live/site_live/show.ex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Discovery started for %{count} device"
|
||||
msgstr "Discovery started for %{count} device"
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:298
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Discovery started..."
|
||||
msgstr "Discovery started..."
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:1053
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to create backup request. Please try again."
|
||||
msgstr "Failed to create backup request. Please try again."
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:211
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to reorder device"
|
||||
msgstr "Failed to reorder device"
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:190
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to reorder site"
|
||||
msgstr "Failed to reorder site"
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:1049
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Manual backup requested. Results will appear shortly."
|
||||
msgstr "Manual backup requested. Results will appear shortly."
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:1004
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "MikroTik API is not enabled for this device."
|
||||
msgstr "MikroTik API is not enabled for this device."
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:85
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No SNMP-enabled devices found"
|
||||
msgstr "No SNMP-enabled devices found"
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:970
|
||||
#: lib/towerops_web/live/device_live/show.ex:982
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No other backups available for comparison"
|
||||
msgstr "No other backups available for comparison"
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:157
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Order reset to alphabetical"
|
||||
msgstr "Order reset to alphabetical"
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please create a site before adding a device."
|
||||
msgstr "Please create a site before adding a device."
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:301
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "SNMP is not enabled for this device"
|
||||
msgstr "SNMP is not enabled for this device"
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:105
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Site not found"
|
||||
msgstr "Site not found"
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:187
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Site order updated"
|
||||
msgstr "Site order updated"
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unable to delete device"
|
||||
msgstr "Unable to delete device"
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:122
|
||||
#: lib/towerops_web/live/device_live/index.ex:132
|
||||
#: lib/towerops_web/live/device_live/show.ex:73
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You don't have access to this device"
|
||||
msgstr "You don't have access to this device"
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:111
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You don't have access to this site"
|
||||
msgstr "You don't have access to this site"
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:959
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You don't have permission to access this backup"
|
||||
msgstr "You don't have permission to access this backup"
|
||||
|
||||
#: lib/towerops_web/live/alert_live/index.ex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Alert acknowledged"
|
||||
msgstr "Alert acknowledged"
|
||||
|
||||
#: lib/towerops_web/live/alert_live/index.ex:43
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Alert not found"
|
||||
msgstr "Site not found"
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:104
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Applied SNMP configuration to %{count} device records at this site"
|
||||
msgstr "Applied SNMP configuration to %{count} device records at this site"
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:113
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Applied agent to %{count} device records at this site"
|
||||
msgstr "Applied agent to %{count} device records at this site"
|
||||
|
||||
#: lib/towerops_web/live/site_live/show.ex:37
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No SNMP-enabled devices at this site"
|
||||
msgstr "No SNMP-enabled devices found"
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:123
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Site created successfully! Now add your first device."
|
||||
msgstr "Site created successfully! Now add your first device."
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:88
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Site deleted successfully"
|
||||
msgstr "Device deleted successfully"
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:136
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Site updated successfully"
|
||||
msgstr "Device updated successfully"
|
||||
|
||||
#: lib/towerops_web/live/alert_live/index.ex:66
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unable to acknowledge alert"
|
||||
msgstr "Unable to acknowledge alert"
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:92
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Unable to delete site"
|
||||
msgstr "Unable to delete device"
|
||||
|
||||
#: lib/towerops_web/live/alert_live/index.ex:52
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "You don't have access to this alert"
|
||||
msgstr "You don't have access to this site"
|
||||
|
|
|
|||
|
|
@ -13,3 +13,209 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Language: en\n"
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:405
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device created. "
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:403
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device created. SNMP discovery started. "
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:258
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:1001
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device has no agent assigned. Assign an agent to create backups."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:87
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device no longer exists"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:110
|
||||
#: lib/towerops_web/live/device_live/index.ex:123
|
||||
#: lib/towerops_web/live/device_live/show.ex:54
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device not found"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:208
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device order updated"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:425
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device updated successfully"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:423
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device updated successfully. SNMP discovery started in background."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Devices"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:106
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Discovery completed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:92
|
||||
#: lib/towerops_web/live/site_live/show.ex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Discovery started for %{count} device"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:298
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Discovery started..."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:1053
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to create backup request. Please try again."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:211
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to reorder device"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:190
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to reorder site"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:1049
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Manual backup requested. Results will appear shortly."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:1004
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "MikroTik API is not enabled for this device."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:85
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No SNMP-enabled devices found"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:970
|
||||
#: lib/towerops_web/live/device_live/show.ex:982
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No other backups available for comparison"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:157
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Order reset to alphabetical"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please create a site before adding a device."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:301
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "SNMP is not enabled for this device"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:105
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Site not found"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:187
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Site order updated"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unable to delete device"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/form.ex:122
|
||||
#: lib/towerops_web/live/device_live/index.ex:132
|
||||
#: lib/towerops_web/live/device_live/show.ex:73
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You don't have access to this device"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/index.ex:111
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You don't have access to this site"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/device_live/show.ex:959
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You don't have permission to access this backup"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/alert_live/index.ex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Alert acknowledged"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/alert_live/index.ex:43
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Alert not found"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:104
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Applied SNMP configuration to %{count} device records at this site"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:113
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Applied agent to %{count} device records at this site"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/site_live/show.ex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No SNMP-enabled devices at this site"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:123
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Site created successfully! Now add your first device."
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Site deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:136
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Site updated successfully"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/alert_live/index.ex:66
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unable to acknowledge alert"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/site_live/form.ex:92
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unable to delete site"
|
||||
msgstr ""
|
||||
|
||||
#: lib/towerops_web/live/alert_live/index.ex:52
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You don't have access to this alert"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -58,6 +58,25 @@ defmodule ToweropsWeb.ConnCase do
|
|||
%{conn: log_in_user(conn, user, opts), user: user, scope: scope}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Registers and logs in a user with sudo mode enabled.
|
||||
|
||||
It stores an updated connection and a registered user in the
|
||||
test context.
|
||||
"""
|
||||
def register_and_log_in_user_with_sudo(%{conn: conn} = context) do
|
||||
user = Towerops.AccountsFixtures.user_fixture()
|
||||
{:ok, user} = Towerops.Accounts.grant_sudo_mode(user)
|
||||
scope = Scope.for_user(user)
|
||||
|
||||
opts =
|
||||
context
|
||||
|> Map.take([:token_authenticated_at])
|
||||
|> Enum.to_list()
|
||||
|
||||
%{conn: log_in_user(conn, user, opts), user: user, scope: scope}
|
||||
end
|
||||
|
||||
@doc """
|
||||
Logs the given `user` into the `conn`.
|
||||
|
||||
|
|
|
|||
|
|
@ -94,17 +94,17 @@ defmodule Towerops.AccountsTest do
|
|||
end
|
||||
|
||||
describe "sudo_mode?/2" do
|
||||
test "validates the authenticated_at time" do
|
||||
test "validates the last_sudo_at time" do
|
||||
now = DateTime.utc_now()
|
||||
|
||||
assert Accounts.sudo_mode?(%User{authenticated_at: DateTime.utc_now()})
|
||||
assert Accounts.sudo_mode?(%User{authenticated_at: DateTime.add(now, -19, :minute)})
|
||||
refute Accounts.sudo_mode?(%User{authenticated_at: DateTime.add(now, -21, :minute)})
|
||||
assert Accounts.sudo_mode?(%User{last_sudo_at: DateTime.utc_now()})
|
||||
assert Accounts.sudo_mode?(%User{last_sudo_at: DateTime.add(now, -9, :minute)})
|
||||
refute Accounts.sudo_mode?(%User{last_sudo_at: DateTime.add(now, -11, :minute)})
|
||||
|
||||
# minute override
|
||||
refute Accounts.sudo_mode?(
|
||||
%User{authenticated_at: DateTime.add(now, -11, :minute)},
|
||||
-10
|
||||
%User{last_sudo_at: DateTime.add(now, -6, :minute)},
|
||||
-5
|
||||
)
|
||||
|
||||
# not authenticated
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ defmodule ToweropsWeb.AccountLive.MyDataTest do
|
|||
|
||||
import Phoenix.LiveViewTest
|
||||
|
||||
setup :register_and_log_in_user
|
||||
setup :register_and_log_in_user_with_sudo
|
||||
|
||||
describe "My Data page" do
|
||||
test "renders for organization owner without additional data", %{conn: conn} do
|
||||
|
|
|
|||
|
|
@ -6,17 +6,6 @@ defmodule ToweropsWeb.UserSettingsLiveTest do
|
|||
|
||||
alias Towerops.Accounts
|
||||
|
||||
describe "UserSettingsLive without sudo mode" do
|
||||
setup :register_and_log_in_user
|
||||
|
||||
test "allows access without sudo mode", %{conn: conn} do
|
||||
# User settings page is accessible without sudo mode
|
||||
{:ok, _view, html} = live(conn, ~p"/users/settings")
|
||||
|
||||
assert html =~ "Account Settings"
|
||||
end
|
||||
end
|
||||
|
||||
describe "UserSettingsLive with sudo mode" do
|
||||
setup :register_and_log_in_user_with_sudo
|
||||
|
||||
|
|
@ -177,19 +166,4 @@ defmodule ToweropsWeb.UserSettingsLiveTest do
|
|||
assert html =~ "Login History"
|
||||
end
|
||||
end
|
||||
|
||||
# Helper to register user and grant sudo mode
|
||||
# Note: user_fixture() already creates users with TOTP enabled by default
|
||||
defp register_and_log_in_user_with_sudo(%{conn: conn}) do
|
||||
user = user_fixture()
|
||||
|
||||
# Log in and grant sudo mode
|
||||
conn =
|
||||
conn
|
||||
|> log_in_user(user)
|
||||
|> init_test_session(%{})
|
||||
|> put_session(:user_sudo_granted_at, System.system_time(:second))
|
||||
|
||||
%{conn: conn, user: user}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -883,11 +883,14 @@ defmodule ToweropsWeb.UserAuthTest do
|
|||
{:ok, _device, _secret} =
|
||||
Accounts.create_totp_device(user.id, "Test Device", NimbleTOTP.secret())
|
||||
|
||||
# Create session with user token
|
||||
token = Accounts.generate_user_session_token(user)
|
||||
session = %{"user_token" => token}
|
||||
|
||||
socket = %Socket{assigns: %{__changed__: %{}, flash: %{}}}
|
||||
socket = Phoenix.Component.assign(socket, :current_scope, Scope.for_user(user))
|
||||
|
||||
assert {:halt, redirected_socket} =
|
||||
UserAuth.on_mount(:require_sudo_mode, %{}, %{}, socket)
|
||||
UserAuth.on_mount(:require_sudo_mode, %{}, session, socket)
|
||||
|
||||
assert Phoenix.Flash.get(redirected_socket.assigns.flash, :error) =~ "verify your identity"
|
||||
end
|
||||
|
|
@ -895,11 +898,14 @@ defmodule ToweropsWeb.UserAuthTest do
|
|||
test "redirects to TOTP enrollment when sudo mode expired and no TOTP" do
|
||||
user = user_fixture(enable_totp: false)
|
||||
|
||||
# Create session with user token
|
||||
token = Accounts.generate_user_session_token(user)
|
||||
session = %{"user_token" => token}
|
||||
|
||||
socket = %Socket{assigns: %{__changed__: %{}, flash: %{}}}
|
||||
socket = Phoenix.Component.assign(socket, :current_scope, Scope.for_user(user))
|
||||
|
||||
assert {:halt, redirected_socket} =
|
||||
UserAuth.on_mount(:require_sudo_mode, %{}, %{}, socket)
|
||||
UserAuth.on_mount(:require_sudo_mode, %{}, session, socket)
|
||||
|
||||
assert Phoenix.Flash.get(redirected_socket.assigns.flash, :error) =~ "Two-factor authentication"
|
||||
end
|
||||
|
|
@ -908,10 +914,13 @@ defmodule ToweropsWeb.UserAuthTest do
|
|||
user = user_fixture()
|
||||
{:ok, user} = Accounts.grant_sudo_mode(user)
|
||||
|
||||
socket = %Socket{assigns: %{__changed__: %{}, flash: %{}}}
|
||||
socket = Phoenix.Component.assign(socket, :current_scope, Scope.for_user(user))
|
||||
# Create session with user token
|
||||
token = Accounts.generate_user_session_token(user)
|
||||
session = %{"user_token" => token}
|
||||
|
||||
assert {:cont, _socket} = UserAuth.on_mount(:require_sudo_mode, %{}, %{}, socket)
|
||||
socket = %Socket{assigns: %{__changed__: %{}, flash: %{}}}
|
||||
|
||||
assert {:cont, _socket} = UserAuth.on_mount(:require_sudo_mode, %{}, session, socket)
|
||||
end
|
||||
|
||||
test "redirects unauthenticated users" do
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue