fix: handle registration keys on headscale 0.29+

Closes HP-555.
This commit is contained in:
Aarnav Tale
2026-07-04 00:07:53 -04:00
parent 990e1e9ff5
commit 948cfad58c
11 changed files with 206 additions and 15 deletions
+14 -3
View File
@@ -12,10 +12,11 @@ import Text from "~/components/text";
import Title from "~/components/title";
import { useForm } from "~/hooks/use-form";
import type { User } from "~/types";
import { normalizeRegistrationKey } from "~/utils/register-key";
import { getUserDisplayName } from "~/utils/user";
const registerSchema = type({
register_key: "string == 24",
register_key: "string > 0",
user: "string > 0",
});
@@ -28,7 +29,16 @@ export interface NewMachineProps {
export default function NewMachine(data: NewMachineProps) {
const [pushDialog, setPushDialog] = useState(false);
const form = useForm({ schema: registerSchema });
const form = useForm({
schema: registerSchema,
validate: (values) =>
normalizeRegistrationKey(String(values.register_key ?? ""))
? undefined
: {
register_key:
"Paste the registration URL or full hskey-authreq-... key from tailscale up.",
},
});
const navigate = useNavigate();
return (
@@ -43,7 +53,8 @@ export default function NewMachine(data: NewMachineProps) {
{...form.field("register_key")}
required
label="Machine Key"
placeholder="AbCd..."
placeholder="hskey-authreq-XXXXXXXXXXXXXXXXXXXXXXXX"
description="Paste the registration URL or full key shown by tailscale up."
/>
<Select
required
+10 -2
View File
@@ -4,6 +4,7 @@ import { authContext, headscaleLiveStoreContext, requestApiContext } from "~/ser
import { isDataWithApiError } from "~/server/headscale/api/error-client";
import { nodesResource } from "~/server/headscale/live-store";
import { Capabilities } from "~/server/web/roles";
import { normalizeRegistrationKey } from "~/utils/register-key";
import type { Route } from "./+types/machine";
@@ -31,13 +32,20 @@ export async function machineAction({ request, context }: Route.ActionArgs) {
});
}
const registrationKey = formData.get("register_key")?.toString();
if (!registrationKey) {
const registrationKeyInput = formData.get("register_key")?.toString();
if (!registrationKeyInput) {
throw data("Missing `register_key` in the form data.", {
status: 400,
});
}
const registrationKey = normalizeRegistrationKey(registrationKeyInput);
if (!registrationKey) {
throw data("Invalid `register_key` in the form data.", {
status: 400,
});
}
const user = formData.get("user")?.toString();
if (!user) {
throw data("Missing `user` in the form data.", {