mirror of
https://github.com/fosrl/pangolin.git
synced 2026-10-29 06:59:06 +01:00
♻️ rename destinationDomain to destinationHost to include the Scheme
This commit is contained in:
@@ -243,7 +243,7 @@ export const redirects = pgTable("redirects", {
|
||||
niceId: text("niceId").notNull(),
|
||||
name: varchar("name").notNull(),
|
||||
subdomain: varchar("subdomain"),
|
||||
destinationDomain: varchar("destinationDomain").notNull(),
|
||||
destinationHost: varchar("destinationHost").notNull(), // scheme://host[:port]
|
||||
pathMatchType: varchar("pathMatchType")
|
||||
.$type<"exact" | "prefix" | "regex">()
|
||||
.notNull()
|
||||
|
||||
@@ -60,7 +60,7 @@ export type RedirectByHost = {
|
||||
orgId: string;
|
||||
matchPath: string | null;
|
||||
pathMatchType: string;
|
||||
destinationDomain: string;
|
||||
destinationHost: string;
|
||||
rewritePath: string | null;
|
||||
rewritePathType: string | null;
|
||||
permanent: boolean;
|
||||
@@ -102,7 +102,7 @@ export async function getRedirectsByHost(
|
||||
orgId: redirects.orgId,
|
||||
matchPath: redirects.matchPath,
|
||||
pathMatchType: redirects.pathMatchType,
|
||||
destinationDomain: redirects.destinationDomain,
|
||||
destinationHost: redirects.destinationHost,
|
||||
rewritePath: redirects.rewritePath,
|
||||
rewritePathType: redirects.rewritePathType,
|
||||
permanent: redirects.permanent,
|
||||
|
||||
@@ -259,7 +259,7 @@ export const redirects = sqliteTable("redirects", {
|
||||
niceId: text("niceId").notNull(),
|
||||
name: text("name").notNull(),
|
||||
subdomain: text("subdomain"),
|
||||
destinationDomain: text("destinationDomain").notNull(),
|
||||
destinationHost: text("destinationHost").notNull(), // scheme://host[:port]
|
||||
pathMatchType: text("pathMatchType")
|
||||
.$type<"exact" | "prefix" | "regex">()
|
||||
.notNull()
|
||||
|
||||
@@ -1060,8 +1060,8 @@ async function findRedirect(
|
||||
}
|
||||
|
||||
/**
|
||||
* Destination for a configured redirect: the request's scheme and query are
|
||||
* kept, the host is swapped for the destination domain and the path is run
|
||||
* Destination for a configured redirect: the scheme and host come from the
|
||||
* redirect's destination, the request's query is kept and the path is run
|
||||
* through the redirect's rewrite rules (if any).
|
||||
*/
|
||||
function buildRedirectUrl(
|
||||
@@ -1083,7 +1083,7 @@ function buildRedirectUrl(
|
||||
// originalRequestURL is validated as a URL, so this is only defensive
|
||||
}
|
||||
|
||||
return `${request.scheme}://${redirect.destinationDomain}${newPath}${search}`;
|
||||
return `${redirect.destinationHost}${newPath}${search}`;
|
||||
}
|
||||
|
||||
// Like a notAllowed login bounce, but the destination is the configured
|
||||
|
||||
@@ -10,7 +10,7 @@ import { fromError } from "zod-validation-error";
|
||||
import { OpenAPITags, registry } from "@server/openApi";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import {
|
||||
redirectDestinationDomainSchema,
|
||||
redirectDestinationHostSchema,
|
||||
redirectMatchPathSchema,
|
||||
redirectPathMatchTypeSchema,
|
||||
redirectRewritePathSchema,
|
||||
@@ -36,7 +36,7 @@ const bodySchema = z
|
||||
resourceId: z.number().int().positive().optional().nullable(),
|
||||
domainId: z.string().nonempty().optional().nullable(),
|
||||
subdomain: z.string().nonempty().optional().nullable(),
|
||||
destinationDomain: redirectDestinationDomainSchema,
|
||||
destinationHost: redirectDestinationHostSchema,
|
||||
pathMatchType: redirectPathMatchTypeSchema.optional(),
|
||||
matchPath: redirectMatchPathSchema.optional().nullable(),
|
||||
rewritePath: redirectRewritePathSchema.optional().nullable(),
|
||||
@@ -126,7 +126,7 @@ export async function createRedirect(
|
||||
resourceId,
|
||||
domainId,
|
||||
subdomain,
|
||||
destinationDomain,
|
||||
destinationHost,
|
||||
pathMatchType,
|
||||
matchPath,
|
||||
rewritePath,
|
||||
@@ -200,7 +200,7 @@ export async function createRedirect(
|
||||
resourceId: resourceId ?? null,
|
||||
domainId: domainId ?? null,
|
||||
subdomain: subdomain ?? null,
|
||||
destinationDomain,
|
||||
destinationHost,
|
||||
pathMatchType: pathMatchType ?? "regex",
|
||||
matchPath: matchPath ?? null,
|
||||
rewritePath: rewritePath ?? null,
|
||||
|
||||
@@ -17,7 +17,7 @@ export type GetRedirectResponse = {
|
||||
niceId: string;
|
||||
name: string;
|
||||
subdomain: string | null;
|
||||
destinationDomain: string;
|
||||
destinationHost: string;
|
||||
pathMatchType: "exact" | "prefix" | "regex";
|
||||
matchPath: string | null;
|
||||
rewritePath: string | null;
|
||||
@@ -43,7 +43,7 @@ const redirectColumns = {
|
||||
niceId: redirects.niceId,
|
||||
name: redirects.name,
|
||||
subdomain: redirects.subdomain,
|
||||
destinationDomain: redirects.destinationDomain,
|
||||
destinationHost: redirects.destinationHost,
|
||||
pathMatchType: redirects.pathMatchType,
|
||||
matchPath: redirects.matchPath,
|
||||
rewritePath: redirects.rewritePath,
|
||||
|
||||
@@ -17,7 +17,7 @@ export type ListRedirectsResponse = PaginatedResponse<{
|
||||
niceId: string;
|
||||
name: string;
|
||||
subdomain: string | null;
|
||||
destinationDomain: string;
|
||||
destinationHost: string;
|
||||
pathMatchType: "exact" | "prefix" | "regex";
|
||||
matchPath: string | null;
|
||||
rewritePath: string | null;
|
||||
@@ -130,7 +130,7 @@ export async function listRedirects(
|
||||
or(
|
||||
like(sql`LOWER(${redirects.name})`, term),
|
||||
like(sql`LOWER(${redirects.matchPath})`, term),
|
||||
like(sql`LOWER(${redirects.destinationDomain})`, term)
|
||||
like(sql`LOWER(${redirects.destinationHost})`, term)
|
||||
)!
|
||||
);
|
||||
}
|
||||
@@ -142,7 +142,7 @@ export async function listRedirects(
|
||||
niceId: redirects.niceId,
|
||||
name: redirects.name,
|
||||
subdomain: redirects.subdomain,
|
||||
destinationDomain: redirects.destinationDomain,
|
||||
destinationHost: redirects.destinationHost,
|
||||
pathMatchType: redirects.pathMatchType,
|
||||
matchPath: redirects.matchPath,
|
||||
rewritePath: redirects.rewritePath,
|
||||
|
||||
@@ -11,7 +11,7 @@ import { OpenAPITags, registry } from "@server/openApi";
|
||||
import { and, eq, ne } from "drizzle-orm";
|
||||
import {
|
||||
redirectNiceIdSchema,
|
||||
redirectDestinationDomainSchema,
|
||||
redirectDestinationHostSchema,
|
||||
redirectMatchPathSchema,
|
||||
redirectPathMatchTypeSchema,
|
||||
redirectRewritePathSchema,
|
||||
@@ -37,7 +37,7 @@ const bodySchema = z.strictObject({
|
||||
resourceId: z.number().int().positive().optional().nullable(),
|
||||
domainId: z.string().nonempty().optional().nullable(),
|
||||
subdomain: z.string().nonempty().optional().nullable(),
|
||||
destinationDomain: redirectDestinationDomainSchema.optional(),
|
||||
destinationHost: redirectDestinationHostSchema.optional(),
|
||||
pathMatchType: redirectPathMatchTypeSchema.optional(),
|
||||
matchPath: redirectMatchPathSchema.optional().nullable(),
|
||||
rewritePath: redirectRewritePathSchema.optional().nullable(),
|
||||
@@ -253,8 +253,8 @@ export async function updateRedirect(
|
||||
if (body.subdomain !== undefined) {
|
||||
updateData.subdomain = body.subdomain;
|
||||
}
|
||||
if (body.destinationDomain !== undefined) {
|
||||
updateData.destinationDomain = body.destinationDomain;
|
||||
if (body.destinationHost !== undefined) {
|
||||
updateData.destinationHost = body.destinationHost;
|
||||
}
|
||||
if (body.pathMatchType !== undefined) {
|
||||
updateData.pathMatchType = body.pathMatchType;
|
||||
|
||||
@@ -49,11 +49,20 @@ export const redirectRewritePathSchema = z.string().nonempty();
|
||||
// Same range as target priorities; 100 means "let the system order it".
|
||||
export const redirectPrioritySchema = z.int().min(1).max(1000);
|
||||
|
||||
export const redirectDestinationDomainSchema = z
|
||||
/**
|
||||
* A destination is `scheme://host[:port]` with no path, query or fragment;
|
||||
* the request path (after any rewrite) is appended to it by badger.
|
||||
*/
|
||||
export function isValidDestinationHost(value: string): boolean {
|
||||
const match = /^https?:\/\/([^/:?#]+)(:\d{1,5})?$/.exec(value);
|
||||
return match !== null && isValidDomain(match[1]);
|
||||
}
|
||||
|
||||
export const redirectDestinationHostSchema = z
|
||||
.string()
|
||||
.nonempty()
|
||||
.refine(isValidDomain, {
|
||||
message: "Invalid domain"
|
||||
.refine(isValidDestinationHost, {
|
||||
message: "Invalid destination, expected scheme://host such as https://example.com"
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user