feat(devices): PATCH accepts icon ref
Export reusable iconRef zod validator (set:<set>:<name> | brand:<slug> | null) and add it as an optional field to patchBody so PATCH /devices/:mac accepts icon. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -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) });
|
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({
|
const patchBody = z.object({
|
||||||
name: z.string().max(120).optional(),
|
name: z.string().max(120).optional(),
|
||||||
grp: z.enum(['Smart Home', 'Entertainment', 'Personal', 'Network', 'Flagged']).optional(),
|
grp: z.enum(['Smart Home', 'Entertainment', 'Personal', 'Network', 'Flagged']).optional(),
|
||||||
status: z.enum(['new', 'known', 'ignored']).optional(),
|
status: z.enum(['new', 'known', 'ignored']).optional(),
|
||||||
note: z.string().max(500).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".
|
// PATCH /devices/:mac — name / edit / promote (owner). This is "add from discovered".
|
||||||
|
|||||||
15
tests/icons/devices_icon.test.js
Normal file
15
tests/icons/devices_icon.test.js
Normal file
@@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user