diff --git a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.tsx b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.tsx index 55211eb2fb0..86c8a961ee1 100644 --- a/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/[project_slug]/settings/ProjectGeneralSettingsPage.tsx @@ -35,9 +35,9 @@ import { type FieldArrayWithId, useFieldArray } from "react-hook-form"; import { toast } from "sonner"; import { joinWithComma, toArrFromList } from "utils/string"; import { - type ApiKeyValidationSchema, HIDDEN_SERVICES, - apiKeyValidationSchema, + type ProjectSettingsPageFormSchema, + projectSettingsPageFormSchema, } from "../../../../../components/settings/ApiKeys/validations"; type EditProjectUIPaths = { @@ -86,7 +86,7 @@ interface EditApiKeyProps { showNebulaSettings: boolean; } -type UpdateAPIForm = UseFormReturn; +type UpdateAPIForm = UseFormReturn; export const ProjectGeneralSettingsPageUI: React.FC = ( props, @@ -94,8 +94,8 @@ export const ProjectGeneralSettingsPageUI: React.FC = ( const { apiKey, updateMutation, deleteMutation } = props; const trackEvent = useTrack(); const router = useDashboardRouter(); - const form = useForm({ - resolver: zodResolver(apiKeyValidationSchema), + const form = useForm({ + resolver: zodResolver(projectSettingsPageFormSchema), defaultValues: { name: apiKey.name, domains: joinWithComma(apiKey.domains), @@ -484,7 +484,7 @@ function EnabledServicesSetting(props: { }); const handleAction = ( srvIdx: number, - srv: FieldArrayWithId, + srv: FieldArrayWithId, actionName: string, checked: boolean, ) => { diff --git a/apps/dashboard/src/components/embedded-wallets/Configure/index.tsx b/apps/dashboard/src/components/embedded-wallets/Configure/index.tsx index 4fa6c060ccf..33f38477f22 100644 --- a/apps/dashboard/src/components/embedded-wallets/Configure/index.tsx +++ b/apps/dashboard/src/components/embedded-wallets/Configure/index.tsx @@ -422,6 +422,10 @@ function AuthEndpointFields(props: { name: "customAuthEndpoint.customHeaders", }); + const expandCustomAuthEndpointField = + form.watch("customAuthEndpoint")?.authEndpoint !== undefined && + canEditAdvancedFeatures; + return (
{ form.setValue( @@ -464,7 +466,7 @@ function AuthEndpointFields(props: { validStrList(str, (domain) => { - return domain.split(":")[0] === "localhost" || RE_DOMAIN.test(domain); + return domain.startsWith("localhost:") || RE_DOMAIN.test(domain); }), { message: "Some of the domains are invalid", @@ -95,26 +95,55 @@ export const apiKeyCreateValidationSchema = z.object({ services: servicesValidation, }); -export const apiKeyValidationSchema = z.object({ +function isValidRedirectURI(uri: string) { + // whitespace is not allowed + if (/\s/g.test(uri)) { + return false; + } + + // foo://... is allowed + if (uri.includes("://")) { + return true; + } + + // localhost:... is allowed + if (uri.startsWith("localhost:")) { + return true; + } + + // valid url is allowed + try { + new URL(uri); + return true; + } catch { + // invalid + } + + // everything else is invalid + return false; +} + +const redirectUriSchema = z + .string() + .refine((str) => validStrList(str, isValidRedirectURI), { + message: + "Some of the redirect URIs are invalid. Make sure they are valid URIs and do not contain spaces.", + }) + .refine((str) => str !== "*", { + message: "Wildcard redirect URIs are not allowed", + }); + +// TODO: move this schema to project settings folder in separate PR +export const projectSettingsPageFormSchema = z.object({ name: nameValidation, domains: domainsValidation, services: servicesValidation, bundleIds: z.string().refine((str) => validStrList(str, RE_BUNDLE_ID), { message: "Some of the bundle ids are invalid", }), - redirectUrls: z - .string() - .refine( - (str) => - validStrList(str, (url) => url.includes("://") && !/\s/g.test(url)), - { - message: - "Some of the redirect URIs are invalid. Make sure they are valid URIs and do not contain spaces.", - }, - ) - .refine((str) => str !== "*", { - message: "Wildcard redirect URIs are not allowed", - }), + // no strict validation for redirectUrls, because project general page does not render redirectUrls form field + // so if the user has already saved an invalid `redirectUrls` on in-app wallet project settings page ( which is fixed now ) - it won't prevent them from updating the general project settings + redirectUrls: z.string(), }); export const apiKeyEmbeddedWalletsValidationSchema = z.object({ @@ -127,7 +156,7 @@ export const apiKeyEmbeddedWalletsValidationSchema = z.object({ applicationImageUrl: applicationImageUrlValidation, }), ]), - redirectUrls: z.union([z.undefined(), z.string()]), + redirectUrls: redirectUriSchema, }); export const apiKeyPayConfigValidationSchema = z.object({ @@ -138,7 +167,9 @@ export type ApiKeyCreateValidationSchema = z.infer< typeof apiKeyCreateValidationSchema >; -export type ApiKeyValidationSchema = z.infer; +export type ProjectSettingsPageFormSchema = z.infer< + typeof projectSettingsPageFormSchema +>; export type ApiKeyEmbeddedWalletsValidationSchema = z.infer< typeof apiKeyEmbeddedWalletsValidationSchema