hex values checking before insert into database

This commit is contained in:
Nate Kelley 2025-07-17 12:14:58 -06:00
parent ee8cce71f8
commit 7b24d167b9
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
4 changed files with 73 additions and 25 deletions

View File

@ -8,6 +8,7 @@ import { UpdateOrganizationRequestSchema } from '@buster/server-shared/organizat
import { zValidator } from '@hono/zod-validator';
import { Hono } from 'hono';
import { HTTPException } from 'hono/http-exception';
import { z } from 'zod';
import { requireOrganizationAdmin } from '../../../middleware/auth';
/**
@ -21,7 +22,6 @@ async function updateOrganizationHandler(
): Promise<UpdateOrganizationResponse> {
try {
// Update the organization
await updateOrganization({
organizationId,
...request,
@ -41,6 +41,11 @@ async function updateOrganizationHandler(
error: error instanceof Error ? error.message : error,
});
// Re-throw Zod errors to be handled by the route error handler
if (error instanceof z.ZodError) {
throw error;
}
throw new HTTPException(500, {
message: 'Failed to update organization',
});
@ -51,31 +56,53 @@ async function updateOrganizationHandler(
const app = new Hono()
.use('*', requireOrganizationAdmin)
.put('/', zValidator('json', UpdateOrganizationRequestSchema), async (c) => {
const request = await c.req.valid('json');
const request = c.req.valid('json');
const user = c.get('busterUser');
const userOrg = c.get('userOrganizationInfo');
const organizationId = userOrg.organizationId;
try {
const response: UpdateOrganizationResponse = await updateOrganizationHandler(
organizationId,
request,
user
);
return c.json(response);
} catch (error) {
console.error('Error in updateOrganizationHandler:', {
organizationId,
userId: user.id,
requestFields: Object.keys(request),
error: error instanceof Error ? error.message : error,
});
const response: UpdateOrganizationResponse = await updateOrganizationHandler(
organizationId,
request,
user
);
throw new HTTPException(500, {
message: 'Failed to update organization',
});
return c.json(response);
})
.onError((e, c) => {
// Handle Zod validation errors with detailed information
if (e instanceof z.ZodError) {
return c.json(
{
error: 'Validation Error',
message: 'Invalid request data',
issues: e.issues.map((issue) => ({
path: issue.path.join('.'),
message: issue.message,
code: issue.code,
})),
},
400
);
}
// Handle HTTP exceptions
if (e instanceof HTTPException) {
return e.getResponse();
}
// Log unexpected errors
console.error('Unhandled error in organization PUT:', e);
// Return generic error for unexpected issues
return c.json(
{
error: 'Internal Server Error',
message: 'Failed to update organization',
},
500
);
});
export default app;

View File

@ -4,16 +4,37 @@ import { db } from '../../connection';
import { organizations } from '../../schema';
import type { OrganizationColorPalettes } from '../../schema-types';
// Hex color validation schema for 3 or 6 digit hex codes
const HexColorSchema = z
.string()
.regex(
/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/,
'Must be a valid 3 or 6 digit hex color code (e.g., #fff or #ffffff)'
);
// Organization Color Palette schema
const OrganizationColorPaletteSchema = z.object({
id: z.string(),
colors: z.array(z.string()),
id: z.string().or(z.number()),
colors: z.array(HexColorSchema),
});
// Input validation schema
const UpdateOrganizationInputSchema = z.object({
organizationId: z.string().uuid('Organization ID must be a valid UUID'),
organizationColorPalettes: z.array(OrganizationColorPaletteSchema).optional(),
organizationColorPalettes: z
.array(OrganizationColorPaletteSchema)
.optional()
.refine(
(palettes) => {
if (!palettes || palettes.length === 0) return true;
const ids = palettes.map((palette) => palette.id);
const uniqueIds = new Set(ids);
return ids.length === uniqueIds.size;
},
{
message: 'All color palette IDs must be unique',
}
),
});
type UpdateOrganizationInput = z.infer<typeof UpdateOrganizationInputSchema>;

View File

@ -1,7 +1,7 @@
// Organization Color Palette Types
export type OrganizationColorPalette = {
id: string;
colors: string[];
id: string | number;
colors: string[]; // Hex color codes
};
export type OrganizationColorPalettes = OrganizationColorPalette[];

View File

@ -12,7 +12,7 @@ const HexColorSchema = z
);
export const OrganizationColorPaletteSchema = z.object({
id: z.string(),
id: z.string().or(z.number()),
colors: z.array(HexColorSchema).min(1).max(25),
});