<.link navigate={~p"/dashboard"} class="inline-flex items-center gap-1 text-sm text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white" > <.icon name="hero-arrow-left" class="h-4 w-4" /> Back to Dashboard

Organization Settings

Manage organization defaults, integrations, and configuration

<%= if @active_tab not in ["integrations", "members"] do %> <.form for={@form} id="organization-form" phx-change="validate" phx-submit="save" data-1p-ignore data-form-type="other" >
<%= if @active_tab == "general" do %>

Organization Name

Update the name of your organization.

<.input field={@form[:name]} type="text" label="Organization Name" required />
<%= if @user_orgs_count > 1 do %>

Default Organization

Set this organization as your default. When you log in, you'll be directed to your default organization.

<%= if @membership.is_default do %>
<.icon name="hero-check-circle" class="h-5 w-5 text-green-600 dark:text-green-400" />

This is your default organization

<% else %>

Click to make this your default organization

<% end %>
<% end %>

Site Organization

Enable site organization to group devices into physical locations (offices, datacenters, etc.).

<.input field={@form[:use_sites]} type="checkbox" label="Use sites to organize devices" />

When enabled, you can organize devices into sites. When disabled, all devices belong directly to the organization.

<%= if @organization.use_sites && @form[:use_sites].value == false do %>
<.icon name="hero-exclamation-triangle" class="h-5 w-5 text-amber-400" />

Warning: Disabling Sites

All devices will be removed from their current sites and assigned directly to the organization. Site assignments will be lost, but devices will remain in the organization.

<% end %>
<% end %> <%= if @active_tab == "snmp" do %>

SNMP Configuration

Set default SNMP settings for all devices in this organization. These can be overridden at the site or device level.

<.icon name="hero-information-circle" class="h-4 w-4 inline" /> Hierarchy: Device > Site > Organization

<.input field={@form[:snmp_version]} type="select" label="SNMP Version" prompt="Select SNMP version" options={[{"v1", "1"}, {"v2c", "2c"}, {"v3", "3"}]} /> <%= if @form[:snmp_version].value in ["1", "2c"] do %> <.input field={@form[:snmp_community]} type="text" label="SNMP Community String" placeholder="e.g., public" /> <% end %> <%= if @form[:snmp_version].value == "3" do %> <.input field={@form[:snmpv3_security_level]} type="select" label="Security Level" prompt="Select security level" options={[ {"No Auth, No Priv", "noAuthNoPriv"}, {"Auth, No Priv", "authNoPriv"}, {"Auth, Priv", "authPriv"} ]} /> <.input field={@form[:snmpv3_username]} type="text" label="Username" placeholder="e.g., snmpuser" /> <%= if @form[:snmpv3_security_level].value in ["authNoPriv", "authPriv"] do %> <.input field={@form[:snmpv3_auth_protocol]} type="select" label="Auth Protocol" prompt="Select protocol" options={[ {"SHA-256 (recommended)", "SHA-256"}, {"SHA-512", "SHA-512"}, {"SHA-384", "SHA-384"}, {"SHA-224", "SHA-224"}, {"SHA (SHA-1)", "SHA"}, {"MD5", "MD5"} ]} /> <.input field={@form[:snmpv3_auth_password]} type="password" label="Auth Password" placeholder="Min 8 characters" autocomplete="off" /> <% end %> <%= if @form[:snmpv3_security_level].value == "authPriv" do %> <.input field={@form[:snmpv3_priv_protocol]} type="select" label="Privacy Protocol" prompt="Select protocol" options={[ {"AES-128 (recommended)", "AES"}, {"AES-256", "AES-256"}, {"AES-192", "AES-192"}, {"AES-256-C", "AES-256-C"}, {"DES (legacy)", "DES"} ]} /> <.input field={@form[:snmpv3_priv_password]} type="password" label="Privacy Password" placeholder="Min 8 characters" autocomplete="off" /> <% end %> <% end %> <.input field={@form[:snmp_port]} type="number" label="SNMP Port" placeholder="161" /> <%= if @organization.snmp_community do %>

Force Apply to All Devices

This will override SNMP settings for ALL devices across all sites in this organization.

<% end %>
<% end %> <%= if @active_tab == "mikrotik" && @current_scope.user.is_superuser do %>

MikroTik API Configuration

Set default MikroTik RouterOS API credentials for all devices in this organization. Only applies to devices detected as MikroTik.

<.icon name="hero-beaker" class="h-4 w-4 inline" /> Experimental Feature: MikroTik API integration is under active development.

<.icon name="hero-information-circle" class="h-4 w-4 inline" /> Hierarchy: Device > Site > Organization

<.input field={@form[:mikrotik_enabled]} type="checkbox" label="Enable MikroTik API" />
<.input field={@form[:mikrotik_username]} type="text" label="Username" placeholder="e.g., admin" autocomplete="off" />
<.input field={@form[:mikrotik_password]} type="password" label="Password" placeholder="RouterOS API password" autocomplete="off" />
<.input field={@form[:mikrotik_port]} type="number" label="API Port" placeholder="8729" autocomplete="off" />
<.input field={@form[:mikrotik_use_ssl]} type="checkbox" label="Use SSL (API-SSL)" />

Critical Security Warning: Plain API (port 8728) sends credentials unencrypted over the network. This setting is blocked for devices using cloud pollers and should only be used with local agents on trusted networks.

Security Warning: Plain API (port 8728) sends credentials unencrypted. Use SSL (port 8729) whenever possible.

<% end %> <%= if @active_tab == "agents" do %> <%= if @available_agents != [] do %>

Default Agent

Select a default agent for SNMP polling. This will be used for all devices in this organization unless overridden at the site or device level.

<.icon name="hero-information-circle" class="h-4 w-4 inline" /> Hierarchy: Device > Site > Organization

<.input field={@form[:default_agent_token_id]} type="select" label="Default Remote Agent" prompt="No default agent - cloud polling" options={Enum.map(@available_agents, &{&1.name, &1.id})} />

Current Device Assignment:

<.icon name="hero-server" class="h-4 w-4" /> {@assignment_breakdown.direct} device-level override
<.icon name="hero-building-office" class="h-4 w-4" /> {@assignment_breakdown.site} inherited from site
<.icon name="hero-building-office-2" class="h-4 w-4" /> {@assignment_breakdown.organization} inheriting organization default
<.icon name="hero-cloud" class="h-4 w-4" /> {@assignment_breakdown.cloud} cloud polling (no agent)
<%= if @organization.default_agent_token_id do %>

Force Apply to All Devices

This will assign the default agent to ALL devices across all sites in this organization.

<% end %>
<% else %>

Default Agent

No agents configured yet. <.link navigate={~p"/agents"} class="text-indigo-600 hover:text-indigo-700 dark:text-indigo-400 dark:hover:text-indigo-300" > Create an agent to enable remote polling.

<% end %> <% end %>
<.link navigate={~p"/dashboard"} class="text-sm font-semibold text-gray-900 dark:text-white" > Cancel
<% end %> <%= if @active_tab == "members" do %>
<%= if @membership.role in [:owner, :admin] do %>

Invite a Team Member

Send an invitation email to add someone to this organization.

<.form for={@invite_form} id="invite-form" phx-submit="send_invitation">
<.input field={@invite_form[:email]} type="email" label="Email address" placeholder="colleague@example.com" required />
<.input field={@invite_form[:role]} type="select" label="Role" options={[{"Admin", "admin"}, {"Member", "member"}, {"Viewer", "viewer"}]} />
<% end %> <%= if @pending_invitations != [] do %>

Pending Invitations

Invitations that haven't been accepted yet.

<%= if @membership.role in [:owner, :admin] do %> <% end %> <%= if @membership.role in [:owner, :admin] do %> <% end %>
Email Role Sent ExpiresActions
{invitation.email} {invitation.role} <.timestamp datetime={invitation.inserted_at} timezone={@timezone} format="absolute" /> <.timestamp datetime={invitation.expires_at} timezone={@timezone} format="absolute" />
<% end %>

Members

People who have access to this organization.

<%= if @membership.role in [:owner, :admin] do %> <% end %> <%= if @membership.role in [:owner, :admin] do %> <% end %>
User Role JoinedActions
{member.user.email}
"bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-400" :admin -> "bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400" :member -> "bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400" :viewer -> "bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-400" end ]}> {member.role} <.timestamp datetime={member.inserted_at} timezone={@timezone} format="absolute" /> <%= if member.role != :owner do %>
<% end %>
<% end %> <%= if @active_tab == "integrations" do %>
<.icon name={provider.icon} class="h-6 w-6 text-indigo-600 dark:text-indigo-400" />

{provider.name}

{provider.description}

<%= if integration = @integrations[provider.id] do %>
{if integration.enabled, do: "Enabled", else: "Disabled"} <%= if integration.last_synced_at do %> Last synced: <.timestamp datetime={integration.last_synced_at} timezone={@timezone} format="absolute" /> <% end %> <%= if integration.last_sync_status && integration.last_sync_status != "never" do %> "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" "partial" -> "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400" "failed" -> "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400" _ -> "bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400" end ]}> {String.capitalize(integration.last_sync_status)} <% end %> <%= if integration.last_synced_at do %> · Next sync in ~{next_sync_minutes( integration.last_synced_at, integration.sync_interval_minutes )}m <% end %> <%= if provider.id == "preseem" do %> <.link navigate={ ~p"/orgs/#{@organization.slug}/settings/integrations/preseem/devices" } class="text-sm text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300" > Manage Devices → <.link navigate={~p"/insights?source=preseem"} class="text-sm text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300" > Network Insights → <% end %> <%= if provider.id == "gaiia" do %> <.link navigate={~p"/orgs/#{@organization.slug}/settings/integrations/gaiia/mapping"} class="text-sm text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300" > Entity Mapping → <.link navigate={ ~p"/orgs/#{@organization.slug}/settings/integrations/gaiia/reconciliation" } class="text-sm text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300" > Reconciliation → <% end %> <%!-- Sync schedule info --%> <%= if integration.enabled do %>

<.icon name="hero-clock" class="h-3.5 w-3.5 inline" /> Sync Schedule

<%= if provider.id == "preseem" do %> Syncs every {integration.sync_interval_minutes} minutes. Baselines and fleet profiles computed nightly. <% end %> <%= if provider.id == "gaiia" do %> Syncs every {integration.sync_interval_minutes} minutes. Reconciliation runs nightly. Also receives real-time webhook updates. <% end %> <%= if provider.id == "pagerduty" do %> Event-driven — alerts are sent to PagerDuty in real time when devices go down, are acknowledged, or recover. <% end %>

<% end %>
<% end %>
<%= if integration = @integrations[provider.id] do %> <% end %>
<%= if @configuring == provider.id do %>
<.form for={@integration_form} id={"#{provider.id}-form"} phx-change="validate_integration" phx-submit="save_integration" >
<.input field={@integration_form[:api_key]} type="password" label={if(provider.id == "pagerduty", do: "Integration Key (Routing Key)", else: "API Key")} placeholder={if(provider.id == "pagerduty", do: "Enter your PagerDuty integration key", else: "Enter your #{provider.name} API key")} autocomplete="off" value={get_credential(@integrations[provider.id], "api_key")} /> <%= if provider.id == "pagerduty" do %>

Find this in PagerDuty → Services → Your Service → Integrations → Events API v2

<% end %> <%= if provider.id != "pagerduty" do %> <.input field={@integration_form[:sync_interval_minutes]} type="number" label="Sync interval (minutes)" min="5" value={ if(@integrations[provider.id], do: @integrations[provider.id].sync_interval_minutes, else: if(provider.id == "gaiia", do: 15, else: 10) ) } /> <% end %> <%= if @test_result do %>
"bg-green-50 dark:bg-green-900/20" {:error, _} -> "bg-red-50 dark:bg-red-900/20" end ]}>

"text-green-800 dark:text-green-200" {:error, _} -> "text-red-800 dark:text-red-200" end ]}> {elem(@test_result, 1)}

<% end %>
<% end %> <%= if provider.id == "gaiia" && @integrations["gaiia"] do %>

Webhook Configuration

Receive real-time updates from Gaiia when accounts, subscriptions, or inventory items change.

Setup Instructions
  1. In your Gaiia admin panel, go to Settings → Webhooks
  2. Click "Add Webhook"
  3. Paste the Webhook URL above
  4. Paste the Webhook Secret above into the "Secret" field
  5. Select events: Account, Billing Subscription, Inventory Item
  6. Save the webhook

Once configured, Towerops will receive real-time updates when accounts, subscriptions, or inventory items change in Gaiia.

<% end %>
<% end %>