Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/daemon/NKS.WebDevConsole.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@
try
{
var installed = await client.GetJsonAsync("/api/binaries/installed");
var keyApps = new[] { "apache", "php", "mysql", "node", "redis", "nginx", "mariadb" };
var keyApps = new[] { "apache", "php", "mysql", "mariadb", "postgresql", "node", "redis", "nginx" };
foreach (var app in keyApps)
{
var first = installed.EnumerateArray()
Expand Down
11 changes: 11 additions & 0 deletions src/daemon/NKS.WebDevConsole.Daemon/Binaries/CatalogClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,17 @@ private static IEnumerable<BinaryRelease> BuiltInFallback()
ArchiveType: "tgz",
Source: "github",
UserAgent: null);

yield return new BinaryRelease(
App: "postgresql",
Version: "18.3",
MajorMinor: "18",
Url: "https://get.enterprisedb.com/postgresql/postgresql-18.3-1-windows-x64-binaries.zip",
Os: "windows",
Arch: "x64",
ArchiveType: "zip",
Source: "enterprisedb",
UserAgent: null);
}

public IEnumerable<BinaryRelease> ForApp(string app, string? os = null, string? arch = null)
Expand Down
14 changes: 8 additions & 6 deletions src/daemon/NKS.WebDevConsole.Daemon/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -662,11 +662,12 @@ static bool IsLoopbackPortFree(System.Net.IPAddress addr, int port)
{
"apache" or "caddy" or "nginx" =>
new[] { ("ports.http", "HttpPort"), ("ports.https", "HttpsPort") },
"mysql" => new[] { ("ports.mysql", "Port") },
"mariadb" => new[] { ("ports.mariadb", "Port") },
"redis" => new[] { ("ports.redis", "Port") },
"mailpit" => new[] { ("ports.mailpitSmtp", "SmtpPort"),
("ports.mailpitHttp", "HttpPort") },
"mysql" => new[] { ("ports.mysql", "Port") },
"mariadb" => new[] { ("ports.mariadb", "Port") },
"postgresql" => new[] { ("ports.postgresql", "Port") },
"redis" => new[] { ("ports.redis", "Port") },
"mailpit" => new[] { ("ports.mailpitSmtp", "SmtpPort"),
("ports.mailpitHttp", "HttpPort") },
_ => Array.Empty<(string, string)>(),
};
foreach (var (k, propName) in mapping)
Expand Down Expand Up @@ -9624,7 +9625,7 @@ await conn.ExecuteAsync(
{
// Heuristic: match `ports.<serviceId>` or any port key that
// looks like it could belong to this module (http/https map
// to apache/caddy/nginx; mysql/redis/mariadb keys map 1:1).
// to apache/caddy/nginx; database/cache keys map 1:1).
var moduleId = module.ServiceId.ToLowerInvariant();
var relevant = portKeys.Any(k =>
{
Expand Down Expand Up @@ -9668,6 +9669,7 @@ await conn.ExecuteAsync(
"https" when moduleId == "apache" || moduleId == "caddy" || moduleId == "nginx" => "HttpsPort",
"mysql" when moduleId == "mysql" => "Port",
"mariadb" when moduleId == "mariadb" => "Port",
"postgresql" when moduleId == "postgresql" => "Port",
"redis" when moduleId == "redis" => "Port",
"mailpitsmtp" when moduleId == "mailpit" => "SmtpPort",
"mailpithttp" when moduleId == "mailpit" => "HttpPort",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace NKS.WebDevConsole.Daemon.Services;
/// <summary>
/// Pre-registers Windows Defender Firewall inbound rules for NKS WDC managed
/// service ports so the user doesn't get the per-first-bind UAC prompt each
/// time a managed binary (Apache, MySQL, Redis, Mailpit) opens a socket for
/// time a managed binary (Apache, MySQL, PostgreSQL, Redis, Mailpit) opens a socket for
/// the first time.
///
/// Rule naming convention:
Expand Down Expand Up @@ -45,6 +45,7 @@ private static readonly (string Service, int Port)[] ManagedPorts =
("apache-http", 80),
("apache-https", 443),
("mysql", 3306),
("postgresql", 5432),
("redis", 6379),
("mailpit-smtp", 1025),
("mailpit-web", 8025),
Expand Down
6 changes: 6 additions & 0 deletions src/frontend/src/components/pages/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@
<el-form-item :label="$t('settings.ports.mysqlPort')">
<el-input-number v-model="ports.mysql" :min="1" :max="65535" style="width: 100%" />
</el-form-item>
<el-form-item :label="$t('settings.ports.postgresqlPort')">
<el-input-number v-model="ports.postgresql" :min="1" :max="65535" style="width: 100%" />
</el-form-item>
<el-form-item :label="$t('settings.ports.redisPort')">
<el-input-number v-model="ports.redis" :min="1" :max="65535" style="width: 100%" />
</el-form-item>
Expand Down Expand Up @@ -1058,6 +1061,7 @@ const ports = reactive({
http: 80,
https: 443,
mysql: 3306,
postgresql: 5432,
redis: 6379,
mailpitSmtp: 1025,
mailpitHttp: 8025,
Expand Down Expand Up @@ -1687,6 +1691,7 @@ async function loadSettings() {
deployUseLegacyHostHandlers.value = !(data['deploy.useLegacyHostHandlers'] === 'false'
|| data['deploy.useLegacyHostHandlers'] === '0')
if (data['ports.mysql']) ports.mysql = parseInt(data['ports.mysql'])
if (data['ports.postgresql']) ports.postgresql = parseInt(data['ports.postgresql'])
if (data['ports.redis']) ports.redis = parseInt(data['ports.redis'])
if (data['ports.mailpitSmtp']) ports.mailpitSmtp = parseInt(data['ports.mailpitSmtp'])
if (data['ports.mailpitHttp']) ports.mailpitHttp = parseInt(data['ports.mailpitHttp'])
Expand Down Expand Up @@ -2559,6 +2564,7 @@ async function save() {
'ports.http': String(ports.http),
'ports.https': String(ports.https),
'ports.mysql': String(ports.mysql),
'ports.postgresql': String(ports.postgresql),
'ports.redis': String(ports.redis),
'ports.mailpitSmtp': String(ports.mailpitSmtp),
'mcp.enabled': String(mcpEnabled.value),
Expand Down
3 changes: 2 additions & 1 deletion src/frontend/src/components/shared/ServiceIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const SHORT_ID: Record<string, string> = {
'nks.wdc.caddy': 'caddy',
'nks.wdc.php': 'php',
'nks.wdc.mysql': 'mysql',
'nks.wdc.postgresql': 'postgresql',
'nks.wdc.redis': 'redis',
'nks.wdc.mailpit': 'mailpit',
}
Expand All @@ -58,7 +59,7 @@ const iconUrl = computed(() => {
// headers, so pipe the token through the query string (the auth middleware
// in Program.cs accepts `?token=` as a fallback to the Bearer header).
// Without this every brand icon 401s and the sidebar fills up with "N".
const knownPlugin = ['apache', 'caddy', 'php', 'mysql', 'redis', 'mailpit'].includes(shortId)
const knownPlugin = ['apache', 'caddy', 'php', 'mysql', 'postgresql', 'redis', 'mailpit'].includes(shortId)
if (knownPlugin) {
const token = daemonToken()
const suffix = token ? `?token=${encodeURIComponent(token)}` : ''
Expand Down
3 changes: 2 additions & 1 deletion src/frontend/src/locales/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1716,6 +1716,7 @@
"httpPort": "HTTP port",
"httpsPort": "HTTPS port",
"mysqlPort": "MySQL port",
"postgresqlPort": "PostgreSQL port",
"redisPort": "Redis port",
"mailpitSmtp": "Mailpit SMTP",
"mailpitHttp": "Mailpit HTTP",
Expand Down Expand Up @@ -2093,4 +2094,4 @@
"sampleSiteWarn": "Ukázkový web možná nebyl vytvořen — zkontroluj stránku Weby",
"dontShowAgain": "Příště nezobrazovat"
}
}
}
3 changes: 2 additions & 1 deletion src/frontend/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1714,6 +1714,7 @@
"httpPort": "HTTP Port",
"httpsPort": "HTTPS Port",
"mysqlPort": "MySQL Port",
"postgresqlPort": "PostgreSQL Port",
"redisPort": "Redis Port",
"mailpitSmtp": "Mailpit SMTP",
"mailpitHttp": "Mailpit HTTP",
Expand Down Expand Up @@ -2091,4 +2092,4 @@
"sampleSiteWarn": "Sample site may not have been created — check Sites page",
"dontShowAgain": "Don't show again"
}
}
}
1 change: 1 addition & 0 deletions tests/NKS.WebDevConsole.Core.Tests/BinaryCatalogTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public void All_ContainsExpectedApps()
Assert.Contains("apache", apps);
Assert.Contains("php", apps);
Assert.Contains("mysql", apps);
Assert.Contains("postgresql", apps);
Assert.Contains("redis", apps);
Assert.Contains("mailpit", apps);
Assert.Contains("nginx", apps);
Expand Down
15 changes: 14 additions & 1 deletion tests/NKS.WebDevConsole.Daemon.Tests/CatalogClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public async Task RefreshAsync_ServerError_StillPopulatesBuiltInFallback()

var count = await client.RefreshAsync();

Assert.True(count >= 3); // at least the 3 cloudflared fallback entries
Assert.True(count >= 4); // cloudflared + PostgreSQL fallback entries
Assert.NotEmpty(client.CachedReleases);
Assert.NotEqual(DateTime.MinValue, client.LastFetch);
}
Expand All @@ -83,6 +83,19 @@ public async Task RefreshAsync_BuiltInFallback_IncludesCloudflaredForAllPlatform
Assert.Single(macos);
}

[Fact]
public async Task RefreshAsync_BuiltInFallback_IncludesPostgreSqlWindows()
{
var client = MakeClient(HttpStatusCode.InternalServerError);
await client.RefreshAsync();

var postgresql = client.ForApp("postgresql", os: "windows", arch: "x64").ToList();

Assert.Single(postgresql);
Assert.Equal("18.3", postgresql[0].Version);
Assert.Equal("zip", postgresql[0].ArchiveType);
}

[Fact]
public async Task ForApp_FiltersByAppCaseInsensitive()
{
Expand Down
Loading