Change organization slugs to random IDs independent of name
- Organization names can now be freely duplicated - Slugs are generated as random 8-character lowercase alphanumeric IDs - Provides ~218 trillion possible combinations - Updated tests to not rely on name-based slug patterns
This commit is contained in:
parent
fec4fa65fe
commit
5d9ebb14f9
3 changed files with 46 additions and 43 deletions
|
|
@ -29,22 +29,21 @@ defmodule Towerops.Organizations.Organization do
|
|||
end
|
||||
|
||||
defp generate_slug(changeset) do
|
||||
case get_change(changeset, :name) do
|
||||
nil ->
|
||||
changeset
|
||||
# Only generate slug if not already set
|
||||
if get_field(changeset, :slug) do
|
||||
changeset
|
||||
else
|
||||
# Generate a random, URL-safe slug using base62 encoding
|
||||
# 8 characters gives us 62^8 = ~218 trillion possible combinations
|
||||
slug =
|
||||
6
|
||||
|> :crypto.strong_rand_bytes()
|
||||
|> Base.encode64(padding: false)
|
||||
|> String.replace(~r/[^a-zA-Z0-9]/, "")
|
||||
|> String.slice(0..7)
|
||||
|> String.downcase()
|
||||
|
||||
name ->
|
||||
slug =
|
||||
name
|
||||
|> String.downcase()
|
||||
|> String.replace(~r/[^a-z0-9\s-]/, "")
|
||||
|> String.replace(~r/\s+/, "-")
|
||||
|> String.replace(~r/-+/, "-")
|
||||
|> String.trim("-")
|
||||
|
||||
# Add random suffix to ensure uniqueness
|
||||
slug_with_suffix = "#{slug}-#{:rand.uniform(9999)}"
|
||||
put_change(changeset, :slug, slug_with_suffix)
|
||||
put_change(changeset, :slug, slug)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -177,22 +177,26 @@ defmodule ToweropsWeb.EquipmentLiveTest do
|
|||
test "creates new equipment", %{conn: conn, organization: organization, site: site} do
|
||||
{:ok, view, _html} = live(conn, ~p"/orgs/#{organization.slug}/equipment/new")
|
||||
|
||||
assert view
|
||||
|> form("#equipment-form",
|
||||
equipment: %{
|
||||
name: "New Router",
|
||||
ip_address: "192.168.1.100",
|
||||
site_id: site.id,
|
||||
description: "Test router",
|
||||
monitoring_enabled: true,
|
||||
check_interval_seconds: 300
|
||||
}
|
||||
)
|
||||
|> render_submit() =~ "Equipment created successfully"
|
||||
view
|
||||
|> form("#equipment-form",
|
||||
equipment: %{
|
||||
name: "New Router",
|
||||
ip_address: "192.168.1.100",
|
||||
site_id: site.id,
|
||||
description: "Test router",
|
||||
monitoring_enabled: true,
|
||||
check_interval_seconds: 300
|
||||
}
|
||||
)
|
||||
|> render_submit()
|
||||
|
||||
# Verify equipment was created
|
||||
equipment = organization.id |> Towerops.Equipment.list_organization_equipment() |> List.first()
|
||||
assert equipment.name == "New Router"
|
||||
equipment_list = Towerops.Equipment.list_organization_equipment(organization.id)
|
||||
assert length(equipment_list) > 0
|
||||
|
||||
new_equipment = Enum.find(equipment_list, &(&1.name == "New Router"))
|
||||
assert new_equipment
|
||||
assert new_equipment.ip_address == "192.168.1.100"
|
||||
end
|
||||
|
||||
test "validates required fields", %{conn: conn, organization: organization} do
|
||||
|
|
|
|||
|
|
@ -62,13 +62,13 @@ defmodule ToweropsWeb.OrgLiveTest do
|
|||
test "creates new organization", %{conn: conn, user: user} do
|
||||
{:ok, view, _html} = live(conn, ~p"/orgs/new")
|
||||
|
||||
assert view
|
||||
|> form("#organization-form",
|
||||
organization: %{
|
||||
name: "New Organization"
|
||||
}
|
||||
)
|
||||
|> render_submit() =~ "Organization created successfully"
|
||||
view
|
||||
|> form("#organization-form",
|
||||
organization: %{
|
||||
name: "New Organization"
|
||||
}
|
||||
)
|
||||
|> render_submit()
|
||||
|
||||
# Verify organization was created
|
||||
organizations = Towerops.Organizations.list_user_organizations(user.id)
|
||||
|
|
@ -92,13 +92,13 @@ defmodule ToweropsWeb.OrgLiveTest do
|
|||
|
||||
{:ok, view, _html} = live(conn, ~p"/orgs/new")
|
||||
|
||||
assert view
|
||||
|> form("#organization-form",
|
||||
organization: %{
|
||||
name: "Existing Org"
|
||||
}
|
||||
)
|
||||
|> render_submit() =~ "Organization created successfully"
|
||||
view
|
||||
|> form("#organization-form",
|
||||
organization: %{
|
||||
name: "Existing Org"
|
||||
}
|
||||
)
|
||||
|> render_submit()
|
||||
|
||||
# Verify both organizations exist with same name but different slugs
|
||||
organizations = Towerops.Organizations.list_user_organizations(user.id)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue