mirror of
https://github.com/fosrl/pangolin.git
synced 2026-10-01 02:09:05 +02:00
Merge upstream/dev into feature-response-headers
Resolve conflicts against upstream's refactors: - server/db/sqlite/schema/schema.ts: adopt upstream's reindented sqliteTable(name, cols, indexes) form for sites/resources, re-applying the headers -> requestHeaders/responseHeaders split. Kept in sync with the Postgres schema. - server/lib/traefik/headersMiddleware.ts: extend upstream's extracted buildCustomHeadersMiddleware helper to take requestHeaders and responseHeaders and emit both customRequestHeaders and customResponseHeaders. - server/lib/traefik/getTraefikConfig.ts and server/private/lib/traefik/getTraefikConfig.ts: keep upstream's helper extraction and appendPathMatch refactor, dropping the superseded inline blocks. Also carry the feature forward onto code that moved upstream: - The resource settings UI moved from resources/proxy/[niceId]/proxy to resources/public/[niceId]/http, which dropped this branch's changes in the previous merge. Re-add the request/response header inputs there and rename the vestigial headers field on the tcp page. - messages/da-DK.json is new upstream and still had the old customHeaders key; rename it in line with the other locales. Per the contributing docs, versioned migrations are intentionally omitted so maintainers can write them at release time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -38,7 +38,7 @@ import {
|
||||
} from "@server/lib/schemas";
|
||||
import { registry } from "@server/openApi";
|
||||
import { OpenAPITags } from "@server/openApi";
|
||||
import { createCertificate } from "#dynamic/routers/certificates/createCertificate";
|
||||
import { createCertificate } from "@server/routers/certificates/createCertificate";
|
||||
import {
|
||||
validateAndConstructDomain,
|
||||
checkWildcardDomainConflict
|
||||
@@ -249,6 +249,42 @@ const updateRawResourceBodySchema = z
|
||||
registry.registerPath({
|
||||
method: "post",
|
||||
path: "/resource/{resourceId}",
|
||||
description:
|
||||
"Update a resource. Policy fields (sso, mfa, pincode, password, whitelist) update the inline policy when no shared resource policy is assigned; when a shared policy is assigned those fields override the shared policy for this resource only.",
|
||||
tags: [OpenAPITags.PublicResourceLegacy],
|
||||
request: {
|
||||
params: updateResourceParamsSchema,
|
||||
body: {
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: updateHttpResourceBodySchema.and(
|
||||
updateRawResourceBodySchema
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: "Successful response",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: z.object({
|
||||
data: z.record(z.string(), z.any()).nullable(),
|
||||
success: z.boolean(),
|
||||
error: z.boolean(),
|
||||
message: z.string(),
|
||||
status: z.number()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
registry.registerPath({
|
||||
method: "post",
|
||||
path: "/public-resource/{resourceId}",
|
||||
description:
|
||||
"Update a resource. Policy fields (sso, mfa, pincode, password, whitelist) update the inline policy when no shared resource policy is assigned; when a shared policy is assigned those fields override the shared policy for this resource only.",
|
||||
tags: [OpenAPITags.PublicResource],
|
||||
@@ -318,8 +354,10 @@ export async function updateResource(
|
||||
);
|
||||
}
|
||||
|
||||
if (["http", "ssh", "rdp", "vnc"].includes(resource.mode)) {
|
||||
// HANDLE UPDATING HTTP RESOURCES
|
||||
if (
|
||||
["http", "ssh", "rdp", "vnc", "inference"].includes(resource.mode)
|
||||
) {
|
||||
// HANDLE UPDATING HTTP / BROWSER / INFERENCE RESOURCES
|
||||
return await updateHttpResource(
|
||||
{
|
||||
req,
|
||||
@@ -502,6 +540,20 @@ async function updateHttpResource(
|
||||
}
|
||||
}
|
||||
|
||||
// Wildcard subdomains are not allowed for inference-mode resources
|
||||
if (
|
||||
resource.mode === "inference" &&
|
||||
updateData.subdomain &&
|
||||
updateData.subdomain.includes("*")
|
||||
) {
|
||||
return next(
|
||||
createHttpError(
|
||||
HttpCode.BAD_REQUEST,
|
||||
"Wildcard subdomains are not supported for inference-mode resources."
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Wildcard subdomains are a paid feature
|
||||
if (updateData.subdomain && updateData.subdomain.includes("*")) {
|
||||
if (!isLicensed) {
|
||||
@@ -567,10 +619,23 @@ async function updateHttpResource(
|
||||
logger.debug(`Full domain: ${fullDomain}`);
|
||||
|
||||
if (fullDomain) {
|
||||
// Inference resources route through the central AI gateway
|
||||
// rather than normal target-based proxying, so they're allowed
|
||||
// to share a full-domain with a non-inference resource (and
|
||||
// vice versa) - only conflicts within the same routing category
|
||||
// are rejected. mode isn't updatable here, so `resource.mode`
|
||||
// reflects the resource's actual (unchanging) routing category.
|
||||
const [existingDomain] = await db
|
||||
.select()
|
||||
.from(resources)
|
||||
.where(eq(resources.fullDomain, fullDomain));
|
||||
.where(
|
||||
and(
|
||||
eq(resources.fullDomain, fullDomain),
|
||||
resource.mode === "inference"
|
||||
? ne(resources.mode, "inference")
|
||||
: eq(resources.mode, "inference")
|
||||
)
|
||||
);
|
||||
|
||||
if (
|
||||
existingDomain &&
|
||||
@@ -636,9 +701,7 @@ async function updateHttpResource(
|
||||
// Update the subdomain in the update data
|
||||
updateData.subdomain = finalSubdomain;
|
||||
|
||||
if (build != "oss") {
|
||||
await createCertificate(domainId, fullDomain, db);
|
||||
}
|
||||
await createCertificate(domainId, fullDomain, db);
|
||||
}
|
||||
|
||||
let requestHeaders = undefined;
|
||||
|
||||
Reference in New Issue
Block a user