feat(backend): Update routes to use machine_id for host identification

- Auto-enrollment endpoints now require and validate machine_id
- Check for duplicates by machine_id instead of friendly_name
- Added /hosts/check-machine-id endpoint for agent installer
- Bulk enrollment updated to handle machine_id
- Multiple hosts with same hostname now supported
This commit is contained in:
Muhammad Ibrahim
2025-10-04 09:04:35 +01:00
parent 811930d1e2
commit b25bba50a7
2 changed files with 67 additions and 8 deletions

View File

@@ -521,6 +521,9 @@ router.post(
body("friendly_name")
.isLength({ min: 1, max: 255 })
.withMessage("Friendly name is required"),
body("machine_id")
.isLength({ min: 1, max: 255 })
.withMessage("Machine ID is required"),
body("metadata").optional().isObject(),
],
async (req, res) => {
@@ -530,15 +533,15 @@ router.post(
return res.status(400).json({ errors: errors.array() });
}
const { friendly_name } = req.body;
const { friendly_name, machine_id } = req.body;
// Generate host API credentials
const api_id = `patchmon_${crypto.randomBytes(8).toString("hex")}`;
const api_key = crypto.randomBytes(32).toString("hex");
// Check if host already exists
// Check if host already exists by machine_id (not hostname)
const existing_host = await prisma.hosts.findUnique({
where: { friendly_name },
where: { machine_id },
});
if (existing_host) {
@@ -546,7 +549,10 @@ router.post(
error: "Host already exists",
host_id: existing_host.id,
api_id: existing_host.api_id,
message: "This host is already enrolled in PatchMon",
machine_id: existing_host.machine_id,
friendly_name: existing_host.friendly_name,
message:
"This machine is already enrolled in PatchMon (matched by machine ID)",
});
}
@@ -554,6 +560,7 @@ router.post(
const host = await prisma.hosts.create({
data: {
id: uuidv4(),
machine_id,
friendly_name,
os_type: "unknown",
os_version: "unknown",
@@ -648,17 +655,26 @@ router.post(
for (const host_data of hosts) {
try {
const { friendly_name } = host_data;
const { friendly_name, machine_id } = host_data;
// Check if host already exists
if (!machine_id) {
results.failed.push({
friendly_name,
error: "Machine ID is required",
});
continue;
}
// Check if host already exists by machine_id
const existing_host = await prisma.hosts.findUnique({
where: { friendly_name },
where: { machine_id },
});
if (existing_host) {
results.skipped.push({
friendly_name,
reason: "Already exists",
machine_id,
reason: "Machine already enrolled",
api_id: existing_host.api_id,
});
continue;
@@ -672,6 +688,7 @@ router.post(
const host = await prisma.hosts.create({
data: {
id: uuidv4(),
machine_id,
friendly_name,
os_type: "unknown",
os_version: "unknown",

View File

@@ -1151,6 +1151,48 @@ export CURL_FLAGS="${curlFlags}"
}
});
// Check if machine_id already exists (requires auth)
router.post("/check-machine-id", validateApiCredentials, async (req, res) => {
try {
const { machine_id } = req.body;
if (!machine_id) {
return res.status(400).json({
error: "machine_id is required",
});
}
// Check if a host with this machine_id exists
const existing_host = await prisma.hosts.findUnique({
where: { machine_id },
select: {
id: true,
friendly_name: true,
machine_id: true,
api_id: true,
status: true,
created_at: true,
},
});
if (existing_host) {
return res.status(200).json({
exists: true,
host: existing_host,
message: "This machine is already enrolled",
});
}
return res.status(200).json({
exists: false,
message: "Machine not yet enrolled",
});
} catch (error) {
console.error("Error checking machine_id:", error);
res.status(500).json({ error: "Failed to check machine_id" });
}
});
// Serve the removal script (public endpoint - no authentication required)
router.get("/remove", async (_req, res) => {
try {