mirror of https://github.com/buster-so/buster.git
hex values checking before insert into database
This commit is contained in:
parent
ee8cce71f8
commit
7b24d167b9
|
@ -8,6 +8,7 @@ import { UpdateOrganizationRequestSchema } from '@buster/server-shared/organizat
|
||||||
import { zValidator } from '@hono/zod-validator';
|
import { zValidator } from '@hono/zod-validator';
|
||||||
import { Hono } from 'hono';
|
import { Hono } from 'hono';
|
||||||
import { HTTPException } from 'hono/http-exception';
|
import { HTTPException } from 'hono/http-exception';
|
||||||
|
import { z } from 'zod';
|
||||||
import { requireOrganizationAdmin } from '../../../middleware/auth';
|
import { requireOrganizationAdmin } from '../../../middleware/auth';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,7 +22,6 @@ async function updateOrganizationHandler(
|
||||||
): Promise<UpdateOrganizationResponse> {
|
): Promise<UpdateOrganizationResponse> {
|
||||||
try {
|
try {
|
||||||
// Update the organization
|
// Update the organization
|
||||||
|
|
||||||
await updateOrganization({
|
await updateOrganization({
|
||||||
organizationId,
|
organizationId,
|
||||||
...request,
|
...request,
|
||||||
|
@ -41,6 +41,11 @@ async function updateOrganizationHandler(
|
||||||
error: error instanceof Error ? error.message : error,
|
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, {
|
throw new HTTPException(500, {
|
||||||
message: 'Failed to update organization',
|
message: 'Failed to update organization',
|
||||||
});
|
});
|
||||||
|
@ -51,31 +56,53 @@ async function updateOrganizationHandler(
|
||||||
const app = new Hono()
|
const app = new Hono()
|
||||||
.use('*', requireOrganizationAdmin)
|
.use('*', requireOrganizationAdmin)
|
||||||
.put('/', zValidator('json', UpdateOrganizationRequestSchema), async (c) => {
|
.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 user = c.get('busterUser');
|
||||||
const userOrg = c.get('userOrganizationInfo');
|
const userOrg = c.get('userOrganizationInfo');
|
||||||
|
|
||||||
const organizationId = userOrg.organizationId;
|
const organizationId = userOrg.organizationId;
|
||||||
|
|
||||||
try {
|
const response: UpdateOrganizationResponse = await updateOrganizationHandler(
|
||||||
const response: UpdateOrganizationResponse = await updateOrganizationHandler(
|
organizationId,
|
||||||
organizationId,
|
request,
|
||||||
request,
|
user
|
||||||
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,
|
|
||||||
});
|
|
||||||
|
|
||||||
throw new HTTPException(500, {
|
return c.json(response);
|
||||||
message: 'Failed to update organization',
|
})
|
||||||
});
|
.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;
|
export default app;
|
||||||
|
|
|
@ -4,16 +4,37 @@ import { db } from '../../connection';
|
||||||
import { organizations } from '../../schema';
|
import { organizations } from '../../schema';
|
||||||
import type { OrganizationColorPalettes } from '../../schema-types';
|
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
|
// Organization Color Palette schema
|
||||||
const OrganizationColorPaletteSchema = z.object({
|
const OrganizationColorPaletteSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string().or(z.number()),
|
||||||
colors: z.array(z.string()),
|
colors: z.array(HexColorSchema),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Input validation schema
|
// Input validation schema
|
||||||
const UpdateOrganizationInputSchema = z.object({
|
const UpdateOrganizationInputSchema = z.object({
|
||||||
organizationId: z.string().uuid('Organization ID must be a valid UUID'),
|
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>;
|
type UpdateOrganizationInput = z.infer<typeof UpdateOrganizationInputSchema>;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Organization Color Palette Types
|
// Organization Color Palette Types
|
||||||
export type OrganizationColorPalette = {
|
export type OrganizationColorPalette = {
|
||||||
id: string;
|
id: string | number;
|
||||||
colors: string[];
|
colors: string[]; // Hex color codes
|
||||||
};
|
};
|
||||||
|
|
||||||
export type OrganizationColorPalettes = OrganizationColorPalette[];
|
export type OrganizationColorPalettes = OrganizationColorPalette[];
|
||||||
|
|
|
@ -12,7 +12,7 @@ const HexColorSchema = z
|
||||||
);
|
);
|
||||||
|
|
||||||
export const OrganizationColorPaletteSchema = z.object({
|
export const OrganizationColorPaletteSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string().or(z.number()),
|
||||||
colors: z.array(HexColorSchema).min(1).max(25),
|
colors: z.array(HexColorSchema).min(1).max(25),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue