mirror of
https://github.com/fosrl/pangolin.git
synced 2026-09-19 09:09:51 +02:00
♻️ rename destinationDomain to destinationHost to include the Scheme
This commit is contained in:
+4
-4
@@ -4421,12 +4421,12 @@
|
|||||||
"redirectDeleteConfirm": "Confirm Delete Redirect",
|
"redirectDeleteConfirm": "Confirm Delete Redirect",
|
||||||
"redirectQuestionRemove": "Are you sure you want to remove this redirect?",
|
"redirectQuestionRemove": "Are you sure you want to remove this redirect?",
|
||||||
"redirectMessageRemove": "Once removed, requests matching this redirect will no longer be forwarded.",
|
"redirectMessageRemove": "Once removed, requests matching this redirect will no longer be forwarded.",
|
||||||
"redirectDestinationDomain": "Destination Domain",
|
"redirectDestinationHost": "Destination",
|
||||||
"redirectDestinationDomainDescription": "The domain requests are sent to, such as example.com",
|
"redirectDestinationHostDescription": "Where requests are sent, including the scheme, such as https://example.com",
|
||||||
"redirectDestinationDomainRequired": "Enter a destination domain",
|
"redirectDestinationHostRequired": "Enter a destination",
|
||||||
"redirectSameDomainAsSource": "Same domain as source",
|
"redirectSameDomainAsSource": "Same domain as source",
|
||||||
"redirectSameDomainAsSourceDescription": "Keep the destination on the source domain and only change the path",
|
"redirectSameDomainAsSourceDescription": "Keep the destination on the source domain and only change the path",
|
||||||
"redirectDestinationDomainInvalid": "Enter a valid domain, such as example.com",
|
"redirectDestinationHostInvalid": "Enter a valid destination with a scheme, such as https://example.com",
|
||||||
"redirectMatchPathDescription": "Which incoming paths this redirect applies to",
|
"redirectMatchPathDescription": "Which incoming paths this redirect applies to",
|
||||||
"redirectRewritePathDescription": "Optionally change the path before redirecting. Leave unset to keep the original path.",
|
"redirectRewritePathDescription": "Optionally change the path before redirecting. Leave unset to keep the original path.",
|
||||||
"redirectRewritePathRequired": "Enter a rewrite path, or choose Strip Prefix",
|
"redirectRewritePathRequired": "Enter a rewrite path, or choose Strip Prefix",
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ export const redirects = pgTable("redirects", {
|
|||||||
niceId: text("niceId").notNull(),
|
niceId: text("niceId").notNull(),
|
||||||
name: varchar("name").notNull(),
|
name: varchar("name").notNull(),
|
||||||
subdomain: varchar("subdomain"),
|
subdomain: varchar("subdomain"),
|
||||||
destinationDomain: varchar("destinationDomain").notNull(),
|
destinationHost: varchar("destinationHost").notNull(), // scheme://host[:port]
|
||||||
pathMatchType: varchar("pathMatchType")
|
pathMatchType: varchar("pathMatchType")
|
||||||
.$type<"exact" | "prefix" | "regex">()
|
.$type<"exact" | "prefix" | "regex">()
|
||||||
.notNull()
|
.notNull()
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export type RedirectByHost = {
|
|||||||
orgId: string;
|
orgId: string;
|
||||||
matchPath: string | null;
|
matchPath: string | null;
|
||||||
pathMatchType: string;
|
pathMatchType: string;
|
||||||
destinationDomain: string;
|
destinationHost: string;
|
||||||
rewritePath: string | null;
|
rewritePath: string | null;
|
||||||
rewritePathType: string | null;
|
rewritePathType: string | null;
|
||||||
permanent: boolean;
|
permanent: boolean;
|
||||||
@@ -102,7 +102,7 @@ export async function getRedirectsByHost(
|
|||||||
orgId: redirects.orgId,
|
orgId: redirects.orgId,
|
||||||
matchPath: redirects.matchPath,
|
matchPath: redirects.matchPath,
|
||||||
pathMatchType: redirects.pathMatchType,
|
pathMatchType: redirects.pathMatchType,
|
||||||
destinationDomain: redirects.destinationDomain,
|
destinationHost: redirects.destinationHost,
|
||||||
rewritePath: redirects.rewritePath,
|
rewritePath: redirects.rewritePath,
|
||||||
rewritePathType: redirects.rewritePathType,
|
rewritePathType: redirects.rewritePathType,
|
||||||
permanent: redirects.permanent,
|
permanent: redirects.permanent,
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ export const redirects = sqliteTable("redirects", {
|
|||||||
niceId: text("niceId").notNull(),
|
niceId: text("niceId").notNull(),
|
||||||
name: text("name").notNull(),
|
name: text("name").notNull(),
|
||||||
subdomain: text("subdomain"),
|
subdomain: text("subdomain"),
|
||||||
destinationDomain: text("destinationDomain").notNull(),
|
destinationHost: text("destinationHost").notNull(), // scheme://host[:port]
|
||||||
pathMatchType: text("pathMatchType")
|
pathMatchType: text("pathMatchType")
|
||||||
.$type<"exact" | "prefix" | "regex">()
|
.$type<"exact" | "prefix" | "regex">()
|
||||||
.notNull()
|
.notNull()
|
||||||
|
|||||||
@@ -1060,8 +1060,8 @@ async function findRedirect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destination for a configured redirect: the request's scheme and query are
|
* Destination for a configured redirect: the scheme and host come from the
|
||||||
* kept, the host is swapped for the destination domain and the path is run
|
* redirect's destination, the request's query is kept and the path is run
|
||||||
* through the redirect's rewrite rules (if any).
|
* through the redirect's rewrite rules (if any).
|
||||||
*/
|
*/
|
||||||
function buildRedirectUrl(
|
function buildRedirectUrl(
|
||||||
@@ -1083,7 +1083,7 @@ function buildRedirectUrl(
|
|||||||
// originalRequestURL is validated as a URL, so this is only defensive
|
// 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
|
// 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 { OpenAPITags, registry } from "@server/openApi";
|
||||||
import { and, eq } from "drizzle-orm";
|
import { and, eq } from "drizzle-orm";
|
||||||
import {
|
import {
|
||||||
redirectDestinationDomainSchema,
|
redirectDestinationHostSchema,
|
||||||
redirectMatchPathSchema,
|
redirectMatchPathSchema,
|
||||||
redirectPathMatchTypeSchema,
|
redirectPathMatchTypeSchema,
|
||||||
redirectRewritePathSchema,
|
redirectRewritePathSchema,
|
||||||
@@ -36,7 +36,7 @@ const bodySchema = z
|
|||||||
resourceId: z.number().int().positive().optional().nullable(),
|
resourceId: z.number().int().positive().optional().nullable(),
|
||||||
domainId: z.string().nonempty().optional().nullable(),
|
domainId: z.string().nonempty().optional().nullable(),
|
||||||
subdomain: z.string().nonempty().optional().nullable(),
|
subdomain: z.string().nonempty().optional().nullable(),
|
||||||
destinationDomain: redirectDestinationDomainSchema,
|
destinationHost: redirectDestinationHostSchema,
|
||||||
pathMatchType: redirectPathMatchTypeSchema.optional(),
|
pathMatchType: redirectPathMatchTypeSchema.optional(),
|
||||||
matchPath: redirectMatchPathSchema.optional().nullable(),
|
matchPath: redirectMatchPathSchema.optional().nullable(),
|
||||||
rewritePath: redirectRewritePathSchema.optional().nullable(),
|
rewritePath: redirectRewritePathSchema.optional().nullable(),
|
||||||
@@ -126,7 +126,7 @@ export async function createRedirect(
|
|||||||
resourceId,
|
resourceId,
|
||||||
domainId,
|
domainId,
|
||||||
subdomain,
|
subdomain,
|
||||||
destinationDomain,
|
destinationHost,
|
||||||
pathMatchType,
|
pathMatchType,
|
||||||
matchPath,
|
matchPath,
|
||||||
rewritePath,
|
rewritePath,
|
||||||
@@ -200,7 +200,7 @@ export async function createRedirect(
|
|||||||
resourceId: resourceId ?? null,
|
resourceId: resourceId ?? null,
|
||||||
domainId: domainId ?? null,
|
domainId: domainId ?? null,
|
||||||
subdomain: subdomain ?? null,
|
subdomain: subdomain ?? null,
|
||||||
destinationDomain,
|
destinationHost,
|
||||||
pathMatchType: pathMatchType ?? "regex",
|
pathMatchType: pathMatchType ?? "regex",
|
||||||
matchPath: matchPath ?? null,
|
matchPath: matchPath ?? null,
|
||||||
rewritePath: rewritePath ?? null,
|
rewritePath: rewritePath ?? null,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export type GetRedirectResponse = {
|
|||||||
niceId: string;
|
niceId: string;
|
||||||
name: string;
|
name: string;
|
||||||
subdomain: string | null;
|
subdomain: string | null;
|
||||||
destinationDomain: string;
|
destinationHost: string;
|
||||||
pathMatchType: "exact" | "prefix" | "regex";
|
pathMatchType: "exact" | "prefix" | "regex";
|
||||||
matchPath: string | null;
|
matchPath: string | null;
|
||||||
rewritePath: string | null;
|
rewritePath: string | null;
|
||||||
@@ -43,7 +43,7 @@ const redirectColumns = {
|
|||||||
niceId: redirects.niceId,
|
niceId: redirects.niceId,
|
||||||
name: redirects.name,
|
name: redirects.name,
|
||||||
subdomain: redirects.subdomain,
|
subdomain: redirects.subdomain,
|
||||||
destinationDomain: redirects.destinationDomain,
|
destinationHost: redirects.destinationHost,
|
||||||
pathMatchType: redirects.pathMatchType,
|
pathMatchType: redirects.pathMatchType,
|
||||||
matchPath: redirects.matchPath,
|
matchPath: redirects.matchPath,
|
||||||
rewritePath: redirects.rewritePath,
|
rewritePath: redirects.rewritePath,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export type ListRedirectsResponse = PaginatedResponse<{
|
|||||||
niceId: string;
|
niceId: string;
|
||||||
name: string;
|
name: string;
|
||||||
subdomain: string | null;
|
subdomain: string | null;
|
||||||
destinationDomain: string;
|
destinationHost: string;
|
||||||
pathMatchType: "exact" | "prefix" | "regex";
|
pathMatchType: "exact" | "prefix" | "regex";
|
||||||
matchPath: string | null;
|
matchPath: string | null;
|
||||||
rewritePath: string | null;
|
rewritePath: string | null;
|
||||||
@@ -130,7 +130,7 @@ export async function listRedirects(
|
|||||||
or(
|
or(
|
||||||
like(sql`LOWER(${redirects.name})`, term),
|
like(sql`LOWER(${redirects.name})`, term),
|
||||||
like(sql`LOWER(${redirects.matchPath})`, 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,
|
niceId: redirects.niceId,
|
||||||
name: redirects.name,
|
name: redirects.name,
|
||||||
subdomain: redirects.subdomain,
|
subdomain: redirects.subdomain,
|
||||||
destinationDomain: redirects.destinationDomain,
|
destinationHost: redirects.destinationHost,
|
||||||
pathMatchType: redirects.pathMatchType,
|
pathMatchType: redirects.pathMatchType,
|
||||||
matchPath: redirects.matchPath,
|
matchPath: redirects.matchPath,
|
||||||
rewritePath: redirects.rewritePath,
|
rewritePath: redirects.rewritePath,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { OpenAPITags, registry } from "@server/openApi";
|
|||||||
import { and, eq, ne } from "drizzle-orm";
|
import { and, eq, ne } from "drizzle-orm";
|
||||||
import {
|
import {
|
||||||
redirectNiceIdSchema,
|
redirectNiceIdSchema,
|
||||||
redirectDestinationDomainSchema,
|
redirectDestinationHostSchema,
|
||||||
redirectMatchPathSchema,
|
redirectMatchPathSchema,
|
||||||
redirectPathMatchTypeSchema,
|
redirectPathMatchTypeSchema,
|
||||||
redirectRewritePathSchema,
|
redirectRewritePathSchema,
|
||||||
@@ -37,7 +37,7 @@ const bodySchema = z.strictObject({
|
|||||||
resourceId: z.number().int().positive().optional().nullable(),
|
resourceId: z.number().int().positive().optional().nullable(),
|
||||||
domainId: z.string().nonempty().optional().nullable(),
|
domainId: z.string().nonempty().optional().nullable(),
|
||||||
subdomain: z.string().nonempty().optional().nullable(),
|
subdomain: z.string().nonempty().optional().nullable(),
|
||||||
destinationDomain: redirectDestinationDomainSchema.optional(),
|
destinationHost: redirectDestinationHostSchema.optional(),
|
||||||
pathMatchType: redirectPathMatchTypeSchema.optional(),
|
pathMatchType: redirectPathMatchTypeSchema.optional(),
|
||||||
matchPath: redirectMatchPathSchema.optional().nullable(),
|
matchPath: redirectMatchPathSchema.optional().nullable(),
|
||||||
rewritePath: redirectRewritePathSchema.optional().nullable(),
|
rewritePath: redirectRewritePathSchema.optional().nullable(),
|
||||||
@@ -253,8 +253,8 @@ export async function updateRedirect(
|
|||||||
if (body.subdomain !== undefined) {
|
if (body.subdomain !== undefined) {
|
||||||
updateData.subdomain = body.subdomain;
|
updateData.subdomain = body.subdomain;
|
||||||
}
|
}
|
||||||
if (body.destinationDomain !== undefined) {
|
if (body.destinationHost !== undefined) {
|
||||||
updateData.destinationDomain = body.destinationDomain;
|
updateData.destinationHost = body.destinationHost;
|
||||||
}
|
}
|
||||||
if (body.pathMatchType !== undefined) {
|
if (body.pathMatchType !== undefined) {
|
||||||
updateData.pathMatchType = body.pathMatchType;
|
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".
|
// Same range as target priorities; 100 means "let the system order it".
|
||||||
export const redirectPrioritySchema = z.int().min(1).max(1000);
|
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()
|
.string()
|
||||||
.nonempty()
|
.nonempty()
|
||||||
.refine(isValidDomain, {
|
.refine(isValidDestinationHost, {
|
||||||
message: "Invalid domain"
|
message: "Invalid destination, expected scheme://host such as https://example.com"
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export default async function RedirectIndexPage(props: RedirectIndexPageProps) {
|
|||||||
niceId: redirect.niceId,
|
niceId: redirect.niceId,
|
||||||
name: redirect.name,
|
name: redirect.name,
|
||||||
subdomain: redirect.subdomain,
|
subdomain: redirect.subdomain,
|
||||||
destinationDomain: redirect.destinationDomain,
|
destinationHost: redirect.destinationHost,
|
||||||
pathMatchType: redirect.pathMatchType,
|
pathMatchType: redirect.pathMatchType,
|
||||||
matchPath: redirect.matchPath,
|
matchPath: redirect.matchPath,
|
||||||
rewritePath: redirect.rewritePath,
|
rewritePath: redirect.rewritePath,
|
||||||
|
|||||||
@@ -40,8 +40,10 @@ import {
|
|||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
import { toast } from "@app/hooks/useToast";
|
import { toast } from "@app/hooks/useToast";
|
||||||
import { createApiClient, formatAxiosError } from "@app/lib/api";
|
import { createApiClient, formatAxiosError } from "@app/lib/api";
|
||||||
import { isValidDomain } from "@server/lib/validators";
|
import {
|
||||||
import { isValidRegex } from "@server/routers/redirect/validation";
|
isValidDestinationHost,
|
||||||
|
isValidRegex
|
||||||
|
} from "@server/routers/redirect/validation";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
import { cn } from "@app/lib/cn";
|
import { cn } from "@app/lib/cn";
|
||||||
import { CaretSortIcon } from "@radix-ui/react-icons";
|
import { CaretSortIcon } from "@radix-ui/react-icons";
|
||||||
@@ -119,14 +121,14 @@ export default function RedirectForm({
|
|||||||
domainId: z.string().nullable(),
|
domainId: z.string().nullable(),
|
||||||
subdomain: z.string().nullable(),
|
subdomain: z.string().nullable(),
|
||||||
resourceId: z.number().int().positive().nullable(),
|
resourceId: z.number().int().positive().nullable(),
|
||||||
destinationDomain: z
|
destinationHost: z
|
||||||
.string()
|
.string()
|
||||||
.trim()
|
.trim()
|
||||||
.min(1, {
|
.min(1, {
|
||||||
message: t("redirectDestinationDomainRequired")
|
message: t("redirectDestinationHostRequired")
|
||||||
})
|
})
|
||||||
.refine(isValidDomain, {
|
.refine(isValidDestinationHost, {
|
||||||
message: t("redirectDestinationDomainInvalid")
|
message: t("redirectDestinationHostInvalid")
|
||||||
}),
|
}),
|
||||||
pathMatchType: z.enum(["exact", "prefix", "regex"]),
|
pathMatchType: z.enum(["exact", "prefix", "regex"]),
|
||||||
matchPath: z.string().trim().nullable(),
|
matchPath: z.string().trim().nullable(),
|
||||||
@@ -196,7 +198,7 @@ export default function RedirectForm({
|
|||||||
domainId: redirect?.domainId ?? null,
|
domainId: redirect?.domainId ?? null,
|
||||||
subdomain: redirect?.subdomain ?? null,
|
subdomain: redirect?.subdomain ?? null,
|
||||||
resourceId: redirect?.resourceId ?? null,
|
resourceId: redirect?.resourceId ?? null,
|
||||||
destinationDomain: redirect?.destinationDomain ?? "",
|
destinationHost: redirect?.destinationHost ?? "",
|
||||||
pathMatchType: redirect?.pathMatchType ?? DEFAULT_PATH_MATCH_TYPE,
|
pathMatchType: redirect?.pathMatchType ?? DEFAULT_PATH_MATCH_TYPE,
|
||||||
matchPath: redirect?.matchPath ?? null,
|
matchPath: redirect?.matchPath ?? null,
|
||||||
rewritePath: redirect?.rewritePath ?? null,
|
rewritePath: redirect?.rewritePath ?? null,
|
||||||
@@ -209,29 +211,32 @@ export default function RedirectForm({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const attachTo = form.watch("attachTo");
|
const attachTo = form.watch("attachTo");
|
||||||
|
const ssl = form.watch("ssl");
|
||||||
|
|
||||||
const sourceFullDomain =
|
const sourceFullDomain =
|
||||||
attachTo === "domain"
|
attachTo === "domain"
|
||||||
? domainFullDomain
|
? domainFullDomain
|
||||||
: (selectedResource?.fullDomain ?? null);
|
: (selectedResource?.fullDomain ?? null);
|
||||||
|
// Resource-attached redirects inherit the resource's ssl setting
|
||||||
|
const sourceSsl =
|
||||||
|
attachTo === "domain" ? ssl : (selectedResource?.ssl ?? true);
|
||||||
|
const sourceHost = sourceFullDomain
|
||||||
|
? `${sourceSsl ? "https" : "http"}://${sourceFullDomain}`
|
||||||
|
: null;
|
||||||
|
|
||||||
// Mirror is UI-only state; on edit, infer it from whether the saved
|
// Mirror is UI-only state; on edit, infer it from whether the saved
|
||||||
// destination already equals the source host.
|
// destination already equals the source host.
|
||||||
const [sameDomainAsSource, setSameDomainAsSource] = useState(
|
const [sameDomainAsSource, setSameDomainAsSource] = useState(
|
||||||
Boolean(
|
Boolean(redirect && sourceHost && redirect.destinationHost === sourceHost)
|
||||||
redirect &&
|
|
||||||
sourceFullDomain &&
|
|
||||||
redirect.destinationDomain === sourceFullDomain
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (sameDomainAsSource && sourceFullDomain) {
|
if (sameDomainAsSource && sourceHost) {
|
||||||
form.setValue("destinationDomain", sourceFullDomain, {
|
form.setValue("destinationHost", sourceHost, {
|
||||||
shouldValidate: true
|
shouldValidate: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [sameDomainAsSource, sourceFullDomain, form]);
|
}, [sameDomainAsSource, sourceHost, form]);
|
||||||
const pathMatchType = form.watch("pathMatchType");
|
const pathMatchType = form.watch("pathMatchType");
|
||||||
const rewritePath = form.watch("rewritePath");
|
const rewritePath = form.watch("rewritePath");
|
||||||
const rewritePathType = form.watch("rewritePathType");
|
const rewritePathType = form.watch("rewritePathType");
|
||||||
@@ -253,7 +258,7 @@ export default function RedirectForm({
|
|||||||
values.attachTo === "domain" ? values.subdomain || null : null,
|
values.attachTo === "domain" ? values.subdomain || null : null,
|
||||||
resourceId:
|
resourceId:
|
||||||
values.attachTo === "resource" ? values.resourceId : null,
|
values.attachTo === "resource" ? values.resourceId : null,
|
||||||
destinationDomain: values.destinationDomain.trim(),
|
destinationHost: values.destinationHost.trim(),
|
||||||
pathMatchType: values.pathMatchType,
|
pathMatchType: values.pathMatchType,
|
||||||
matchPath: values.matchPath?.trim() || null,
|
matchPath: values.matchPath?.trim() || null,
|
||||||
rewritePath: values.rewritePath?.trim() || null,
|
rewritePath: values.rewritePath?.trim() || null,
|
||||||
@@ -674,18 +679,18 @@ export default function RedirectForm({
|
|||||||
<SettingsFormCell span="full">
|
<SettingsFormCell span="full">
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="destinationDomain"
|
name="destinationHost"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>
|
<FormLabel>
|
||||||
{t(
|
{t(
|
||||||
"redirectDestinationDomain"
|
"redirectDestinationHost"
|
||||||
)}
|
)}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
placeholder="example.com"
|
placeholder="https://example.com"
|
||||||
readOnly={
|
readOnly={
|
||||||
sameDomainAsSource
|
sameDomainAsSource
|
||||||
}
|
}
|
||||||
@@ -694,7 +699,7 @@ export default function RedirectForm({
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
{t(
|
{t(
|
||||||
"redirectDestinationDomainDescription"
|
"redirectDestinationHostDescription"
|
||||||
)}
|
)}
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export type RedirectRow = {
|
|||||||
niceId: string;
|
niceId: string;
|
||||||
name: string;
|
name: string;
|
||||||
subdomain: string | null;
|
subdomain: string | null;
|
||||||
destinationDomain: string;
|
destinationHost: string;
|
||||||
pathMatchType: "exact" | "prefix" | "regex";
|
pathMatchType: "exact" | "prefix" | "regex";
|
||||||
matchPath: string | null;
|
matchPath: string | null;
|
||||||
rewritePath: string | null;
|
rewritePath: string | null;
|
||||||
@@ -301,7 +301,7 @@ export default function RedirectsTable({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "destination",
|
id: "destination",
|
||||||
accessorKey: "destinationDomain",
|
accessorKey: "destinationHost",
|
||||||
friendlyName: t("redirectDestination"),
|
friendlyName: t("redirectDestination"),
|
||||||
header: () => (
|
header: () => (
|
||||||
<span className="p-3">{t("redirectDestination")}</span>
|
<span className="p-3">{t("redirectDestination")}</span>
|
||||||
@@ -310,7 +310,7 @@ export default function RedirectsTable({
|
|||||||
const redirect = row.original;
|
const redirect = row.original;
|
||||||
return (
|
return (
|
||||||
<code className="text-sm truncate">
|
<code className="text-sm truncate">
|
||||||
{redirect.destinationDomain}
|
{redirect.destinationHost}
|
||||||
{redirect.rewritePath && (
|
{redirect.rewritePath && (
|
||||||
<span className="text-muted-foreground">
|
<span className="text-muted-foreground">
|
||||||
{redirect.rewritePathType === "prefix"
|
{redirect.rewritePathType === "prefix"
|
||||||
|
|||||||
Reference in New Issue
Block a user