diff --git a/CHANGELOG.md b/CHANGELOG.md index 239aa42..b0b76c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - The machine actions backend has been reworked to better handle errors and provide more information to the user (closes [#185](https://github.com/tale/headplane/issues/185)). - Machine tags now show states when waiting for subnet or exit node approval and when expiry is disabled. - Expiry status on the UI was incorrectly showing as never due to changes in the Headscale API. +- Added validation for machine renaming to prevent invalid submissions (closes [#192](https://github.com/tale/headplane/issues/192)). ### 0.5.10 (April 4, 2025) - Fix an issue where other preferences to skip onboarding affected every user. diff --git a/app/components/Input.tsx b/app/components/Input.tsx index 54cb64f..3e94ee5 100644 --- a/app/components/Input.tsx +++ b/app/components/Input.tsx @@ -71,14 +71,14 @@ export default function Input(props: InputProps) { {props.description} )} - {isInvalid && ( + {isInvalid ? (
{validationErrors.join(' ')}
- )} + ) : null} ); } diff --git a/app/routes/machines/dialogs/rename.tsx b/app/routes/machines/dialogs/rename.tsx index 4a05e4a..f3f08a1 100644 --- a/app/routes/machines/dialogs/rename.tsx +++ b/app/routes/machines/dialogs/rename.tsx @@ -30,11 +30,42 @@ export default function Rename({ { + if (value.length === 0) { + return 'Cannot be empty'; + } + + // DNS hostname validation + if (value.toLowerCase() !== value) { + return 'Cannot contain uppercase letters'; + } + + if (value.length > 63) { + return 'DNS hostnames cannot be 64+ characters'; + } + + // Test for invalid characters + if (!/^[a-z0-9-]+$/.test(value)) { + return 'Cannot contain special characters'; + } + + // Test for leading/trailing hyphens + if (value.startsWith('-') || value.endsWith('-')) { + return 'Cannot start or end with a hyphen'; + } + + // Test for consecutive hyphens + if (value.includes('--')) { + return 'Cannot contain consecutive hyphens'; + } + }} /> {magic ? ( name.length > 0 && name !== machine.givenName ? (