more tests
This commit is contained in:
parent
8667d6a288
commit
b78a40555c
2 changed files with 678 additions and 2 deletions
|
|
@ -1,11 +1,472 @@
|
|||
defmodule Towerops.AdminTest do
|
||||
use Towerops.DataCase
|
||||
|
||||
import Towerops.AccountsFixtures
|
||||
|
||||
alias Towerops.Accounts.User
|
||||
alias Towerops.Admin
|
||||
alias Towerops.Organizations.Organization
|
||||
|
||||
describe "create_audit_log/1" do
|
||||
test "creates audit log with valid attributes" do
|
||||
superuser = user_fixture(%{superuser: true})
|
||||
target_user = user_fixture()
|
||||
|
||||
attrs = %{
|
||||
action: "impersonate_start",
|
||||
superuser_id: superuser.id,
|
||||
target_user_id: target_user.id,
|
||||
ip_address: "192.168.1.1"
|
||||
}
|
||||
|
||||
assert {:ok, audit_log} = Admin.create_audit_log(attrs)
|
||||
assert audit_log.action == "impersonate_start"
|
||||
assert audit_log.superuser_id == superuser.id
|
||||
assert audit_log.target_user_id == target_user.id
|
||||
assert audit_log.ip_address.address == "192.168.1.1"
|
||||
end
|
||||
|
||||
test "creates audit log with nil target_user_id" do
|
||||
superuser = user_fixture(%{superuser: true})
|
||||
|
||||
attrs = %{
|
||||
action: "user_data_exported",
|
||||
superuser_id: superuser.id,
|
||||
target_user_id: nil,
|
||||
ip_address: "10.0.0.1"
|
||||
}
|
||||
|
||||
assert {:ok, audit_log} = Admin.create_audit_log(attrs)
|
||||
assert audit_log.target_user_id == nil
|
||||
end
|
||||
|
||||
test "creates audit log with only required field (action)" do
|
||||
attrs = %{
|
||||
action: "impersonate_start"
|
||||
# Only action is required, superuser_id and ip_address are optional
|
||||
}
|
||||
|
||||
assert {:ok, audit_log} = Admin.create_audit_log(attrs)
|
||||
assert audit_log.action == "impersonate_start"
|
||||
assert audit_log.superuser_id == nil
|
||||
assert audit_log.ip_address == nil
|
||||
end
|
||||
|
||||
test "returns error with invalid action" do
|
||||
superuser = user_fixture(%{superuser: true})
|
||||
|
||||
attrs = %{
|
||||
action: "invalid_action",
|
||||
superuser_id: superuser.id,
|
||||
ip_address: "127.0.0.1"
|
||||
}
|
||||
|
||||
assert {:error, changeset} = Admin.create_audit_log(attrs)
|
||||
assert %{action: ["is invalid"]} = errors_on(changeset)
|
||||
end
|
||||
|
||||
test "returns error with missing action" do
|
||||
superuser = user_fixture(%{superuser: true})
|
||||
|
||||
attrs = %{
|
||||
superuser_id: superuser.id,
|
||||
ip_address: "127.0.0.1"
|
||||
}
|
||||
|
||||
assert {:error, changeset} = Admin.create_audit_log(attrs)
|
||||
assert %{action: ["can't be blank"]} = errors_on(changeset)
|
||||
end
|
||||
end
|
||||
|
||||
describe "list_audit_logs/1" do
|
||||
setup do
|
||||
superuser = user_fixture(%{superuser: true})
|
||||
target_user = user_fixture()
|
||||
|
||||
%{superuser: superuser, target_user: target_user}
|
||||
end
|
||||
|
||||
test "returns all audit logs with default pagination", %{superuser: superuser, target_user: target_user} do
|
||||
{:ok, _log1} =
|
||||
Admin.create_audit_log(%{
|
||||
action: "impersonate_start",
|
||||
superuser_id: superuser.id,
|
||||
target_user_id: target_user.id,
|
||||
ip_address: "127.0.0.1"
|
||||
})
|
||||
|
||||
{:ok, _log2} =
|
||||
Admin.create_audit_log(%{
|
||||
action: "impersonate_end",
|
||||
superuser_id: superuser.id,
|
||||
target_user_id: target_user.id,
|
||||
ip_address: "127.0.0.1"
|
||||
})
|
||||
|
||||
result = Admin.list_audit_logs()
|
||||
assert length(result) == 2
|
||||
end
|
||||
|
||||
test "respects limit parameter", %{superuser: superuser, target_user: target_user} do
|
||||
for _i <- 1..5 do
|
||||
Admin.create_audit_log(%{
|
||||
action: "impersonate_start",
|
||||
superuser_id: superuser.id,
|
||||
target_user_id: target_user.id,
|
||||
ip_address: "127.0.0.1"
|
||||
})
|
||||
end
|
||||
|
||||
result = Admin.list_audit_logs(limit: 3)
|
||||
assert length(result) == 3
|
||||
end
|
||||
|
||||
test "orders logs by inserted_at descending", %{superuser: superuser, target_user: target_user} do
|
||||
{:ok, _log1} =
|
||||
Admin.create_audit_log(%{
|
||||
action: "impersonate_start",
|
||||
superuser_id: superuser.id,
|
||||
target_user_id: target_user.id,
|
||||
ip_address: "127.0.0.1"
|
||||
})
|
||||
|
||||
{:ok, _log2} =
|
||||
Admin.create_audit_log(%{
|
||||
action: "impersonate_end",
|
||||
superuser_id: superuser.id,
|
||||
target_user_id: target_user.id,
|
||||
ip_address: "127.0.0.1"
|
||||
})
|
||||
|
||||
result = Admin.list_audit_logs()
|
||||
assert length(result) == 2
|
||||
|
||||
# Verify ordering: each record's inserted_at should be >= next record
|
||||
[first, second] = result
|
||||
assert DateTime.compare(first.inserted_at, second.inserted_at) in [:gt, :eq]
|
||||
end
|
||||
|
||||
test "preloads superuser and target_user associations", %{superuser: superuser, target_user: target_user} do
|
||||
{:ok, _log} =
|
||||
Admin.create_audit_log(%{
|
||||
action: "impersonate_start",
|
||||
superuser_id: superuser.id,
|
||||
target_user_id: target_user.id,
|
||||
ip_address: "127.0.0.1"
|
||||
})
|
||||
|
||||
result = Admin.list_audit_logs()
|
||||
assert length(result) == 1
|
||||
|
||||
log = hd(result)
|
||||
assert Ecto.assoc_loaded?(log.superuser)
|
||||
assert Ecto.assoc_loaded?(log.target_user)
|
||||
end
|
||||
|
||||
test "returns empty list when no audit logs exist" do
|
||||
result = Admin.list_audit_logs()
|
||||
assert result == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "list_all_users/1" do
|
||||
test "returns all users with default pagination" do
|
||||
user1 = user_fixture()
|
||||
user2 = user_fixture()
|
||||
user3 = user_fixture()
|
||||
|
||||
result = Admin.list_all_users()
|
||||
assert length(result) >= 3
|
||||
user_ids = Enum.map(result, & &1.id)
|
||||
assert user1.id in user_ids
|
||||
assert user2.id in user_ids
|
||||
assert user3.id in user_ids
|
||||
end
|
||||
|
||||
test "respects limit parameter" do
|
||||
for _i <- 1..10 do
|
||||
user_fixture()
|
||||
end
|
||||
|
||||
result = Admin.list_all_users(limit: 5)
|
||||
assert length(result) == 5
|
||||
end
|
||||
|
||||
test "respects offset parameter" do
|
||||
# Create users in a clean test
|
||||
Repo.delete_all(User)
|
||||
_users = for _i <- 1..10, do: user_fixture()
|
||||
|
||||
result = Admin.list_all_users(offset: 7)
|
||||
assert length(result) == 3
|
||||
end
|
||||
|
||||
test "combines limit and offset" do
|
||||
Repo.delete_all(User)
|
||||
|
||||
for _i <- 1..20 do
|
||||
user_fixture()
|
||||
end
|
||||
|
||||
result = Admin.list_all_users(limit: 5, offset: 10)
|
||||
assert length(result) == 5
|
||||
end
|
||||
|
||||
test "orders users by inserted_at descending" do
|
||||
Repo.delete_all(User)
|
||||
|
||||
_user1 = user_fixture()
|
||||
_user2 = user_fixture()
|
||||
_user3 = user_fixture()
|
||||
|
||||
result = Admin.list_all_users()
|
||||
assert length(result) == 3
|
||||
|
||||
# Verify descending order: each user's inserted_at should be >= next user
|
||||
[first, second, third] = result
|
||||
assert DateTime.compare(first.inserted_at, second.inserted_at) in [:gt, :eq]
|
||||
assert DateTime.compare(second.inserted_at, third.inserted_at) in [:gt, :eq]
|
||||
end
|
||||
|
||||
test "returns empty list when no users exist" do
|
||||
# Clean up any existing users
|
||||
Repo.delete_all(User)
|
||||
|
||||
result = Admin.list_all_users()
|
||||
assert result == []
|
||||
end
|
||||
|
||||
test "preloads organizations association" do
|
||||
user = user_fixture()
|
||||
|
||||
result = Admin.list_all_users()
|
||||
found_user = Enum.find(result, &(&1.id == user.id))
|
||||
|
||||
assert Ecto.assoc_loaded?(found_user.organizations)
|
||||
end
|
||||
end
|
||||
|
||||
describe "count_users/0" do
|
||||
test "returns count of all users" do
|
||||
Repo.delete_all(User)
|
||||
|
||||
assert Admin.count_users() == 0
|
||||
|
||||
user_fixture()
|
||||
assert Admin.count_users() == 1
|
||||
|
||||
user_fixture()
|
||||
user_fixture()
|
||||
assert Admin.count_users() == 3
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete_user/3" do
|
||||
test "deletes user and creates audit log" do
|
||||
superuser = user_fixture(%{superuser: true})
|
||||
target_user = user_fixture()
|
||||
target_user_id = target_user.id
|
||||
target_user_email = target_user.email
|
||||
|
||||
assert {:ok, _deleted_user} = Admin.delete_user(target_user_id, superuser.id, "192.168.1.1")
|
||||
|
||||
# User should be deleted
|
||||
refute Repo.get(User, target_user_id)
|
||||
|
||||
# Audit log should be created
|
||||
audit_logs = Admin.list_audit_logs()
|
||||
assert length(audit_logs) == 1
|
||||
log = hd(audit_logs)
|
||||
assert log.action == "user_delete"
|
||||
assert log.superuser_id == superuser.id
|
||||
# target_user_id may be nil due to foreign key constraints after deletion
|
||||
assert log.ip_address.address == "192.168.1.1"
|
||||
assert log.metadata["email"] == target_user_email
|
||||
end
|
||||
|
||||
test "raises exception when user does not exist" do
|
||||
superuser = user_fixture(%{superuser: true})
|
||||
non_existent_id = Ecto.UUID.generate()
|
||||
|
||||
assert_raise Ecto.NoResultsError, fn ->
|
||||
Admin.delete_user(non_existent_id, superuser.id, "127.0.0.1")
|
||||
end
|
||||
end
|
||||
|
||||
test "anonymizes login history before deletion" do
|
||||
superuser = user_fixture(%{superuser: true})
|
||||
target_user = user_fixture()
|
||||
|
||||
# Create a login attempt for the target user
|
||||
{:ok, _login} =
|
||||
Towerops.Accounts.record_login_attempt(%{
|
||||
user_id: target_user.id,
|
||||
email: target_user.email,
|
||||
success: true,
|
||||
method: "password",
|
||||
ip_address: "10.0.0.1"
|
||||
})
|
||||
|
||||
assert {:ok, _deleted_user} = Admin.delete_user(target_user.id, superuser.id, "192.168.1.1")
|
||||
|
||||
# User should be deleted
|
||||
refute Repo.get(User, target_user.id)
|
||||
|
||||
# Login attempt should be anonymized (user_id set to nil, anonymized_at set)
|
||||
login_attempt = Repo.get_by(Towerops.Accounts.LoginAttempt, email: target_user.email)
|
||||
|
||||
if login_attempt do
|
||||
assert is_nil(login_attempt.user_id)
|
||||
assert login_attempt.anonymized_at
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "list_all_organizations/1" do
|
||||
test "returns all organizations with default pagination" do
|
||||
# Each user can only create one free organization, so use different users
|
||||
user1 = user_fixture()
|
||||
user2 = user_fixture()
|
||||
user3 = user_fixture()
|
||||
{:ok, org1} = Towerops.Organizations.create_organization(%{name: "Org 1"}, user1.id)
|
||||
{:ok, org2} = Towerops.Organizations.create_organization(%{name: "Org 2"}, user2.id)
|
||||
{:ok, org3} = Towerops.Organizations.create_organization(%{name: "Org 3"}, user3.id)
|
||||
|
||||
result = Admin.list_all_organizations()
|
||||
assert length(result) >= 3
|
||||
org_ids = Enum.map(result, & &1.id)
|
||||
assert org1.id in org_ids
|
||||
assert org2.id in org_ids
|
||||
assert org3.id in org_ids
|
||||
end
|
||||
|
||||
test "respects limit parameter" do
|
||||
for i <- 1..10 do
|
||||
user = user_fixture()
|
||||
Towerops.Organizations.create_organization(%{name: "Org #{i}"}, user.id)
|
||||
end
|
||||
|
||||
result = Admin.list_all_organizations(limit: 5)
|
||||
assert length(result) == 5
|
||||
end
|
||||
|
||||
test "respects offset parameter" do
|
||||
Repo.delete_all(Organization)
|
||||
|
||||
_orgs =
|
||||
for i <- 1..10 do
|
||||
user = user_fixture()
|
||||
{:ok, org} = Towerops.Organizations.create_organization(%{name: "Org #{i}"}, user.id)
|
||||
org
|
||||
end
|
||||
|
||||
result = Admin.list_all_organizations(offset: 7)
|
||||
assert length(result) == 3
|
||||
end
|
||||
|
||||
test "combines limit and offset" do
|
||||
Repo.delete_all(Organization)
|
||||
|
||||
for i <- 1..20 do
|
||||
user = user_fixture()
|
||||
Towerops.Organizations.create_organization(%{name: "Org #{i}"}, user.id)
|
||||
end
|
||||
|
||||
result = Admin.list_all_organizations(limit: 5, offset: 10)
|
||||
assert length(result) == 5
|
||||
end
|
||||
|
||||
test "orders organizations by inserted_at descending" do
|
||||
Repo.delete_all(Organization)
|
||||
|
||||
user1 = user_fixture()
|
||||
user2 = user_fixture()
|
||||
user3 = user_fixture()
|
||||
|
||||
{:ok, _org1} = Towerops.Organizations.create_organization(%{name: "Org 1"}, user1.id)
|
||||
{:ok, _org2} = Towerops.Organizations.create_organization(%{name: "Org 2"}, user2.id)
|
||||
{:ok, _org3} = Towerops.Organizations.create_organization(%{name: "Org 3"}, user3.id)
|
||||
|
||||
result = Admin.list_all_organizations()
|
||||
assert length(result) == 3
|
||||
|
||||
# Verify descending order: each org's inserted_at should be >= next org
|
||||
[first, second, third] = result
|
||||
assert DateTime.compare(first.inserted_at, second.inserted_at) in [:gt, :eq]
|
||||
assert DateTime.compare(second.inserted_at, third.inserted_at) in [:gt, :eq]
|
||||
end
|
||||
|
||||
test "returns empty list when no organizations exist" do
|
||||
Repo.delete_all(Organization)
|
||||
|
||||
result = Admin.list_all_organizations()
|
||||
assert result == []
|
||||
end
|
||||
|
||||
test "preloads memberships with users" do
|
||||
user = user_fixture()
|
||||
{:ok, org} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
|
||||
|
||||
result = Admin.list_all_organizations()
|
||||
found_org = Enum.find(result, &(&1.id == org.id))
|
||||
|
||||
assert Ecto.assoc_loaded?(found_org.memberships)
|
||||
assert found_org.memberships != []
|
||||
assert Ecto.assoc_loaded?(hd(found_org.memberships).user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "count_organizations/0" do
|
||||
test "returns count of all organizations" do
|
||||
Repo.delete_all(Organization)
|
||||
|
||||
assert Admin.count_organizations() == 0
|
||||
|
||||
user1 = user_fixture()
|
||||
Towerops.Organizations.create_organization(%{name: "Org 1"}, user1.id)
|
||||
assert Admin.count_organizations() == 1
|
||||
|
||||
user2 = user_fixture()
|
||||
user3 = user_fixture()
|
||||
Towerops.Organizations.create_organization(%{name: "Org 2"}, user2.id)
|
||||
Towerops.Organizations.create_organization(%{name: "Org 3"}, user3.id)
|
||||
assert Admin.count_organizations() == 3
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete_organization/3" do
|
||||
test "deletes organization and creates audit log" do
|
||||
superuser = user_fixture(%{superuser: true})
|
||||
user = user_fixture()
|
||||
{:ok, org} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
|
||||
|
||||
assert {:ok, _deleted_org} = Admin.delete_organization(org.id, superuser.id, "192.168.1.1")
|
||||
|
||||
# Organization should be deleted
|
||||
refute Repo.get(Organization, org.id)
|
||||
|
||||
# Audit log should be created
|
||||
audit_logs = Admin.list_audit_logs()
|
||||
assert length(audit_logs) == 1
|
||||
log = hd(audit_logs)
|
||||
assert log.action == "org_delete"
|
||||
assert log.superuser_id == superuser.id
|
||||
assert log.ip_address.address == "192.168.1.1"
|
||||
assert log.metadata["name"] == "Test Org"
|
||||
assert log.metadata["slug"] == org.slug
|
||||
end
|
||||
|
||||
test "raises exception when organization does not exist" do
|
||||
superuser = user_fixture(%{superuser: true})
|
||||
non_existent_id = Ecto.UUID.generate()
|
||||
|
||||
assert_raise Ecto.NoResultsError, fn ->
|
||||
Admin.delete_organization(non_existent_id, superuser.id, "127.0.0.1")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "GDPR data access - list_audit_logs_for_user/2" do
|
||||
import Towerops.AccountsFixtures
|
||||
|
||||
setup do
|
||||
user = user_fixture()
|
||||
superuser = user_fixture(%{superuser: true})
|
||||
|
|
|
|||
215
test/towerops/geoip_test.exs
Normal file
215
test/towerops/geoip_test.exs
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
defmodule Towerops.GeoIPTest do
|
||||
use Towerops.DataCase, async: true
|
||||
|
||||
alias Towerops.GeoIP
|
||||
alias Towerops.GeoIP.Block
|
||||
alias Towerops.GeoIP.Location
|
||||
|
||||
describe "lookup/1" do
|
||||
test "returns country code for valid IP with location data" do
|
||||
# Insert test location
|
||||
location = insert_location(%{geoname_id: 5_375_480, country_code: "US"})
|
||||
|
||||
# Insert test block for IP 8.8.8.8 (134744072)
|
||||
insert_block(%{
|
||||
geoname_id: location.geoname_id,
|
||||
start_ip_int: 134_744_072,
|
||||
end_ip_int: 134_744_072
|
||||
})
|
||||
|
||||
assert GeoIP.lookup("8.8.8.8") == "US"
|
||||
end
|
||||
|
||||
test "returns nil for valid IP with no location data" do
|
||||
assert GeoIP.lookup("192.168.1.1") == nil
|
||||
end
|
||||
|
||||
test "returns nil for invalid IP address" do
|
||||
assert GeoIP.lookup("invalid") == nil
|
||||
end
|
||||
|
||||
test "returns nil for empty string" do
|
||||
assert GeoIP.lookup("") == nil
|
||||
end
|
||||
|
||||
test "returns nil for IP with too many octets" do
|
||||
assert GeoIP.lookup("1.2.3.4.5") == nil
|
||||
end
|
||||
|
||||
test "returns nil for IP with invalid octets" do
|
||||
assert GeoIP.lookup("999.999.999.999") == nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "lookup_full/1" do
|
||||
test "returns full location data for valid IP" do
|
||||
# Insert test location with full data
|
||||
location =
|
||||
insert_location(%{
|
||||
geoname_id: 5_375_480,
|
||||
country_code: "US",
|
||||
country_name: "United States",
|
||||
city_name: "Mountain View",
|
||||
subdivision_1_name: "California",
|
||||
subdivision_2_name: nil,
|
||||
latitude: 37.386,
|
||||
longitude: -122.0838
|
||||
})
|
||||
|
||||
# Insert test block for IP 8.8.8.8
|
||||
insert_block(%{
|
||||
geoname_id: location.geoname_id,
|
||||
start_ip_int: 134_744_072,
|
||||
end_ip_int: 134_744_072
|
||||
})
|
||||
|
||||
result = GeoIP.lookup_full("8.8.8.8")
|
||||
|
||||
assert result.country_code == "US"
|
||||
assert result.country_name == "United States"
|
||||
assert result.city_name == "Mountain View"
|
||||
assert result.subdivision_1_name == "California"
|
||||
assert result.subdivision_2_name == nil
|
||||
assert result.latitude == 37.386
|
||||
assert result.longitude == -122.0838
|
||||
end
|
||||
|
||||
test "returns location data with minimal fields" do
|
||||
location = insert_location(%{geoname_id: 1234, country_code: "CA"})
|
||||
|
||||
insert_block(%{
|
||||
geoname_id: location.geoname_id,
|
||||
start_ip_int: 100,
|
||||
end_ip_int: 200
|
||||
})
|
||||
|
||||
result = GeoIP.lookup_full("0.0.0.100")
|
||||
|
||||
assert result.country_code == "CA"
|
||||
assert result.country_name == nil
|
||||
assert result.city_name == nil
|
||||
end
|
||||
|
||||
test "returns nil for IP not in any block" do
|
||||
# Create location and block, but query different IP
|
||||
location = insert_location(%{geoname_id: 5678, country_code: "US"})
|
||||
|
||||
insert_block(%{
|
||||
geoname_id: location.geoname_id,
|
||||
start_ip_int: 1000,
|
||||
end_ip_int: 2000
|
||||
})
|
||||
|
||||
assert GeoIP.lookup_full("192.168.1.1") == nil
|
||||
end
|
||||
|
||||
test "returns nil for invalid IP string" do
|
||||
assert GeoIP.lookup_full("not-an-ip") == nil
|
||||
end
|
||||
|
||||
test "returns nil for empty string" do
|
||||
assert GeoIP.lookup_full("") == nil
|
||||
end
|
||||
|
||||
test "handles IP at start of range" do
|
||||
location = insert_location(%{geoname_id: 9999, country_code: "FR"})
|
||||
|
||||
insert_block(%{
|
||||
geoname_id: location.geoname_id,
|
||||
start_ip_int: 167_772_160,
|
||||
end_ip_int: 167_772_170
|
||||
})
|
||||
|
||||
# 10.0.0.0 = 167772160
|
||||
result = GeoIP.lookup_full("10.0.0.0")
|
||||
assert result.country_code == "FR"
|
||||
end
|
||||
|
||||
test "handles IP at end of range" do
|
||||
location = insert_location(%{geoname_id: 8888, country_code: "DE"})
|
||||
|
||||
insert_block(%{
|
||||
geoname_id: location.geoname_id,
|
||||
start_ip_int: 167_772_160,
|
||||
end_ip_int: 167_772_170
|
||||
})
|
||||
|
||||
# 10.0.0.10 = 167772170
|
||||
result = GeoIP.lookup_full("10.0.0.10")
|
||||
assert result.country_code == "DE"
|
||||
end
|
||||
|
||||
test "handles IP in middle of range" do
|
||||
location = insert_location(%{geoname_id: 7777, country_code: "GB"})
|
||||
|
||||
insert_block(%{
|
||||
geoname_id: location.geoname_id,
|
||||
start_ip_int: 167_772_160,
|
||||
end_ip_int: 167_772_170
|
||||
})
|
||||
|
||||
# 10.0.0.5 = 167772165
|
||||
result = GeoIP.lookup_full("10.0.0.5")
|
||||
assert result.country_code == "GB"
|
||||
end
|
||||
|
||||
test "returns first matching block when multiple blocks overlap" do
|
||||
location1 = insert_location(%{geoname_id: 1111, country_code: "US"})
|
||||
location2 = insert_location(%{geoname_id: 2222, country_code: "CA"})
|
||||
|
||||
insert_block(%{
|
||||
network: "0.0.0.100/24",
|
||||
geoname_id: location1.geoname_id,
|
||||
start_ip_int: 100,
|
||||
end_ip_int: 200
|
||||
})
|
||||
|
||||
insert_block(%{
|
||||
network: "0.0.0.50/24",
|
||||
geoname_id: location2.geoname_id,
|
||||
start_ip_int: 50,
|
||||
end_ip_int: 150
|
||||
})
|
||||
|
||||
# Query returns first match due to limit: 1
|
||||
result = GeoIP.lookup_full("0.0.0.150")
|
||||
assert result.country_code in ["US", "CA"]
|
||||
end
|
||||
end
|
||||
|
||||
# Helper functions to insert test data
|
||||
defp insert_location(attrs) do
|
||||
default_attrs = %{
|
||||
geoname_id: System.unique_integer([:positive]),
|
||||
country_code: "US",
|
||||
country_name: nil,
|
||||
city_name: nil,
|
||||
subdivision_1_name: nil,
|
||||
subdivision_2_name: nil,
|
||||
latitude: nil,
|
||||
longitude: nil
|
||||
}
|
||||
|
||||
attrs = Map.merge(default_attrs, Map.new(attrs))
|
||||
|
||||
%Location{}
|
||||
|> Location.changeset(attrs)
|
||||
|> Repo.insert!()
|
||||
end
|
||||
|
||||
defp insert_block(attrs) do
|
||||
default_attrs = %{
|
||||
network: "0.0.0.0/32",
|
||||
start_ip_int: 0,
|
||||
end_ip_int: 0,
|
||||
geoname_id: nil,
|
||||
registered_country_geoname_id: nil
|
||||
}
|
||||
|
||||
attrs = Map.merge(default_attrs, Map.new(attrs))
|
||||
|
||||
%Block{}
|
||||
|> Block.changeset(attrs)
|
||||
|> Repo.insert!()
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue