Files
formbricks/apps/web/lib/utils/url.ts
T
Dhruwang Jariwala 939fedfca4 feat: Formbricks 5 (#8017)
Signed-off-by: gulshank0 <gulshanbahadur002@gmail.com>
Co-authored-by: Tiago Farto <tiago@formbricks.com>
Co-authored-by: Johannes <72809645+jobenjada@users.noreply.github.com>
Co-authored-by: pandeymangg <anshuman.pandey9999@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tiago <1585571+xernobyl@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Theodór Tómas <theodortomas@gmail.com>
Co-authored-by: Anshuman Pandey <54475686+pandeymangg@users.noreply.github.com>
Co-authored-by: Bhagya Amarasinghe <b.sithumini@yahoo.com>
Co-authored-by: Chowdhury Tafsir Ahmed Siddiki <ctafsiras@gmail.com>
Co-authored-by: neila <40727091+neila@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Harsh Bhat <90265455+harshsbhat@users.noreply.github.com>
Co-authored-by: Harsh Bhat <harshbhat@Harshs-MacBook-Air.local>
Co-authored-by: Johannes <johannes@formbricks.com>
Co-authored-by: Balázs Úr <balazs@urbalazs.hu>
Co-authored-by: Gulshan <gulshanbahadur002@gmail.com>
Co-authored-by: Harsh Bhat <harsh121102@gmail.com>
Co-authored-by: Javi Aguilar <122741+itsjavi@users.noreply.github.com>
Co-authored-by: Johannes <jobenjada@users.noreply.github.com>
2026-05-15 16:43:27 +00:00

86 lines
2.1 KiB
TypeScript

import { TActionClassPageUrlRule } from "@formbricks/types/action-classes";
export const testURLmatch = (
testUrl: string,
pageUrlValue: string,
pageUrlRule: TActionClassPageUrlRule,
t: (key: string) => string
): boolean => {
let regex: RegExp;
switch (pageUrlRule) {
case "exactMatch":
return testUrl === pageUrlValue;
case "contains":
return testUrl.includes(pageUrlValue);
case "startsWith":
return testUrl.startsWith(pageUrlValue);
case "endsWith":
return testUrl.endsWith(pageUrlValue);
case "notMatch":
return testUrl !== pageUrlValue;
case "notContains":
return !testUrl.includes(pageUrlValue);
case "matchesRegex":
try {
regex = new RegExp(pageUrlValue);
} catch {
throw new Error(t("workspace.actions.invalid_regex"));
}
return regex.test(testUrl);
default:
throw new Error(t("workspace.actions.invalid_match_type"));
}
};
// Helper function to validate callback URLs
export const getValidatedCallbackUrl = (
url: string | null | undefined,
WEBAPP_URL: string
): string | null => {
if (!url) {
return null;
}
try {
const parsedWebAppUrl = new URL(WEBAPP_URL);
const isAbsoluteUrl = /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url);
const isRootRelativePath = url.startsWith("/");
// Reject ambiguous non-URL values like "foo" while still allowing safe root-relative paths.
if (!isAbsoluteUrl && !isRootRelativePath) {
return null;
}
const parsedUrl = isAbsoluteUrl ? new URL(url) : new URL(url, parsedWebAppUrl.origin);
const allowedSchemes = ["https:", "http:"];
const allowedOrigins = new Set([parsedWebAppUrl.origin]);
if (!allowedSchemes.includes(parsedUrl.protocol)) {
return null;
}
if (!allowedOrigins.has(parsedUrl.origin)) {
return null;
}
if (parsedUrl.username || parsedUrl.password) {
return null;
}
return parsedUrl.toString();
} catch {
return null;
}
};
export const isStringUrl = (url: string): boolean => {
try {
new URL(url);
return true;
} catch {
return false;
}
};