-
Notifications
You must be signed in to change notification settings - Fork 610
feat: centralize validation schemas #2669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8f46c1d
fefc63e
d62e3dc
bbc2f7d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,7 @@ import { trpc } from "@/lib/trpc/client"; | |
| import { zodResolver } from "@hookform/resolvers/zod"; | ||
| import { DialogTrigger } from "@radix-ui/react-dialog"; | ||
| import type { Role } from "@unkey/db"; | ||
| import { validation } from "@unkey/validation"; | ||
| import { useRouter } from "next/navigation"; | ||
| import { useState } from "react"; | ||
| import { useForm } from "react-hook-form"; | ||
|
|
@@ -38,14 +39,8 @@ type Props = { | |
| }; | ||
|
|
||
| const formSchema = z.object({ | ||
| name: z | ||
| .string() | ||
| .min(3) | ||
| .regex(/^[a-zA-Z0-9_:\-\.\*]+$/, { | ||
| message: | ||
| "Must be at least 3 characters long and only contain alphanumeric, colons, periods, dashes and underscores", | ||
| }), | ||
| description: z.string().optional(), | ||
| name: validation.name, | ||
| description: validation.description.optional(), | ||
|
Comment on lines
+42
to
+43
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Now I can make a determination. The validation rules are equivalent: Previous validation: name: z.string().min(3).regex(/^[a-zA-Z0-9_:\-\.\*]+$/, {
message: "Must be at least 3 characters long and only contain alphanumeric, colons, periods, dashes and underscores"
}),
description: z.string().optional()New centralized validation from @unkey/validation: name: z.string().min(3).max(256),
description: z.string().min(3).max(256)The new validation rules are actually more strict for the description field (requiring min 3 chars instead of being completely optional) and add a max length constraint of 256 chars for both fields. The name field drops the regex pattern restriction but maintains the min length requirement. Validation rules have changed and become more restrictive The new schema:
🔗 Analysis chainVerify validation rules equivalence. The schema now uses centralized validation rules. Let's verify that these rules maintain the same validation constraints as before. The previous attempt didn't show us the new validation rules. Let's try to locate the validation module and its contents to compare with the previous implementation we found, which required:
The previous attempt showed us the validation module is imported from multiple places. Let's find its implementation to compare with the previous validation rules we found in the git history. 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Compare old and new validation rules
# Search for previous validation schema definition
echo "Previous validation rules:"
git log -p -S "formSchema = z.object" --full-history -- "apps/dashboard/app/(app)/authorization/roles/[roleId]/update-role.tsx"
# Check the new validation rules implementation
echo -e "\nNew validation rules from @unkey/validation:"
rg -A 10 "export const name = " --type ts
rg -A 10 "export const description = " --type ts
Length of output: 5722 Script: #!/bin/bash
# Let's try a different approach to find the validation rules
# Search for validation rules in the entire codebase
echo "Searching for validation rules:"
fd -e ts -e tsx --exec grep -l "validation" {} \; | xargs cat
# Alternatively, let's try to find the specific import path
echo -e "\nSearching for validation import:"
rg "@unkey/validation" --type ts
Length of output: 259433 Script: #!/bin/bash
# Let's check the validation module's implementation
echo "Searching for validation implementation:"
fd -e ts -e tsx --exec grep -l "export const validation" {} \; | xargs cat
# Also let's check the previous implementation of the form schema
echo -e "\nSearching for previous form schema in the file:"
git log -p -S "formSchema = z.object" -- "apps/dashboard/app/(app)/authorization/roles/[roleId]/update-role.tsx"
Length of output: 6683 |
||
| }); | ||
|
|
||
| export const UpdateRole: React.FC<Props> = ({ trigger, role }) => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,6 +53,7 @@ | |
| "@unkey/rbac": "workspace:^", | ||
| "@unkey/resend": "workspace:^", | ||
| "@unkey/schema": "workspace:^", | ||
| "@unkey/validation": "workspace:^", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Warning: @unkey/validation package is missing but being imported The package is being imported in multiple files but appears to be missing from the workspace:
The workspace dependency cannot be added until the package is created and properly set up in the monorepo. 🔗 Analysis chainLGTM! Verify the @unkey/validation package setup. The addition of Let's verify the package setup: 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Verify the @unkey/validation package existence and configuration
# Check if the package.json exists for @unkey/validation
fd --type f "package.json" | grep -l "validation" | xargs cat
# Check for any existing imports of validation schemas
rg "@unkey/validation" --type ts --type tsx
Length of output: 216 Script: #!/bin/bash
# Let's try a different approach to verify the package setup
# Check if validation package exists in packages directory
fd "package.json" packages/
# Check for any TypeScript files importing from @unkey/validation
rg -t ts "@unkey/validation"
# Look for validation-related files in packages directory
fd "validation" packages/
Length of output: 968 Script: #!/bin/bash
# Let's check the root packages directory specifically for validation package
ls -la packages/validation 2>/dev/null || echo "Validation package not found"
# Check the workspace configuration in root package.json
cat package.json | grep -A 5 "workspaces"
# Check if there are any validation schemas in a potential validation package
fd . packages/validation --type f 2>/dev/null || echo "No validation package files found"
Length of output: 391 |
||
| "@unkey/vault": "workspace:^", | ||
| "@unkey/vercel": "workspace:^", | ||
| "@upstash/ratelimit": "^2.0.1", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| `@unkey/validation` contains various shared schema or validation utils. | ||
|
|
||
| For example user-chosen identifiers. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| { | ||
| "name": "@unkey/validation", | ||
| "version": "1.0.0", | ||
| "description": "", | ||
| "main": "src/index.ts", | ||
| "types": "src/index.ts", | ||
| "keywords": [], | ||
| "author": "Andreas Thomas", | ||
| "license": "AGPL-3.0", | ||
| "devDependencies": { | ||
| "@types/node": "^20.14.9", | ||
| "@unkey/tsconfig": "workspace:*", | ||
| "typescript": "^5.5.3" | ||
| }, | ||
| "dependencies": { | ||
| "zod": "^3.23.5" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,46 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||
| import { z } from "zod"; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||||||||||||||||||
| * An identifier is any string the user gives us to be used as a lookup key. | ||||||||||||||||||||||||||||||||||||||||||||||||
| * It must be URL safe and fit into our database (varchar 256) | ||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||
| const identifier = z | ||||||||||||||||||||||||||||||||||||||||||||||||
| .string() | ||||||||||||||||||||||||||||||||||||||||||||||||
| .min(3) | ||||||||||||||||||||||||||||||||||||||||||||||||
| .max(256) | ||||||||||||||||||||||||||||||||||||||||||||||||
| .regex( | ||||||||||||||||||||||||||||||||||||||||||||||||
| /^[a-zA-Z0-9_\.:\-]*$/, | ||||||||||||||||||||||||||||||||||||||||||||||||
| "Only alphanumeric, underscores, periods, colons and hyphens are allowed", | ||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||
| * A name is a user given human-readable string. | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * It must not be used in URLs. | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @example the name of a key | ||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||
| const name = z.string().min(3).max(256); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+16
to
+23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider adding character restrictions for the name schema. While the documentation states it "must not be used in URLs", there are no character restrictions preventing unsafe characters. Consider adding a regex pattern to enforce safe characters, similar to the identifier schema. -const name = z.string().min(3).max(256);
+const name = z
+ .string()
+ .min(3)
+ .max(256)
+ .regex(
+ /^[^<>{}[\]\\\/]*$/,
+ "Name cannot contain special characters like <, >, {, }, [, ], \\, or /"
+ );📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||
| * A description is a user given human-readable string. | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * It must not be used in URLs. | ||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||
| * @example The description of a permission | ||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||
| const description = z.string().min(3).max(256); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| const unkeyId = z | ||||||||||||||||||||||||||||||||||||||||||||||||
| .string() | ||||||||||||||||||||||||||||||||||||||||||||||||
| .regex( | ||||||||||||||||||||||||||||||||||||||||||||||||
| /^[a-z]{3,4}_[a-zA-Z0-9]{8,}$/, | ||||||||||||||||||||||||||||||||||||||||||||||||
| "Unkey IDs must include a prefix, separated by an underscore: key_abcdefg123", | ||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| export const validation = { | ||||||||||||||||||||||||||||||||||||||||||||||||
| identifier, | ||||||||||||||||||||||||||||||||||||||||||||||||
| name, | ||||||||||||||||||||||||||||||||||||||||||||||||
| description, | ||||||||||||||||||||||||||||||||||||||||||||||||
| unkeyId, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "$schema": "https://json.schemastore.org/tsconfig", | ||
| "extends": "@unkey/tsconfig/base.json", | ||
| "exclude": ["dist"], | ||
| "compilerOptions": { | ||
| "outDir": "dist" | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Validation rules have been relaxed and need adjustment
The previous implementation had stricter validation rules for the role name:
/^[a-zA-Z0-9_:\-\.\*]+$/with specific error messageThe centralized validation should be updated to maintain the same level of strictness for role names to prevent potential security or consistency issues.
internal/validation/src/index.ts: Thenamevalidator should include the regex pattern for role names🔗 Analysis chain
Verify validation rules consistency
The schema now uses centralized validation methods. Let's ensure the validation rules remain consistent with the previous implementation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 1419
Script:
Length of output: 2289
Script:
Length of output: 2012