Agents and probes report OS, arch and build (version, tag, commit, time). The backend looks up country and ISP of public addresses only, stores them in node_meta (schema v5) and exposes display info via /api/public/nodes, /api/public/about and /api/admin/build-info behind site.show_build.
70 lines
3.4 KiB
C#
70 lines
3.4 KiB
C#
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Routing;
|
|
using Monitor.Backend.Application;
|
|
|
|
namespace Monitor.Backend.Api;
|
|
|
|
/// <summary>
|
|
/// 节点的展示信息:系统、架构、国家、运营商。<b>只有这几项,没有任何 IP 地址、城市、ASN、经纬度</b>——
|
|
/// 这些在 Backend 里只在查询的那一刻用到,存起来的记录里也没有,所以访客(和任何别的接口)都拿不到。
|
|
/// </summary>
|
|
public static class NodeEndpoints
|
|
{
|
|
private const string Tag = "public-nodes";
|
|
|
|
public static void Map(RouteGroupBuilder group)
|
|
{
|
|
group.MapGet("/nodes", ListAsync)
|
|
.Api("nodes_list", "Display info of the visible agents and probes: system, architecture, country and ISP (never an address)", Tag)
|
|
.Returns<PageDto<NodeInfoDto>>().ProducesProblems(403);
|
|
group.MapGet("/about", AboutAsync)
|
|
.Api("about_get", "The backend's version, tag and build time, if the site shows build info", Tag)
|
|
.Returns<AboutDto>().ProducesProblems(403);
|
|
}
|
|
|
|
/// <summary>这个后端自己的构建信息;没有(本地构建)的字段是 <c>null</c>。</summary>
|
|
internal static BuildDto Backend(bool withCommit) =>
|
|
new(Monitor.Protocol.BuildInfo.Version, Empty(Monitor.Protocol.BuildInfo.Tag), withCommit ? Empty(Monitor.Protocol.BuildInfo.Commit) : null, Empty(Monitor.Protocol.BuildInfo.BuiltAt));
|
|
|
|
private static string? Empty(string value) => value.Length == 0 ? null : value;
|
|
|
|
private static async Task<IResult> AboutAsync(HttpContext http, SettingsService settings)
|
|
{
|
|
bool show = await settings.IsShowBuildAsync(http.RequestAborted);
|
|
http.Response.Headers.CacheControl = "no-store";
|
|
return TypedResults.Json(new AboutDto(show, show ? Backend(withCommit: false) : null), ApiJsonContext.Default.AboutDto);
|
|
}
|
|
|
|
private static async Task<IResult> ListAsync(HttpContext http, AgentService agents, ProbeService probes, NodeInfoService nodes, SettingsService settings, CancellationToken ct)
|
|
{
|
|
// 和别的公开接口一样:看得见的 Agent(隐藏的只有登录后才看得见)和没有被吊销的 Probe
|
|
var visible = new HashSet<string>(StringComparer.Ordinal);
|
|
foreach (AgentView view in await agents.ListAsync(ct))
|
|
{
|
|
if (view.Agent.Status == Fleet.Server.NodeStatus.Active && (view.Agent.PublicVisible || PublicGuard.CanSeeHidden(http)))
|
|
{
|
|
visible.Add(view.Agent.Id.Value);
|
|
}
|
|
}
|
|
|
|
foreach (ProbeView probe in await probes.ListAsync(ct))
|
|
{
|
|
if (!probe.Revoked)
|
|
{
|
|
visible.Add(probe.Probe.Id);
|
|
}
|
|
}
|
|
|
|
// 版本和 tag 只在站点打开「显示构建信息」时才给访客;关着就是 null
|
|
bool showBuild = await settings.IsShowBuildAsync(ct);
|
|
var items = (await nodes.ListAsync(ct))
|
|
.Where(n => visible.Contains(n.NodeId))
|
|
.OrderBy(n => n.NodeId, StringComparer.Ordinal)
|
|
.Select(n => new NodeInfoDto(n.NodeId, n.Kind, n.Os, n.OsName, n.Arch, n.Country, n.IspKey, n.IspName, showBuild ? n.Version : null, showBuild ? n.Tag : null))
|
|
.ToList();
|
|
http.Response.Headers.CacheControl = "no-store";
|
|
return TypedResults.Json(new PageDto<NodeInfoDto>(items, null), ApiJsonContext.Default.PageDtoNodeInfoDto);
|
|
}
|
|
}
|