diff --git a/lib/api/routes/devices.js b/lib/api/routes/devices.js index 9580901..a5b1989 100644 --- a/lib/api/routes/devices.js +++ b/lib/api/routes/devices.js @@ -53,12 +53,14 @@ router.get('/discovered', requireOwner, asyncWrap(async (_req, res) => { })); const macParam = z.object({ mac: z.string().regex(/^[0-9a-f]{2}(:[0-9a-f]{2}){5}$/i) }); +export const iconRef = z.string().regex(/^(set:[a-z0-9-]+:[a-z0-9-]+|brand:[a-z0-9-]+)$/).nullable(); const patchBody = z.object({ name: z.string().max(120).optional(), grp: z.enum(['Smart Home', 'Entertainment', 'Personal', 'Network', 'Flagged']).optional(), status: z.enum(['new', 'known', 'ignored']).optional(), note: z.string().max(500).optional(), - flagged: z.boolean().optional() + flagged: z.boolean().optional(), + icon: iconRef.optional() }); // PATCH /devices/:mac — name / edit / promote (owner). This is "add from discovered". diff --git a/tests/icons/devices_icon.test.js b/tests/icons/devices_icon.test.js new file mode 100644 index 0000000..5e6a436 --- /dev/null +++ b/tests/icons/devices_icon.test.js @@ -0,0 +1,15 @@ +import { describe, it, expect } from 'vitest'; +import { z } from 'zod'; +import { iconRef } from '../../lib/api/routes/devices.js'; + +describe('icon ref validation', () => { + it('accepts set + brand refs and null', () => { + expect(iconRef.safeParse('set:devices:router').success).toBe(true); + expect(iconRef.safeParse('brand:apple').success).toBe(true); + expect(iconRef.safeParse(null).success).toBe(true); + }); + it('rejects junk', () => { + expect(iconRef.safeParse('set:bad').success).toBe(false); + expect(iconRef.safeParse('javascript:alert').success).toBe(false); + }); +});