Server locations: no user threshold
The public projection of a server's place showed only the country for servers reporting fewer than 10 users. The owner never decided that threshold: every located server now shows its city, coordinates (0.1°) and network, and a CDN-fronted one still shows only its CDN, since the address reached is the CDN's edge. Statistics:PublicCityMinUsers is gone; the ROADMAP decision on server locations, CLAUDE.md and the /stargazing explainer are corrected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
31d1d21d1e
commit
eb7552e8f3
9 files changed
+56
-57
No files matched your search
@@ -1,4 +1,4 @@
|
||||
using MongoDB.Entities;
|
||||
using MongoDB.Entities;
|
||||
|
||||
using PrivaPub.Models.Jobs;
|
||||
using PrivaPub.Tests.Support;
|
||||
@@ -9,9 +9,8 @@ using System.Text.Json.Nodes;
|
||||
|
||||
namespace PrivaPub.Tests.Http
|
||||
{
|
||||
// Where a server is, on the public instance API: the projection decided for public server locations (city and network
|
||||
// only for servers reporting at least 10 users and not behind a CDN, the country otherwise, the CDN's name for a
|
||||
// CDN-fronted one), the batch form, and this server itself.
|
||||
// Where a server is, on the public instance API: where it was located (city, coordinates and network, whatever its size),
|
||||
// only the CDN's name for a CDN-fronted one, the batch form, and this server itself.
|
||||
[Trait("Category", "Integration")]
|
||||
public sealed class InstanceLocationTests : IAsyncLifetime
|
||||
{
|
||||
@@ -51,7 +50,7 @@ namespace PrivaPub.Tests.Http
|
||||
async Task<JsonNode> Geo(string host) => (await _host.Client().Get($"/api/privapub/v1/instances/{host}")).Ok().Body["geo"];
|
||||
|
||||
[Fact]
|
||||
public async Task A_server_with_enough_users_shows_its_city_coordinates_and_network()
|
||||
public async Task A_located_server_shows_its_city_coordinates_and_network()
|
||||
{
|
||||
var geo = await Geo(await Instance(50, Milan()));
|
||||
|
||||
@@ -66,16 +65,24 @@ namespace PrivaPub.Tests.Http
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task A_small_server_shows_only_its_country()
|
||||
public async Task A_one_user_server_shows_its_city_too()
|
||||
{
|
||||
var geo = await Geo(await Instance(3, Milan()));
|
||||
var geo = await Geo(await Instance(1, Milan()));
|
||||
|
||||
Assert.Equal("city", geo.Text("precision"));
|
||||
Assert.Equal(("IT", "Milan", "Example Hosting"), (geo.Text("country"), geo.Text("city"), geo.Text("network")));
|
||||
Assert.Equal(45.5, geo["latitude"]!.GetValue<double>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task A_server_located_only_to_its_country_shows_the_country()
|
||||
{
|
||||
var geo = await Geo(await Instance(50, new InstanceGeo { Country = "IT", Source = "DB-IP Lite 2026-10", LocatedAt = DateTime.UtcNow }));
|
||||
|
||||
Assert.Equal("country", geo.Text("precision"));
|
||||
Assert.Equal("IT", geo.Text("country"));
|
||||
Assert.Null(geo["city"]);
|
||||
Assert.Null(geo["latitude"]);
|
||||
Assert.Null(geo["longitude"]);
|
||||
Assert.Null(geo["network"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -102,7 +109,7 @@ namespace PrivaPub.Tests.Http
|
||||
var host = await Instance(3, Milan());
|
||||
var described = (await _host.Client().Get($"/api/privapub/v1/instances/{host}")).Ok().Body;
|
||||
|
||||
Assert.Equal("country", described["geo"].Text("precision"));
|
||||
Assert.Equal("city", described["geo"].Text("precision"));
|
||||
Assert.Equal(described["geo"]!.ToJsonString(), (await Geo(host))!.ToJsonString());
|
||||
}
|
||||
|
||||
@@ -117,7 +124,7 @@ namespace PrivaPub.Tests.Http
|
||||
var hosts = answer.Body!.AsArray().Select(i => i.Text("host")).ToList();
|
||||
|
||||
Assert.Equal(new[] { small, big }, hosts);
|
||||
Assert.Equal("country", answer.Body![0]["geo"].Text("precision"));
|
||||
Assert.Equal("city", answer.Body![0]["geo"].Text("precision"));
|
||||
Assert.Equal("city", answer.Body![1]["geo"].Text("precision"));
|
||||
Assert.Empty((await _host.Client().Get("/api/privapub/v1/instances")).Ok().Body!.AsArray());
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
using MongoDB.Entities;
|
||||
|
||||
@@ -78,16 +78,16 @@ namespace PrivaPub.Tests.Statistics
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void The_public_location_depends_on_size_and_on_a_cdn()
|
||||
public void The_public_location_is_where_the_server_was_located_unless_a_cdn_hides_it()
|
||||
{
|
||||
var geo = new InstanceGeo { Country = "DE", City = "Berlin", Latitude = 52.5, Longitude = 13.4, AsnOrg = "Hetzner", Asn = 24940 };
|
||||
|
||||
Assert.Equal(new PublicLocation("DE", "Berlin", 52.5, 13.4, "Hetzner", null), PublicGeo.Project(new RemoteInstance { Geo = geo, UsersTotal = 10 }, 10));
|
||||
Assert.Equal(new PublicLocation("DE", null, null, null, null, null), PublicGeo.Project(new RemoteInstance { Geo = geo, UsersTotal = 1 }, 10));
|
||||
Assert.Equal(new PublicLocation("DE", null, null, null, null, null), PublicGeo.Project(new RemoteInstance { Geo = geo }, 10));
|
||||
Assert.Equal(new PublicLocation("DE", "Berlin", 52.5, 13.4, "Hetzner", null), PublicGeo.Project(geo));
|
||||
Assert.Equal(new PublicLocation("DE", null, null, null, null, null), PublicGeo.Project(new InstanceGeo { Country = "DE" }));
|
||||
Assert.Equal(new PublicLocation(null, null, null, null, null, "Cloudflare"),
|
||||
PublicGeo.Project(new RemoteInstance { Geo = new InstanceGeo { Country = "US", City = "SF", Cdn = "Cloudflare" }, UsersTotal = 5000 }, 10));
|
||||
Assert.Null(PublicGeo.Project(new RemoteInstance(), 10));
|
||||
PublicGeo.Project(new InstanceGeo { Country = "US", City = "SF", Latitude = 37.8, Longitude = -122.4, Cdn = "Cloudflare" }));
|
||||
Assert.Null(PublicGeo.Project(new InstanceGeo()));
|
||||
Assert.Null(PublicGeo.Project(null));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user