mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 06:06:10 +00:00
fix(auth): validate User.timezone against IANA zone list on profile update
The shared profile-update schema accepted any 1-64 character string
for the timezone field and persisted it directly into User.timezone.
Downstream callers — most notably the v1.4.38 dashboard summary route
— pass the raw stored value into postgres via
`to_char(measured_at AT TIME ZONE ${userTz})`, which hard-fails with
`invalid_parameter_value` for any unknown zone. Before v1.4.38 the
field was consumed only through the defensive isValidTimezone wrapper
in @/lib/tz/format and silently fell back to Europe/Berlin, so the
gap was latent; the new SQL path made it a self-DoS regression on any
account that ever wrote a junk zone.
Chains the existing isValidTimezone helper into the Zod schema as a
refine so the API now returns 422 "Invalid IANA timezone" at the
write boundary instead of writing junk and failing on read.
This commit is contained in:
1 parent
679fcd2d08
commit
24379721d1
1 file changed
+7
-1
@@ -6,12 +6,18 @@
|
||||
import { prisma } from "@/lib/db";
|
||||
import { auditLog } from "@/lib/auth/audit";
|
||||
import { profileSchema } from "@/lib/validations/auth";
|
||||
import { isValidTimezone } from "@/lib/tz/format";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
const extendedProfileSchema = profileSchema.extend({
|
||||
displayName: z.string().min(1).max(80).nullable().optional(),
|
||||
locale: z.enum(["de", "en"]).nullable().optional(),
|
||||
timezone: z.string().min(1).max(64).optional(),
|
||||
timezone: z
|
||||
.string()
|
||||
.min(1)
|
||||
.max(64)
|
||||
.refine(isValidTimezone, "Invalid IANA timezone")
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export type ApplyProfileInput = z.infer<typeof extendedProfileSchema>;
|
||||
|
||||
Reference in new issue
Block a user