mirror of
https://github.com/tale/headplane.git
synced 2026-08-20 09:52:19 +00:00
fix(ui): submit raw number input value for auth key expiry (#609)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,8 +21,13 @@ export default function NumberInput(props: NumberInputProps) {
|
||||
const { label, name, description } = props;
|
||||
|
||||
return (
|
||||
// `name` belongs on the Root, not the Input. The Input is a text field that
|
||||
// holds the locale-formatted value ("365,000", "365 000", "365.000"), while
|
||||
// the Root renders a hidden number input carrying the raw value. Naming the
|
||||
// Input would submit the formatted string and break server-side parsing.
|
||||
<NumberField.Root
|
||||
className="flex flex-col gap-1"
|
||||
name={name}
|
||||
defaultValue={props.defaultValue}
|
||||
value={props.value}
|
||||
onValueChange={props.onValueChange}
|
||||
@@ -49,10 +54,7 @@ export default function NumberInput(props: NumberInputProps) {
|
||||
"border border-mist-200 dark:border-mist-800",
|
||||
)}
|
||||
>
|
||||
<NumberField.Input
|
||||
name={name}
|
||||
className="w-full rounded-l-md bg-transparent py-2 pl-3 text-sm focus:outline-hidden"
|
||||
/>
|
||||
<NumberField.Input className="w-full rounded-l-md bg-transparent py-2 pl-3 text-sm focus:outline-hidden" />
|
||||
<NumberField.Decrement aria-label="Decrement" className="h-7.5 w-7.5 rounded-lg p-1">
|
||||
<Minus className="h-4 w-4" />
|
||||
</NumberField.Decrement>
|
||||
|
||||
@@ -88,10 +88,21 @@ export async function authKeysAction({ request, context }: Route.ActionArgs) {
|
||||
});
|
||||
}
|
||||
|
||||
const day = Number(expiry.toString().split(" ")[0]);
|
||||
// The form submits the raw, unformatted value of the number input, so
|
||||
// anything that is not a plain integer (grouping separators from
|
||||
// `Intl.NumberFormat`, unit suffixes, ...) is malformed input. Parsing it
|
||||
// leniently either produces an Invalid Date (500) or, for dot-grouping
|
||||
// locales, a silently truncated expiry.
|
||||
const day = /^\d+$/.test(expiry.trim()) ? Number(expiry.trim()) : Number.NaN;
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() + day);
|
||||
|
||||
if (day < 1 || Number.isNaN(date.getTime())) {
|
||||
return data("`expiry` must be a whole number of days.", {
|
||||
status: 400,
|
||||
});
|
||||
}
|
||||
|
||||
const key = await api.preAuthKeys.create({
|
||||
user,
|
||||
ephemeral: ephemeral === "on",
|
||||
|
||||
Reference in New Issue
Block a user