Skip to content

Commit afae589

Browse files
Merge pull request #59 from fosrl/dev
1.3.0
2 parents 46c3883 + b52c6d8 commit afae589

5 files changed

Lines changed: 409 additions & 85 deletions

File tree

install/config/config.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
# https://docs.pangolin.net/
33

44
gerbil:
5-
start_port: 51820
6-
base_endpoint: "{{.DashboardDomain}}"
5+
start_port: 51820
6+
base_endpoint: "{{.DashboardDomain}}"
77

88
managed:
9-
id: "{{.HybridId}}"
10-
secret: "{{.HybridSecret}}"
9+
id: "{{.HybridId}}"
10+
secret: "{{.HybridSecret}}"

server/db/regions.ts

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
// Regions of the World
2+
// as of 2025-10-25
3+
//
4+
// Adapted according to the United Nations Geoscheme
5+
// see https://www.unicode.org/cldr/charts/48/supplemental/territory_containment_un_m_49.html
6+
// see https://unstats.un.org/unsd/methodology/m49
7+
8+
export const REGIONS = [
9+
{
10+
name: "regionAfrica",
11+
id: "002",
12+
includes: [
13+
{
14+
name: "regionNorthernAfrica",
15+
id: "015",
16+
countries: ["DZ", "EG", "LY", "MA", "SD", "TN", "EH"]
17+
},
18+
{
19+
name: "regionEasternAfrica",
20+
id: "014",
21+
countries: ["IO", "BI", "KM", "DJ", "ER", "ET", "TF", "KE", "MG", "MW", "MU", "YT", "MZ", "RE", "RW", "SC", "SO", "SS", "UG", "ZM", "ZW"]
22+
},
23+
{
24+
name: "regionMiddleAfrica",
25+
id: "017",
26+
countries: ["AO", "CM", "CF", "TD", "CG", "CD", "GQ", "GA", "ST"]
27+
},
28+
{
29+
name: "regionSouthernAfrica",
30+
id: "018",
31+
countries: ["BW", "SZ", "LS", "NA", "ZA"]
32+
},
33+
{
34+
name: "regionWesternAfrica",
35+
id: "011",
36+
countries: ["BJ", "BF", "CV", "CI", "GM", "GH", "GN", "GW", "LR", "ML", "MR", "NE", "NG", "SH", "SN", "SL", "TG"]
37+
}
38+
]
39+
},
40+
{
41+
name: "regionAmericas",
42+
id: "019",
43+
includes: [
44+
{
45+
name: "regionCaribbean",
46+
id: "029",
47+
countries: ["AI", "AG", "AW", "BS", "BB", "BQ", "VG", "KY", "CU", "CW", "DM", "DO", "GD", "GP", "HT", "JM", "MQ", "MS", "PR", "BL", "KN", "LC", "MF", "VC", "SX", "TT", "TC", "VI"]
48+
},
49+
{
50+
name: "regionCentralAmerica",
51+
id: "013",
52+
countries: ["BZ", "CR", "SV", "GT", "HN", "MX", "NI", "PA"]
53+
},
54+
{
55+
name: "regionSouthAmerica",
56+
id: "005",
57+
countries: ["AR", "BO", "BV", "BR", "CL", "CO", "EC", "FK", "GF", "GY", "PY", "PE", "GS", "SR", "UY", "VE"]
58+
},
59+
{
60+
name: "regionNorthernAmerica",
61+
id: "021",
62+
countries: ["BM", "CA", "GL", "PM", "US"]
63+
}
64+
]
65+
},
66+
{
67+
name: "regionAsia",
68+
id: "142",
69+
includes: [
70+
{
71+
name: "regionCentralAsia",
72+
id: "143",
73+
countries: ["KZ", "KG", "TJ", "TM", "UZ"]
74+
},
75+
{
76+
name: "regionEasternAsia",
77+
id: "030",
78+
countries: ["CN", "HK", "MO", "KP", "JP", "MN", "KR"]
79+
},
80+
{
81+
name: "regionSouthEasternAsia",
82+
id: "035",
83+
countries: ["BN", "KH", "ID", "LA", "MY", "MM", "PH", "SG", "TH", "TL", "VN"]
84+
},
85+
{
86+
name: "regionSouthernAsia",
87+
id: "034",
88+
countries: ["AF", "BD", "BT", "IN", "IR", "MV", "NP", "PK", "LK"]
89+
},
90+
{
91+
name: "regionWesternAsia",
92+
id: "145",
93+
countries: ["AM", "AZ", "BH", "CY", "GE", "IQ", "IL", "JO", "KW", "LB", "OM", "QA", "SA", "PS", "SY", "TR", "AE", "YE"]
94+
}
95+
]
96+
},
97+
{
98+
name: "regionEurope",
99+
id: "150",
100+
includes: [
101+
{
102+
name: "regionEasternEurope",
103+
id: "151",
104+
countries: ["BY", "BG", "CZ", "HU", "PL", "MD", "RO", "RU", "SK", "UA"]
105+
},
106+
{
107+
name: "regionNorthernEurope",
108+
id: "154",
109+
countries: ["AX", "DK", "EE", "FO", "FI", "GG", "IS", "IE", "IM", "JE", "LV", "LT", "NO", "SJ", "SE", "GB"]
110+
},
111+
{
112+
name: "regionSouthernEurope",
113+
id: "039",
114+
countries: ["AL", "AD", "BA", "HR", "GI", "GR", "VA", "IT", "MT", "ME", "MK", "PT", "SM", "RS", "SI", "ES"]
115+
},
116+
{
117+
name: "regionWesternEurope",
118+
id: "155",
119+
countries: ["AT", "BE", "FR", "DE", "LI", "LU", "MC", "NL", "CH"]
120+
}
121+
]
122+
},
123+
{
124+
name: "regionOceania",
125+
id: "009",
126+
includes: [
127+
{
128+
name: "regionAustraliaAndNewZealand",
129+
id: "053",
130+
countries: ["AU", "CX", "CC", "HM", "NZ", "NF"]
131+
},
132+
{
133+
name: "regionMelanesia",
134+
id: "054",
135+
countries: ["FJ", "NC", "PG", "SB", "VU"]
136+
},
137+
{
138+
name: "regionMicronesia",
139+
id: "057",
140+
countries: ["GU", "KI", "MH", "FM", "NR", "MP", "PW", "UM"]
141+
},
142+
{
143+
name: "regionPolynesia",
144+
id: "061",
145+
countries: ["AS", "CK", "PF", "NU", "PN", "WS", "TK", "TO", "TV", "WF"]
146+
}
147+
]
148+
}
149+
];
150+
151+
type Subregion = {
152+
name: string;
153+
id: string;
154+
countries: string[];
155+
};
156+
157+
type Region = {
158+
name: string;
159+
id: string;
160+
includes: Subregion[];
161+
};
162+
163+
export function getRegionNameById(regionId: string): string | undefined {
164+
// Check top-level regions
165+
const region = REGIONS.find((r) => r.id === regionId);
166+
if (region) {
167+
return region.name;
168+
}
169+
170+
// Check subregions
171+
for (const region of REGIONS) {
172+
for (const subregion of region.includes) {
173+
if (subregion.id === regionId) {
174+
return subregion.name;
175+
}
176+
}
177+
}
178+
179+
return undefined;
180+
}
181+
182+
export function isValidRegionId(regionId: string): boolean {
183+
// Check top-level regions
184+
if (REGIONS.find((r) => r.id === regionId)) {
185+
return true;
186+
}
187+
188+
// Check subregions
189+
for (const region of REGIONS) {
190+
if (region.includes.find((s) => s.id === regionId)) {
191+
return true;
192+
}
193+
}
194+
195+
return false;
196+
}

server/lib/ip.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import semver from "semver";
2+
13
interface IPRange {
24
start: bigint;
35
end: bigint;
@@ -229,3 +231,35 @@ export function isIpInCidr(ip: string, cidr: string): boolean {
229231
const range = cidrToRange(cidr);
230232
return ipBigInt >= range.start && ipBigInt <= range.end;
231233
}
234+
235+
export function stripPortFromHost(ip: string, badgerVersion?: string): string {
236+
const isNewerBadger =
237+
badgerVersion &&
238+
semver.valid(badgerVersion) &&
239+
semver.gte(badgerVersion, "1.3.1");
240+
241+
if (isNewerBadger) {
242+
return ip;
243+
}
244+
245+
if (ip.startsWith("[") && ip.includes("]")) {
246+
// if brackets are found, extract the IPv6 address from between the brackets
247+
const ipv6Match = ip.match(/\[(.*?)\]/);
248+
if (ipv6Match) {
249+
return ipv6Match[1];
250+
}
251+
}
252+
253+
// Check if it looks like IPv4 (contains dots and matches IPv4 pattern)
254+
// IPv4 format: x.x.x.x where x is 0-255
255+
const ipv4Pattern = /^(\d{1,3}\.){3}\d{1,3}/;
256+
if (ipv4Pattern.test(ip)) {
257+
const lastColonIndex = ip.lastIndexOf(":");
258+
if (lastColonIndex !== -1) {
259+
return ip.substring(0, lastColonIndex);
260+
}
261+
}
262+
263+
// Return as is
264+
return ip;
265+
}

0 commit comments

Comments
 (0)