towerops/lib/towerops_web/live/org_live/new.html.heex
Graham McIntire 3a408a8dc1 Security hardening + performance fixes across codebase
CRITICAL:
- Membership: remove :role/:org_id/:user_id from mass-assignment cast; use explicit create_changeset/4 and role_update_changeset/2
- GraphQL member resolver: add authorize_invite/3 checking admin/owner role and role hierarchy
- REST invitations controller: add auth check for invite creation

HIGH:
- ApiToken: remove :organization_id/:user_id from cast; use explicit create_changeset/4

MEDIUM:
- Move 8 LiveView Ecto queries into context modules (Admin, Alerts, Coverages, OnCall, Snmp)
- Replace Process.put/Process.get with socket assigns for unresolved_alert_count (user_auth + layouts + 50 templates)
- Add batch get_utilization_for_interfaces/1 to eliminate N+1 capacity queries in device show
- Replace Process.sleep with Process.monitor/assert_receive or Process.send_after in 5 test files

LOW:
- Add handle_params/3 to UserResetPasswordLive, UserRegistrationLive, StatusPageLive
- Remove redundant Repo.preload calls; add preloads to list_site_devices/1
- Fix @impl annotations and credo nesting warnings
2026-06-21 17:40:50 -05:00

43 lines
1.6 KiB
Text

<Layouts.authenticated
flash={@flash}
current_scope={@current_scope}
unresolved_alert_count={assigns[:unresolved_alert_count] || 0}
>
<.header>
{@page_title}
<:subtitle>{t("Create a new organization to manage your sites and devices")}</:subtitle>
</.header>
<%= if not @can_create_free do %>
<div class="max-w-2xl mb-6 rounded-lg bg-orange-50 dark:bg-orange-900/20 p-4 border border-orange-200 dark:border-orange-800">
<div class="flex">
<.icon name="hero-exclamation-triangle" class="h-5 w-5 text-orange-400" />
<div class="ml-3">
<h3 class="text-sm font-medium text-orange-800 dark:text-orange-400">
{t("Free organization limit reached")}
</h3>
<p class="mt-1 text-sm text-orange-700 dark:text-orange-300">
You already have {@free_org_count} free {if @free_org_count == 1,
do: "organization",
else: "organizations"}. {t(
"To create additional organizations, you'll need to upgrade your existing organization to a paid plan."
)}
</p>
</div>
</div>
</div>
<% end %>
<div class="max-w-2xl">
<.form for={@form} id="organization-form" phx-change="validate" phx-submit="save">
<.input field={@form[:name]} type="text" label={t("Organization Name")} required />
<div class="flex gap-3 mt-6">
<.button phx-disable-with={t("Creating...")} variant="primary">
Create Organization
</.button>
<.button navigate={~p"/orgs"}>{t("Cancel")}</.button>
</div>
</.form>
</div>
</Layouts.authenticated>