Skip to content

Commit

Permalink
Fix API key redirect URL schema on in-app wallet settings and unrespo…
Browse files Browse the repository at this point in the history
…nsive general project settings page (#5747)

## Problem solved

Fixes: DASH-629

<!-- start pr-codex -->

---

## PR-Codex overview
This PR focuses on updating the validation schema and related components for project settings, particularly around custom authentication endpoints and redirect URIs. The changes enhance the form handling and validation logic in the dashboard.

### Detailed summary
- Introduced `expandCustomAuthEndpointField` for conditional rendering of custom authentication endpoint fields.
- Updated `checked` property of `GatedSwitch` to use the new variable.
- Modified the placeholder of `Textarea` in `NativeAppsFieldset`.
- Changed `UpdateAPIForm` type to use `ProjectSettingsPageFormSchema`.
- Updated form initialization to use `projectSettingsPageFormSchema`.
- Refined validation logic for redirect URIs, allowing specific formats.
- Created a new `redirectUriSchema` for validating redirect URIs.
- Updated `redirectUrls` validation to use the new schema.
- Changed the exported validation type from `ApiKeyValidationSchema` to `ProjectSettingsPageFormSchema`.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->
  • Loading branch information
MananTank committed Dec 16, 2024
1 parent 7819e1e commit f1cf2fa
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -86,16 +86,16 @@ interface EditApiKeyProps {
showNebulaSettings: boolean;
}

type UpdateAPIForm = UseFormReturn<ApiKeyValidationSchema>;
type UpdateAPIForm = UseFormReturn<ProjectSettingsPageFormSchema>;

export const ProjectGeneralSettingsPageUI: React.FC<EditApiKeyProps> = (
props,
) => {
const { apiKey, updateMutation, deleteMutation } = props;
const trackEvent = useTrack();
const router = useDashboardRouter();
const form = useForm<ApiKeyValidationSchema>({
resolver: zodResolver(apiKeyValidationSchema),
const form = useForm<ProjectSettingsPageFormSchema>({
resolver: zodResolver(projectSettingsPageFormSchema),
defaultValues: {
name: apiKey.name,
domains: joinWithComma(apiKey.domains),
Expand Down Expand Up @@ -484,7 +484,7 @@ function EnabledServicesSetting(props: {
});
const handleAction = (
srvIdx: number,
srv: FieldArrayWithId<ApiKeyValidationSchema, "services", "id">,
srv: FieldArrayWithId<ProjectSettingsPageFormSchema, "services", "id">,
actionName: string,
checked: boolean,
) => {
Expand Down
15 changes: 10 additions & 5 deletions apps/dashboard/src/components/embedded-wallets/Configure/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ function AuthEndpointFields(props: {
name: "customAuthEndpoint.customHeaders",
});

const expandCustomAuthEndpointField =
form.watch("customAuthEndpoint")?.authEndpoint !== undefined &&
canEditAdvancedFeatures;

return (
<div>
<SwitchContainer
Expand All @@ -445,9 +449,7 @@ function AuthEndpointFields(props: {
>
<GatedSwitch
trackingLabel="customAuthEndpoint"
checked={
!!form.watch("customAuthEndpoint") && canEditAdvancedFeatures
}
checked={expandCustomAuthEndpointField}
upgradeRequired={!canEditAdvancedFeatures}
onCheckedChange={(checked) => {
form.setValue(
Expand All @@ -464,7 +466,7 @@ function AuthEndpointFields(props: {
</SwitchContainer>

<AdvancedConfigurationContainer
show={canEditAdvancedFeatures && !!form.watch("customAuthEndpoint")}
show={expandCustomAuthEndpointField}
className="grid grid-cols-1 gap-6 lg:grid-cols-2"
>
<FormField
Expand Down Expand Up @@ -561,7 +563,10 @@ function NativeAppsFieldset(props: {
<FormItem>
<FormLabel>Allowed redirect URIs</FormLabel>
<FormControl>
<Textarea {...field} placeholder="appName://" />
<Textarea
{...field}
placeholder="appName://, localhost:3000, https://example.com"
/>
</FormControl>
<FormDescription>
Enter redirect URIs separated by commas or new lines. This is
Expand Down
65 changes: 48 additions & 17 deletions apps/dashboard/src/components/settings/ApiKeys/validations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const nameValidation = z
const domainsValidation = z.string().refine(
(str) =>
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",
Expand Down Expand Up @@ -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({
Expand All @@ -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({
Expand All @@ -138,7 +167,9 @@ export type ApiKeyCreateValidationSchema = z.infer<
typeof apiKeyCreateValidationSchema
>;

export type ApiKeyValidationSchema = z.infer<typeof apiKeyValidationSchema>;
export type ProjectSettingsPageFormSchema = z.infer<
typeof projectSettingsPageFormSchema
>;

export type ApiKeyEmbeddedWalletsValidationSchema = z.infer<
typeof apiKeyEmbeddedWalletsValidationSchema
Expand Down

0 comments on commit f1cf2fa

Please sign in to comment.